diff options
author | Anton Khirnov <anton@khirnov.net> | 2019-01-26 12:07:27 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2019-01-26 15:31:06 +0100 |
commit | 042257840fd26ad8d4dd8f304ad1adf06d6b50b4 (patch) | |
tree | 72b19ca211306af3610173096a87c638226a3d10 /mg2d.c | |
parent | d519d82a3e4b32944b77b1ae26cfefa45ec29d71 (diff) |
Solve the discretized system exactly on the coarsest level.
Diffstat (limited to 'mg2d.c')
-rw-r--r-- | mg2d.c | 35 |
1 files changed, 23 insertions, 12 deletions
@@ -297,12 +297,9 @@ static int mg_solve_subgrid(MG2DContext *ctx, MG2DLevel *level) /* handle coarsest grid */ if (!level->child) { - - for (int j = 0; j < 16; j++) { - ret = mg_relax_step(ctx, level, "coarse-step"); - if (ret < 0) - return ret; - } + ret = mg_relax_step(ctx, level, "coarse-step"); + if (ret < 0) + return ret; level->count_cycles++; goto finish; @@ -553,7 +550,7 @@ static void mg_level_free(MG2DLevel **plevel) *plevel = NULL; } -static MG2DLevel *mg_level_alloc(const size_t domain_size) +static MG2DLevel *mg_level_alloc(enum EGSType type, const size_t domain_size) { MG2DLevel *level; int ret; @@ -567,7 +564,7 @@ static MG2DLevel *mg_level_alloc(const size_t domain_size) goto fail; level->prolong_tmp_stride = domain_size + 1; - level->solver = mg2di_egs_alloc(EGS_SOLVER_RELAXATION, + level->solver = mg2di_egs_alloc(type, (size_t [2]){domain_size, domain_size}); if (!level->solver) goto fail; @@ -591,9 +588,11 @@ static int log2i(int n) static int mg_levels_alloc(MG2DContext *ctx, size_t domain_size) { MG2DInternal *priv = ctx->priv; - MG2DLevel *cur; + MG2DLevel *cur, **last; + size_t last_size; + unsigned int last_depth; - priv->root = mg_level_alloc(domain_size); + priv->root = mg_level_alloc(EGS_SOLVER_RELAXATION, domain_size); if (!priv->root) return -ENOMEM; @@ -601,14 +600,14 @@ static int mg_levels_alloc(MG2DContext *ctx, size_t domain_size) // the children all have sizes 2**n + 1 // but we skip the closest lower one if it is too close if (domain_size <= 2) - return 0; + goto finish; domain_size = (1 << log2i(domain_size - 2)) + 1; if ((double)priv->root->solver->domain_size[0] / domain_size < 1.5) domain_size = (domain_size >> 1) + 1; cur = priv->root; for (int i = 0; i < LEVELS_MAX && domain_size > 4; i++) { - cur->child = mg_level_alloc(domain_size); + cur->child = mg_level_alloc(EGS_SOLVER_RELAXATION, domain_size); if (!cur->child) return -ENOMEM; cur->child->depth = i + 1; @@ -617,6 +616,18 @@ static int mg_levels_alloc(MG2DContext *ctx, size_t domain_size) domain_size = (domain_size >> 1) + 1; } +finish: + last = &priv->root; + while ((*last)->child) + last = &((*last)->child); + last_size = (*last)->solver->domain_size[0]; + last_depth = (*last)->depth; + mg_level_free(last); + *last = mg_level_alloc(EGS_SOLVER_EXACT, last_size); + if (!*last) + return -ENOMEM; + (*last)->depth = last_depth; + return 0; } |