Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Newly adapted quadrants in wrap #310

Merged
merged 13 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/p4est_to_p8est.h
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,6 @@
#define p4est_wrap_destroy p8est_wrap_destroy
#define p4est_wrap_set_hollow p8est_wrap_set_hollow
#define p4est_wrap_set_coarsen_delay p8est_wrap_set_coarsen_delay
#define p4est_wrap_set_partitioning p8est_wrap_set_partitioning
#define p4est_wrap_get_ghost p8est_wrap_get_ghost
#define p4est_wrap_get_mesh p8est_wrap_get_mesh
#define p4est_wrap_mark_refine p8est_wrap_mark_refine
Expand Down
112 changes: 104 additions & 8 deletions src/p4est_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ p4est_wrap_params_init (p4est_wrap_params_t *params)
params->coarsen_delay = 0;
params->coarsen_affect = 0;
params->partition_for_coarsening = 1;
params->store_adapted = 0;
params->user_pointer = NULL;
}

Expand Down Expand Up @@ -300,7 +301,7 @@ p4est_wrap_new_copy (p4est_wrap_t * source, size_t data_size,

pp = P4EST_ALLOC_ZERO (p4est_wrap_t, 1);

/* copy the sources wrap paramters; however the copy will is hollow */
/* copy the sources wrap parameters; however the copy is hollow */
pp->params = source->params;
pp->params.hollow = 1;

Expand All @@ -319,6 +320,24 @@ p4est_wrap_new_copy (p4est_wrap_t * source, size_t data_size,
p4est_reset_data (pp->p4est, data_size, NULL, NULL);
}

/* copy newly_adapted arrays if set */
P4EST_ASSERT ((source->newly_refined == NULL) ==
(source->newly_coarsened == NULL));
if (source->newly_refined != NULL) {
P4EST_ASSERT (source->newly_refined->elem_size ==
sizeof (p4est_locidx_t));
P4EST_ASSERT (source->newly_coarsened->elem_size ==
sizeof (p4est_locidx_t));
pp->newly_refined =
sc_array_new_count (sizeof (p4est_locidx_t),
source->newly_refined->elem_count);
sc_array_copy (pp->newly_refined, source->newly_refined);
pp->newly_coarsened =
sc_array_new_count (sizeof (p4est_locidx_t),
source->newly_coarsened->elem_count);
sc_array_copy (pp->newly_coarsened, source->newly_coarsened);
}

pp->weight_exponent = 0; /* keep this even though using ALLOC_ZERO */

pp->p4est->user_pointer = pp;
Expand Down Expand Up @@ -462,6 +481,14 @@ p4est_wrap_destroy (p4est_wrap_t * pp)
p4est_ghost_destroy (pp->ghost);
}

P4EST_ASSERT ((pp->newly_refined == NULL) == (pp->newly_coarsened == NULL));
if (pp->newly_refined != NULL) {
P4EST_ASSERT (pp->newly_refined->elem_size == sizeof (p4est_locidx_t));
P4EST_ASSERT (pp->newly_coarsened->elem_size == sizeof (p4est_locidx_t));
sc_array_destroy (pp->newly_refined);
sc_array_destroy (pp->newly_coarsened);
}

P4EST_FREE (pp->flags);
P4EST_FREE (pp->temp_flags);

Expand Down Expand Up @@ -558,13 +585,6 @@ p4est_wrap_set_coarsen_delay (p4est_wrap_t * pp,
}
}

void
p4est_wrap_set_partitioning (p4est_wrap_t *pp, int partition_for_coarsening)
{
P4EST_ASSERT (pp != NULL);
pp->params.partition_for_coarsening = partition_for_coarsening;
}

p4est_ghost_t *
p4est_wrap_get_ghost (p4est_wrap_t * pp)
{
Expand Down Expand Up @@ -646,6 +666,14 @@ p4est_wrap_adapt (p4est_wrap_t * pp)
p4est_gloidx_t global_num, global_num_entry;
unsigned checksum_entry, checksum_exit;
p4est_t *p4est = pp->p4est;
sc_array_t *quad_levels;
int8_t *level;
size_t qz, zz;
p4est_topidx_t tt;
p4est_tree_t *tree;
sc_array_t *tquadrants;
p4est_quadrant_t *quadrant;
p4est_locidx_t *lqid;

P4EST_ASSERT (!pp->params.hollow);
P4EST_ASSERT (pp->params.coarsen_delay >= 0);
Expand All @@ -660,6 +688,27 @@ p4est_wrap_adapt (p4est_wrap_t * pp)
P4EST_ASSERT (pp->num_refine_flags >= 0 &&
pp->num_refine_flags <= p4est->local_num_quadrants);

quad_levels = sc_array_new (sizeof (int8_t));
if (pp->params.store_adapted) {
P4EST_ASSERT (p4est_is_balanced
(pp->p4est, pp->params.mesh_params.btype));

/* store quadrant levels to compare with future adapted version */
sc_array_resize (quad_levels, p4est->local_num_quadrants);

/* iterate over p4est and store leaf levels */
for (tt = p4est->first_local_tree, qz = 0; tt <= p4est->last_local_tree;
++tt) {
tree = p4est_tree_array_index (p4est->trees, tt);
tquadrants = &tree->quadrants;
for (zz = 0; zz < tquadrants->elem_count; ++zz, ++qz) {
level = (int8_t *) sc_array_index (quad_levels, qz);
quadrant = p4est_quadrant_array_index (tquadrants, zz);
*level = quadrant->level;
}
}
}

/* This allocation is optimistic when not all refine requests are honored */
pp->temp_flags = P4EST_ALLOC_ZERO (uint8_t, p4est->local_num_quadrants +
(P4EST_CHILDREN - 1) *
Expand Down Expand Up @@ -740,6 +789,53 @@ p4est_wrap_adapt (p4est_wrap_t * pp)
#endif
pp->num_refine_flags = 0;

/* update newly_adapted arrays */
P4EST_ASSERT ((pp->newly_refined == NULL) == (pp->newly_coarsened == NULL));
if (pp->newly_refined != NULL) {
/* delete previous newly_adapted arrays, if there are any */
sc_array_destroy_null (&pp->newly_refined);
sc_array_destroy_null (&pp->newly_coarsened);
}
if (pp->params.store_adapted) {
pp->newly_refined = sc_array_new (sizeof (p4est_locidx_t));
pp->newly_coarsened = sc_array_new (sizeof (p4est_locidx_t));

for (tt = p4est->first_local_tree, qz = 0; tt <= p4est->last_local_tree;
++tt) {
/* refine, coarsen and balance does not affect the range of local trees */
tree = p4est_tree_array_index (p4est->trees, tt);
tquadrants = &tree->quadrants;
for (zz = 0; zz < tquadrants->elem_count;) {
quadrant = p4est_quadrant_array_index (tquadrants, zz);
level = (int8_t *) sc_array_index (quad_levels, qz);

/* compare levels to identify adaptation */
if (quadrant->level > *level) {
/* quadrant was newly refined, store its index in the new p4est */
lqid = (p4est_locidx_t *) sc_array_push (pp->newly_refined);
*lqid = (p4est_locidx_t) zz;
zz += P4EST_CHILDREN;
qz++;
}
else if (quadrant->level < *level) {
/* quadrant was newly coarsened, store its index in the new p4est */
lqid = (p4est_locidx_t *) sc_array_push (pp->newly_coarsened);
*lqid = (p4est_locidx_t) zz;
zz++;
qz += P4EST_CHILDREN;
}
else {
/* quadrant was not newly adapted */
zz++;
qz++;
}
}
P4EST_ASSERT (zz == tquadrants->elem_count);
}
P4EST_ASSERT (qz == quad_levels->elem_count);
}
sc_array_destroy (quad_levels);

return changed;
}

Expand Down
34 changes: 19 additions & 15 deletions src/p4est_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ typedef struct
modified to allow one level
of coarsening when calling
\ref p4est_wrap_partition. */
int store_adapted; /**< Boolean: If true, the indices of
most recently adapted quadrants are
stored in the \ref newly_refined
and \ref newly_coarsened array of
the wrap. */
void *user_pointer; /**< Set the user pointer in
\ref p4est_wrap_t. Subsequently, we
will never access it. */
Expand Down Expand Up @@ -102,6 +107,20 @@ typedef struct p4est_wrap
int p4est_children;
p4est_t *p4est; /**< p4est->user_pointer is used internally */

/* If \a params.store_adapted is true, these arrays store the indices of the
* quadrants refined and coarsened during the most recent call to
* \ref p4est_wrap_adapt. The wrap's \a p4est has to be balanced when entering
* the adaptation, to avoid multi-level refinement.
* The arrays are allocated during the first call of \ref p4est_wrap_adapt.
* At every time the arrays index into the local quadrants of the p4est as it
* was directly after completion of \ref p4est_wrap_adapt. So, they are not
* updated in \ref p4est_wrap_partition. Newly_refined only stores newly
* refined quadrants with child id 0. */
sc_array_t *newly_refined; /**< Indices of quadrants refined during
most recent \ref p4est_wrap_adapt */
sc_array_t *newly_coarsened; /**< Indices of quadrants coarsened during
most recent \ref p4est_wrap_adapt */

/* anything below here is considered private und should not be touched */
int weight_exponent;
uint8_t *flags, *temp_flags;
Expand Down Expand Up @@ -286,21 +305,6 @@ void p4est_wrap_set_coarsen_delay (p4est_wrap_t * pp,
int coarsen_delay,
int coarsen_affect);

/** Set a parameter that ensures future partitions allow one level of coarsening.
* The partition_for_coarsening parameter is passed to \ref p4est_partition_ext
* in \ref p4est_wrap_partition.
* If not zero, all future calls to \ref p4est_wrap_partition will partition
* in a manner that allows one level of coarsening. This function does not
* automatically repartition the mesh, when switching partition_for_coarsening
* to a non-zero value.
* \param [in,out] pp A valid p4est_wrap structure.
* \param [in] partition_for_coarsening Boolean: If true, all future partitions
* of the wrap allow one level of coarsening.
* Suggested default: 1.
*/
void p4est_wrap_set_partitioning (p4est_wrap_t *pp,
int partition_for_coarsening);

/** Return the appropriate ghost layer.
* This function is necessary since two versions may exist simultaneously
* after refinement and before partition/complete.
Expand Down
34 changes: 19 additions & 15 deletions src/p8est_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ typedef struct
modified to allow one level
of coarsening when calling
\ref p8est_wrap_partition. */
int store_adapted; /**< Boolean: If true, the indices of
most recently adapted quadrants are
stored in the \ref newly_refined
and \ref newly_coarsened array of
the wrap. */
void *user_pointer; /**< Set the user pointer in
\ref p8est_wrap_t. Subsequently, we
will never access it. */
Expand Down Expand Up @@ -102,6 +107,20 @@ typedef struct p8est_wrap
int p4est_children;
p8est_t *p4est; /**< p4est->user_pointer is used internally */

/* If \a params.store_adapted is true, these arrays store the indices of the
* quadrants refined and coarsened during the most recent call to
* \ref p8est_wrap_adapt. The wrap's \a p4est has to be balanced when entering
* the adaptation, to avoid multi-level refinement.
* The arrays are allocated during the first call of \ref p8est_wrap_adapt.
* At every time the arrays index into the local quadrants of the p8est as it
* was directly after completion of \ref p8est_wrap_adapt. So, they are not
* updated in \ref p8est_wrap_partition. Newly_refined only stores newly
* refined quadrants with child id 0. */
sc_array_t *newly_refined; /**< Indices of quadrants refined during
most recent \ref p8est_wrap_adapt */
sc_array_t *newly_coarsened; /**< Indices of quadrants coarsened during
most recent \ref p8est_wrap_adapt */

/* anything below here is considered private und should not be touched */
int weight_exponent;
uint8_t *flags, *temp_flags;
Expand Down Expand Up @@ -271,21 +290,6 @@ void p8est_wrap_set_coarsen_delay (p8est_wrap_t * pp,
int coarsen_delay,
int coarsen_affect);

/** Set a parameter that ensures future partitions allow one level of coarsening.
* The partition_for_coarsening parameter is passed to \ref p8est_partition_ext
* in \ref p8est_wrap_partition.
* If not zero, all future calls to \ref p8est_wrap_partition will partition
* in a manner that allows one level of coarsening. This function does not
* automatically repartition the mesh, when switching partition_for_coarsening
* to a non-zero value.
* \param [in,out] pp A valid p8est_wrap structure.
* \param [in] partition_for_coarsening Boolean: If true, all future partitions
* of the wrap allow one level of coarsening.
* Suggested default: 1.
*/
void p8est_wrap_set_partitioning (p8est_wrap_t *pp,
int partition_for_coarsening);

/** Return the appropriate ghost layer.
* This function is necessary since two versions may exist simultaneously
* after refinement and before partition/complete.
Expand Down