From 8f3f595d977eb7174b29dc61583fac2d1149a199 Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Wed, 12 Apr 2023 18:21:36 +0200 Subject: [PATCH 1/9] add p4est_comm_is_empty_gfx --- src/p4est_communication.c | 15 +++++++++++++++ src/p4est_communication.h | 17 +++++++++++++++++ src/p4est_to_p8est.h | 1 + src/p8est_communication.h | 15 +++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/src/p4est_communication.c b/src/p4est_communication.c index 27fe8c349..4829b3856 100644 --- a/src/p4est_communication.c +++ b/src/p4est_communication.c @@ -595,6 +595,21 @@ p4est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int num_procs, int p) return gfq[p] == gfq[p + 1]; } +int +p4est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, const p4est_quadrant_t *gfp, + int num_procs, int p) +{ + P4EST_ASSERT (0 <= p && p < num_procs); + P4EST_ASSERT (gfp != NULL); + + if (gfq) { + return gfq[p] == gfq[p + 1]; + } + else { + return p4est_quadrant_is_equal_piggy (&gfp[p], &gfp[p + 1]); + } +} + int p4est_comm_is_contained (p4est_t * p4est, p4est_locidx_t which_tree, const p4est_quadrant_t * q, int rank) diff --git a/src/p4est_communication.h b/src/p4est_communication.h index 08e51e68d..927bf73c0 100644 --- a/src/p4est_communication.h +++ b/src/p4est_communication.h @@ -161,6 +161,23 @@ int p4est_comm_is_empty (p4est_t *p4est, int p); int p4est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int num_procs, int p); + +/** Query whether a processor has no quadrants. + * If gfq == NULL, the function uses p4est_quadrant_is_equal on gfp, else it + * compares the entries p and p+1 of gfq. + * \param [in] gfq An array encoding the partition offsets in the + * global quadrant array; length \a num_procs + 1. + * \param [in] gfp An array encoding the partition shape. + * Non-decreasing; length \a num_procs + 1. + * \param [in] num_procs Number of processes in the partition. + * \param [in] p Valid 0 < \a p < \a num_procs. + * \return True if and only if processor \p is empty. + */ +int p4est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, + const p4est_quadrant_t *gfp, + int num_procs, int p); + + /** Test whether a quadrant is fully contained in a rank's owned region. * This function may return false when \ref p4est_comm_is_owner returns true. * \param [in] rank Rank whose ownership is tested. diff --git a/src/p4est_to_p8est.h b/src/p4est_to_p8est.h index dc8e00207..5ceea28ce 100644 --- a/src/p4est_to_p8est.h +++ b/src/p4est_to_p8est.h @@ -459,6 +459,7 @@ #define p4est_comm_count_pertree p8est_comm_count_pertree #define p4est_comm_is_empty p8est_comm_is_empty #define p4est_comm_is_empty_gfq p8est_comm_is_empty_gfq +#define p4est_comm_is_empty_gfx p8est_comm_is_empty_gfx #define p4est_comm_is_contained p8est_comm_is_contained #define p4est_comm_is_owner p8est_comm_is_owner #define p4est_comm_is_owner_gfp p8est_comm_is_owner_gfp diff --git a/src/p8est_communication.h b/src/p8est_communication.h index 062a4341e..65d9c4096 100644 --- a/src/p8est_communication.h +++ b/src/p8est_communication.h @@ -161,6 +161,21 @@ int p8est_comm_is_empty (p8est_t *p8est, int p); int p8est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int num_procs, int p); +/** Query whether a processor has no quadrants. + * If gfq == NULL, the function uses p4est_quadrant_is_equal on gfp, else it + * compares the entries p and p+1 of gfq. + * \param [in] gfq An array encoding the partition offsets in the + * global quadrant array; length \a num_procs + 1. + * \param [in] gfp An array encoding the partition shape. + * Non-decreasing; length \a num_procs + 1. + * \param [in] num_procs Number of processes in the partition. + * \param [in] p Valid 0 < \a p < \a num_procs. + * \return True if and only if processor \p is empty. + */ +int p8est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, + const p4est_quadrant_t *gfp, + int num_procs, int p); + /** Test whether a quadrant is fully contained in a rank's owned region. * This function may return false when \ref p8est_comm_is_owner returns true. * \param [in] rank Rank whose ownership is tested. From bcc4dd72ec7ea5ac47b28160b9a7fb4deba29f79 Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Wed, 12 Apr 2023 18:25:54 +0200 Subject: [PATCH 2/9] change documentation of p4est_comm_is_empty_gfq --- src/p4est_communication.h | 4 ++-- src/p8est_communication.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p4est_communication.h b/src/p4est_communication.h index 927bf73c0..10c14b6ce 100644 --- a/src/p4est_communication.h +++ b/src/p4est_communication.h @@ -152,8 +152,8 @@ void p4est_comm_count_pertree (p4est_t * p4est, int p4est_comm_is_empty (p4est_t *p4est, int p); /** Query whether a processor has no quadrants. - * \param [in] gfp An array encoding the partition shape. - * Non-decreasing; length \a num_procs + 1. + * \param [in] gfq An array encoding the partition offsets in the + * global quadrant array; length \a num_procs + 1. * \param [in] num_procs Number of processes in the partition. * \param [in] p Valid 0 < \a p < \a num_procs. * \return True if and only if processor \p is empty. diff --git a/src/p8est_communication.h b/src/p8est_communication.h index 65d9c4096..48320efe1 100644 --- a/src/p8est_communication.h +++ b/src/p8est_communication.h @@ -152,8 +152,8 @@ void p8est_comm_count_pertree (p8est_t * p8est, int p8est_comm_is_empty (p8est_t *p8est, int p); /** Query whether a processor has no quadrants. - * \param [in] gfp An array encoding the partition shape. - * Non-decreasing; length \a num_procs + 1. + * \param [in] gfq An array encoding the partition offsets in the + * global quadrant array; length \a num_procs + 1. * \param [in] num_procs Number of processes in the partition. * \param [in] p Valid 0 < \a p < \a num_procs. * \return True if and only if processor \p is empty. From 5b575919e2d27606ea00ec0f3708f8a2973436e7 Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Wed, 12 Apr 2023 18:30:56 +0200 Subject: [PATCH 3/9] add p4est_search_partition_gfp --- src/p4est_search.c | 34 +++++++++++++++++++++++++++++++--- src/p4est_search.h | 37 +++++++++++++++++++++++++++++++++++++ src/p4est_to_p8est.h | 1 + src/p8est_search.h | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/src/p4est_search.c b/src/p4est_search.c index 72cf27cff..90387f873 100644 --- a/src/p4est_search.c +++ b/src/p4est_search.c @@ -1344,7 +1344,8 @@ p4est_partition_recursion (const p4est_partition_recursion_t * rec, (rec->gfp, rec->num_procs, rec->num_trees, &child, cpfirst)) { /* cpfirst starts at the tree's first descendant but may be empty */ P4EST_ASSERT (i > 0); - while (p4est_comm_is_empty_gfq (rec->gfq, rec->num_procs, cpfirst)) { + while (p4est_comm_is_empty_gfx + (rec->gfq, rec->gfp, rec->num_procs, cpfirst)) { ++cpfirst; P4EST_ASSERT (p4est_traverse_type_childid (rec->position_array, cpfirst, quadrant) == @@ -1451,6 +1452,33 @@ p4est_search_partition_gfx (const p4est_gloidx_t *gfq, quadrant_fn, point_fn, points); } +void +p4est_search_partition_gfp (const p4est_quadrant_t *gfp, int nmemb, + p4est_topidx_t num_trees, int call_post, void *user, + p4est_search_partition_t quadrant_fn, + p4est_search_partition_t point_fn, + sc_array_t *points) +{ + p4est_t p, *user_p4est = &p; + + /* sanity checks on global first position */ + P4EST_ASSERT (gfp != NULL); + P4EST_ASSERT (gfp[0].p.which_tree == 0); + P4EST_ASSERT (gfp[nmemb].x == 0); + P4EST_ASSERT (gfp[nmemb].y == 0); +#ifdef P4_TO_P8 + P4EST_ASSERT (gfp[nmemb].z == 0); +#endif + P4EST_ASSERT (gfp[nmemb].p.which_tree == num_trees); + + /* conjure up call convention for partition search */ + memset (user_p4est, 0, sizeof (p4est_t)); + user_p4est->user_pointer = user; + p4est_search_partition_internal + (NULL, gfp, nmemb, num_trees, call_post, user_p4est, + quadrant_fn, point_fn, points); +} + void p4est_search_partition_internal (const p4est_gloidx_t *gfq, const p4est_quadrant_t *gfp, int nmemb, p4est_topidx_t num_trees, int call_post, p4est_t *user_p4est, @@ -1466,7 +1494,6 @@ void p4est_search_partition_internal p4est_partition_recursion_t srec, *rec = &srec; /* we do nothing if there is nothing to be done */ - P4EST_ASSERT (gfq != NULL); P4EST_ASSERT (gfp != NULL); P4EST_ASSERT (points == NULL || point_fn != NULL); if (quadrant_fn == NULL && points == NULL) { @@ -1523,7 +1550,8 @@ void p4est_search_partition_internal if (p4est_traverse_is_clean_start (rec->gfp, rec->num_procs, rec->num_trees, &root, pfirst)) { /* pfirst starts at the tree's first descendant but may be empty */ - while (p4est_comm_is_empty_gfq (rec->gfq, rec->num_procs, pfirst)) { + while (p4est_comm_is_empty_gfx + (rec->gfq, rec->gfp, rec->num_procs, pfirst)) { ++pfirst; P4EST_ASSERT (p4est_traverse_type_tree (&position_array, pfirst, NULL) == (size_t) tt); diff --git a/src/p4est_search.h b/src/p4est_search.h index 2dfd3f5eb..2411219c2 100644 --- a/src/p4est_search.h +++ b/src/p4est_search.h @@ -452,6 +452,43 @@ void p4est_search_partition_gfx p4est_search_partition_t quadrant_fn, p4est_search_partition_t point_fn, sc_array_t *points); +/** Traverse some given global partition top-down. + * The partition can be that of any p4est, not necessarily known to the + * caller. This is not a collective function. It does not communicate. + * We proceed top-down through the partition, identically on all processors + * except for the results of two user-provided callbacks. The recursion will only + * go down branches that are split between multiple processors. The callback + * functions can be used to stop a branch recursion even for split branches. + * This function offers the option to search for arbitrary user-defined points + * analogously to \ref p4est_search_local. + * This function is similar to p4est_search_partition_gfx, but does not require + * the p4est_gloidx_t array gfq. If gfq is available, using + * p4est_search_partition_gfx is recommended, because it is slightly faster. + * \note Traversing the whole given partition will be at least O(P), + * so sensible use of the callback function is advised to cut it short. + * \param [in] gfp Partition position to traverse. Length \a nmemb + 1. + * \param [in] nmemb Number of processors encoded in \a gfp (plus one). + * \param [in] num_trees Tree number must match the contents of \a gfp. + * \param [in] call_post If true, call quadrant callback both pre and post + * point callback, in both cases before recursion (!). + * \param [in] user We pass a dummy p4est to the callbacks whose only + * valid element is its user_pointer set to \a user. + * \param [in] quadrant_fn This function controls the recursion, + * which only continues deeper if this + * callback returns true for a branch quadrant. + * It is allowed to set this to NULL. + * \param [in] point_fn This function decides per-point whether it is + * followed down the recursion. + * Must be non-NULL if \b points are not NULL. + * \param [in] points User-provided array of \b points that are + * passed to the callback \b point_fn. + * See \ref p4est_search_local for details. + */ +void p4est_search_partition_gfp + (const p4est_quadrant_t *gfp, int nmemb, p4est_topidx_t num_trees, + int call_post, void *user, p4est_search_partition_t quadrant_fn, + p4est_search_partition_t point_fn, sc_array_t *points); + /** Callback function for the top-down search through the whole forest. * \param [in] p4est The forest to search. * We recurse through the trees one after another. diff --git a/src/p4est_to_p8est.h b/src/p4est_to_p8est.h index 5ceea28ce..e126de105 100644 --- a/src/p4est_to_p8est.h +++ b/src/p4est_to_p8est.h @@ -410,6 +410,7 @@ #define p4est_search_reorder p8est_search_reorder #define p4est_search_partition p8est_search_partition #define p4est_search_partition_gfx p8est_search_partition_gfx +#define p4est_search_partition_gfp p8est_search_partition_gfp #define p4est_search_all p8est_search_all #define p4est_build_new p8est_build_new #define p4est_build_init_add p8est_build_init_add diff --git a/src/p8est_search.h b/src/p8est_search.h index 69f00d4a9..4559020cc 100644 --- a/src/p8est_search.h +++ b/src/p8est_search.h @@ -454,6 +454,43 @@ void p8est_search_partition_gfx p8est_search_partition_t quadrant_fn, p8est_search_partition_t point_fn, sc_array_t *points); +/** Traverse some given global partition top-down. + * The partition can be that of any p4est, not necessarily known to the + * caller. This is not a collective function. It does not communicate. + * We proceed top-down through the partition, identically on all processors + * except for the results of two user-provided callbacks. The recursion will only + * go down branches that are split between multiple processors. The callback + * functions can be used to stop a branch recursion even for split branches. + * This function offers the option to search for arbitrary user-defined points + * analogously to \ref p4est_search_local. + * This function is similar to p4est_search_partition_gfx, but does not require + * the p4est_gloidx_t array gfq. If gfq is available, using + * p4est_search_partition_gfx is recommended, because it is slightly faster. + * \note Traversing the whole given partition will be at least O(P), + * so sensible use of the callback function is advised to cut it short. + * \param [in] gfp Partition position to traverse. Length \a nmemb + 1. + * \param [in] nmemb Number of processors encoded in \a gfp (plus one). + * \param [in] num_trees Tree number must match the contents of \a gfp. + * \param [in] call_post If true, call quadrant callback both pre and post + * point callback, in both cases before recursion (!). + * \param [in] user We pass a dummy p4est to the callbacks whose only + * valid element is its user_pointer set to \a user. + * \param [in] quadrant_fn This function controls the recursion, + * which only continues deeper if this + * callback returns true for a branch quadrant. + * It is allowed to set this to NULL. + * \param [in] point_fn This function decides per-point whether it is + * followed down the recursion. + * Must be non-NULL if \b points are not NULL. + * \param [in] points User-provided array of \b points that are + * passed to the callback \b point_fn. + * See \ref p4est_search_local for details. + */ +void p8est_search_partition_gfp + (const p4est_quadrant_t *gfp, int nmemb, p4est_topidx_t num_trees, + int call_post, void *user, p4est_search_partition_t quadrant_fn, + p4est_search_partition_t point_fn, sc_array_t *points); + /** Callback function for the top-down search through the whole forest. * \param [in] p4est The forest to search. * We recurse through the trees one after another. From f2a510f7df085819413e8832b5ed0f0b615c4379 Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Thu, 13 Apr 2023 14:15:51 +0200 Subject: [PATCH 4/9] adapt p4est_comm_is_empty_gfx to coding standards --- src/p4est_communication.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p4est_communication.c b/src/p4est_communication.c index 4829b3856..381ab8ee4 100644 --- a/src/p4est_communication.c +++ b/src/p4est_communication.c @@ -599,10 +599,10 @@ int p4est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, const p4est_quadrant_t *gfp, int num_procs, int p) { - P4EST_ASSERT (0 <= p && p < num_procs); P4EST_ASSERT (gfp != NULL); + P4EST_ASSERT (0 <= p && p < num_procs); - if (gfq) { + if (gfq != NULL) { return gfq[p] == gfq[p + 1]; } else { From 213add3faaeb0789473dcb4e1fec6a02e89af85a Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Thu, 13 Apr 2023 14:23:39 +0200 Subject: [PATCH 5/9] improve comments and use doxygen commands --- src/p4est_communication.h | 12 ++++++------ src/p4est_search.h | 8 ++++---- src/p8est_communication.h | 12 ++++++------ src/p8est_search.h | 26 +++++++++++++------------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/p4est_communication.h b/src/p4est_communication.h index 10c14b6ce..76c088527 100644 --- a/src/p4est_communication.h +++ b/src/p4est_communication.h @@ -155,23 +155,23 @@ int p4est_comm_is_empty (p4est_t *p4est, int p); * \param [in] gfq An array encoding the partition offsets in the * global quadrant array; length \a num_procs + 1. * \param [in] num_procs Number of processes in the partition. - * \param [in] p Valid 0 < \a p < \a num_procs. - * \return True if and only if processor \p is empty. + * \param [in] p Valid 0 <= \a p < \a num_procs. + * \return True if and only if processor \a p is empty. */ int p4est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int num_procs, int p); /** Query whether a processor has no quadrants. - * If gfq == NULL, the function uses p4est_quadrant_is_equal on gfp, else it - * compares the entries p and p+1 of gfq. + * If \a gfq == NULL, the function uses p4est_quadrant_is_equal on \a gfp, else + * it compares the entries \a p and \a p+1 of \a gfq. * \param [in] gfq An array encoding the partition offsets in the * global quadrant array; length \a num_procs + 1. * \param [in] gfp An array encoding the partition shape. * Non-decreasing; length \a num_procs + 1. * \param [in] num_procs Number of processes in the partition. - * \param [in] p Valid 0 < \a p < \a num_procs. - * \return True if and only if processor \p is empty. + * \param [in] p Valid 0 <= \a p < \a num_procs. + * \return True if and only if processor \a p is empty. */ int p4est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, const p4est_quadrant_t *gfp, diff --git a/src/p4est_search.h b/src/p4est_search.h index 2411219c2..a68101a86 100644 --- a/src/p4est_search.h +++ b/src/p4est_search.h @@ -311,7 +311,7 @@ typedef int (*p4est_search_reorder_t) (p4est_t * p4est, sc_array_t * indices); /** Run a depth-first traversal, optionally filtering search points. - * There are three main differences to \ref p4est_search_local: + * There are three main differences to \ref p4est_search_local : * * * Before beginning the recursion, we call the \a reorder_fn callback * with an index array enumerating the local tree roots. The callback @@ -461,9 +461,9 @@ void p4est_search_partition_gfx * functions can be used to stop a branch recursion even for split branches. * This function offers the option to search for arbitrary user-defined points * analogously to \ref p4est_search_local. - * This function is similar to p4est_search_partition_gfx, but does not require - * the p4est_gloidx_t array gfq. If gfq is available, using - * p4est_search_partition_gfx is recommended, because it is slightly faster. + * This function is similar to \ref p4est_search_partition_gfx, but does not + * require the \ref p4est_gloidx_t array gfq. If gfq is available, using + * \ref p4est_search_partition_gfx is recommended, because it is slightly faster. * \note Traversing the whole given partition will be at least O(P), * so sensible use of the callback function is advised to cut it short. * \param [in] gfp Partition position to traverse. Length \a nmemb + 1. diff --git a/src/p8est_communication.h b/src/p8est_communication.h index 48320efe1..2643b6738 100644 --- a/src/p8est_communication.h +++ b/src/p8est_communication.h @@ -155,22 +155,22 @@ int p8est_comm_is_empty (p8est_t *p8est, int p); * \param [in] gfq An array encoding the partition offsets in the * global quadrant array; length \a num_procs + 1. * \param [in] num_procs Number of processes in the partition. - * \param [in] p Valid 0 < \a p < \a num_procs. - * \return True if and only if processor \p is empty. + * \param [in] p Valid 0 <= \a p < \a num_procs. + * \return True if and only if processor \a p is empty. */ int p8est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int num_procs, int p); /** Query whether a processor has no quadrants. - * If gfq == NULL, the function uses p4est_quadrant_is_equal on gfp, else it - * compares the entries p and p+1 of gfq. + * If \a gfq == NULL, the function uses p4est_quadrant_is_equal on \a gfp, else + * it compares the entries \a p and \a p+1 of \a gfq. * \param [in] gfq An array encoding the partition offsets in the * global quadrant array; length \a num_procs + 1. * \param [in] gfp An array encoding the partition shape. * Non-decreasing; length \a num_procs + 1. * \param [in] num_procs Number of processes in the partition. - * \param [in] p Valid 0 < \a p < \a num_procs. - * \return True if and only if processor \p is empty. + * \param [in] p Valid 0 <= \a p < \a num_procs. + * \return True if and only if processor \a p is empty. */ int p8est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, const p4est_quadrant_t *gfp, diff --git a/src/p8est_search.h b/src/p8est_search.h index 4559020cc..0d32b1009 100644 --- a/src/p8est_search.h +++ b/src/p8est_search.h @@ -314,7 +314,7 @@ typedef int (*p8est_search_reorder_t) (p8est_t * p4est, sc_array_t * indices); /** Run a depth-first traversal, optionally filtering search points. - * There are three main differences to \ref p4est_search_local: + * There are three main differences to \ref p8est_search_local : * * * Before beginning the recursion, we call the \a reorder_fn callback * with an index array enumerating the local tree roots. The callback @@ -394,7 +394,7 @@ typedef int (*p8est_search_partition_t) (p8est_t * p4est, * go down branches that are split between multiple processors. The callback * functions can be used to stop a branch recursion even for split branches. * This function offers the option to search for arbitrary user-defined points - * analogously to \ref p4est_search_local. + * analogously to \ref p8est_search_local. * \note Traversing the whole processor partition will be at least O(P), * so sensible use of the callback function is advised to cut it short. * \param [in] p4est The forest to traverse. @@ -462,10 +462,10 @@ void p8est_search_partition_gfx * go down branches that are split between multiple processors. The callback * functions can be used to stop a branch recursion even for split branches. * This function offers the option to search for arbitrary user-defined points - * analogously to \ref p4est_search_local. - * This function is similar to p4est_search_partition_gfx, but does not require - * the p4est_gloidx_t array gfq. If gfq is available, using - * p4est_search_partition_gfx is recommended, because it is slightly faster. + * analogously to \ref p8est_search_local. + * This function is similar to \ref p8est_search_partition_gfx, but does not + * require the \ref p4est_gloidx_t array gfq. If gfq is available, using + * \ref p8est_search_partition_gfx is recommended, because it is slightly faster. * \note Traversing the whole given partition will be at least O(P), * so sensible use of the callback function is advised to cut it short. * \param [in] gfp Partition position to traverse. Length \a nmemb + 1. @@ -484,12 +484,12 @@ void p8est_search_partition_gfx * Must be non-NULL if \b points are not NULL. * \param [in] points User-provided array of \b points that are * passed to the callback \b point_fn. - * See \ref p4est_search_local for details. + * See \ref p8est_search_local for details. */ void p8est_search_partition_gfp - (const p4est_quadrant_t *gfp, int nmemb, p4est_topidx_t num_trees, - int call_post, void *user, p4est_search_partition_t quadrant_fn, - p4est_search_partition_t point_fn, sc_array_t *points); + (const p8est_quadrant_t *gfp, int nmemb, p4est_topidx_t num_trees, + int call_post, void *user, p8est_search_partition_t quadrant_fn, + p8est_search_partition_t point_fn, sc_array_t *points); /** Callback function for the top-down search through the whole forest. * \param [in] p4est The forest to search. @@ -549,8 +549,8 @@ typedef int (*p8est_search_all_t) (p8est_t * p8est, /** Perform a top-down search on the whole forest. * - * This function combines the functionality of \ref p4est_search_local and \ref - * p4est_search_partition; their documentation applies for the most part. + * This function combines the functionality of \ref p8est_search_local and \ref + * p8est_search_partition; their documentation applies for the most part. * * The recursion proceeds from the root quadrant of each tree until * (a) we encounter a remote quadrant that covers only one processor, or @@ -581,7 +581,7 @@ typedef int (*p8est_search_all_t) (p8est_t * p8est, * \note * This function works fine when used for the special cases that either the * partition or the local quadrants are not of interest. However, in the case - * of querying only local information we expect that \ref p4est_search_local + * of querying only local information we expect that \ref p8est_search_local * will be faster since it employs specific local optimizations. * * \param [in] p4est The forest to be searched. From 7f27823102469f883b1f2945a78c07438be5f972 Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Thu, 13 Apr 2023 14:27:10 +0200 Subject: [PATCH 6/9] allow gfq == NULL in p4est_search_partition_gfx --- src/p4est_search.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/src/p4est_search.c b/src/p4est_search.c index 90387f873..05102a45b 100644 --- a/src/p4est_search.c +++ b/src/p4est_search.c @@ -1430,9 +1430,9 @@ p4est_search_partition_gfx (const p4est_gloidx_t *gfq, p4est_t p, *user_p4est = &p; /* sanity checks on global first quadrant */ - P4EST_ASSERT (gfq != NULL); - P4EST_ASSERT (gfq[0] == 0); - P4EST_ASSERT (gfq[nmemb] >= (p4est_gloidx_t) num_trees); + P4EST_ASSERT ((gfq == NULL) + || ((gfq[0] == 0) + && (gfq[nmemb] >= (p4est_gloidx_t) num_trees))); /* sanity checks on global first position */ P4EST_ASSERT (gfp != NULL); @@ -1459,23 +1459,8 @@ p4est_search_partition_gfp (const p4est_quadrant_t *gfp, int nmemb, p4est_search_partition_t point_fn, sc_array_t *points) { - p4est_t p, *user_p4est = &p; - - /* sanity checks on global first position */ - P4EST_ASSERT (gfp != NULL); - P4EST_ASSERT (gfp[0].p.which_tree == 0); - P4EST_ASSERT (gfp[nmemb].x == 0); - P4EST_ASSERT (gfp[nmemb].y == 0); -#ifdef P4_TO_P8 - P4EST_ASSERT (gfp[nmemb].z == 0); -#endif - P4EST_ASSERT (gfp[nmemb].p.which_tree == num_trees); - - /* conjure up call convention for partition search */ - memset (user_p4est, 0, sizeof (p4est_t)); - user_p4est->user_pointer = user; - p4est_search_partition_internal - (NULL, gfp, nmemb, num_trees, call_post, user_p4est, + p4est_search_partition_gfx + (NULL, gfp, nmemb, num_trees, call_post, user, quadrant_fn, point_fn, points); } From f5641ed4b8d82cd3ca4cc1c4d8e2e4075bfa2fe4 Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Wed, 6 Dec 2023 17:57:22 +0100 Subject: [PATCH 7/9] enforce gfq != NULL in search_partition_gfx --- src/p4est_search.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/p4est_search.c b/src/p4est_search.c index 723f03a94..59c256cc7 100644 --- a/src/p4est_search.c +++ b/src/p4est_search.c @@ -1433,9 +1433,9 @@ p4est_search_partition_gfx (const p4est_gloidx_t *gfq, p4est_t p, *user_p4est = &p; /* sanity checks on global first quadrant */ - P4EST_ASSERT ((gfq == NULL) - || ((gfq[0] == 0) - && (gfq[nmemb] >= (p4est_gloidx_t) num_trees))); + P4EST_ASSERT (gfq != NULL); + P4EST_ASSERT (gfq[0] == 0); + P4EST_ASSERT (gfq[nmemb] >= (p4est_gloidx_t) num_trees); /* sanity checks on global first position */ P4EST_ASSERT (gfp != NULL); @@ -1457,13 +1457,28 @@ p4est_search_partition_gfx (const p4est_gloidx_t *gfq, void p4est_search_partition_gfp (const p4est_quadrant_t *gfp, int nmemb, - p4est_topidx_t num_trees, int call_post, void *user, - p4est_search_partition_t quadrant_fn, + p4est_topidx_t num_trees, int call_post, + void *user, p4est_search_partition_t quadrant_fn, p4est_search_partition_t point_fn, sc_array_t *points) { - p4est_search_partition_gfx - (NULL, gfp, nmemb, num_trees, call_post, user, + p4est_t p, *user_p4est = &p; + + /* sanity checks on global first position */ + P4EST_ASSERT (gfp != NULL); + P4EST_ASSERT (gfp[0].p.which_tree == 0); + P4EST_ASSERT (gfp[nmemb].x == 0); + P4EST_ASSERT (gfp[nmemb].y == 0); +#ifdef P4_TO_P8 + P4EST_ASSERT (gfp[nmemb].z == 0); +#endif + P4EST_ASSERT (gfp[nmemb].p.which_tree == num_trees); + + /* conjure up call convention for partition search */ + memset (user_p4est, 0, sizeof (p4est_t)); + user_p4est->user_pointer = user; + p4est_search_partition_internal + (NULL, gfp, nmemb, num_trees, call_post, user_p4est, quadrant_fn, point_fn, points); } From 9b5486d42e98abb88deac87e652b78e5ef0ce6ab Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Wed, 6 Dec 2023 18:15:21 +0100 Subject: [PATCH 8/9] add comm_is_empty_gfp --- src/p4est_communication.c | 9 +++++++++ src/p4est_communication.h | 9 +++++++++ src/p4est_to_p8est.h | 1 + src/p8est_communication.h | 10 ++++++++++ 4 files changed, 29 insertions(+) diff --git a/src/p4est_communication.c b/src/p4est_communication.c index 381ab8ee4..7b9faa409 100644 --- a/src/p4est_communication.c +++ b/src/p4est_communication.c @@ -595,6 +595,15 @@ p4est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int num_procs, int p) return gfq[p] == gfq[p + 1]; } +int +p4est_comm_is_empty_gfp (const p4est_quadrant_t *gfp, int num_procs, int p) +{ + P4EST_ASSERT (gfp != NULL); + P4EST_ASSERT (0 <= p && p < num_procs); + + return p4est_quadrant_is_equal_piggy (&gfp[p], &gfp[p + 1]); +} + int p4est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, const p4est_quadrant_t *gfp, int num_procs, int p) diff --git a/src/p4est_communication.h b/src/p4est_communication.h index 76c088527..cf32651c0 100644 --- a/src/p4est_communication.h +++ b/src/p4est_communication.h @@ -161,6 +161,15 @@ int p4est_comm_is_empty (p4est_t *p4est, int p); int p4est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int num_procs, int p); +/** Query whether a processor has no quadrants. + * \param [in] gfp An array encoding the partition shape. + * Non-decreasing; length \a num_procs + 1. + * \param [in] num_procs Number of processes in the partition. + * \param [in] p Valid 0 <= \a p < \a num_procs. + * \return True if and only if processor \a p is empty. + */ +int p4est_comm_is_empty_gfp (const p4est_quadrant_t *gfp, + int num_procs, int p); /** Query whether a processor has no quadrants. * If \a gfq == NULL, the function uses p4est_quadrant_is_equal on \a gfp, else diff --git a/src/p4est_to_p8est.h b/src/p4est_to_p8est.h index b66d9bcbf..4b7caa168 100644 --- a/src/p4est_to_p8est.h +++ b/src/p4est_to_p8est.h @@ -461,6 +461,7 @@ #define p4est_comm_count_pertree p8est_comm_count_pertree #define p4est_comm_is_empty p8est_comm_is_empty #define p4est_comm_is_empty_gfq p8est_comm_is_empty_gfq +#define p4est_comm_is_empty_gfp p8est_comm_is_empty_gfp #define p4est_comm_is_empty_gfx p8est_comm_is_empty_gfx #define p4est_comm_is_contained p8est_comm_is_contained #define p4est_comm_is_owner p8est_comm_is_owner diff --git a/src/p8est_communication.h b/src/p8est_communication.h index 2643b6738..ac11a16d3 100644 --- a/src/p8est_communication.h +++ b/src/p8est_communication.h @@ -161,6 +161,16 @@ int p8est_comm_is_empty (p8est_t *p8est, int p); int p8est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int num_procs, int p); +/** Query whether a processor has no quadrants. + * \param [in] gfp An array encoding the partition shape. + * Non-decreasing; length \a num_procs + 1. + * \param [in] num_procs Number of processes in the partition. + * \param [in] p Valid 0 <= \a p < \a num_procs. + * \return True if and only if processor \a p is empty. + */ +int p8est_comm_is_empty_gfp (const p8est_quadrant_t *gfp, + int num_procs, int p); + /** Query whether a processor has no quadrants. * If \a gfq == NULL, the function uses p4est_quadrant_is_equal on \a gfp, else * it compares the entries \a p and \a p+1 of \a gfq. From 176b92a2095264b24216c396c3713a6ca1f68b13 Mon Sep 17 00:00:00 2001 From: Hannes Brandt Date: Wed, 6 Dec 2023 18:40:55 +0100 Subject: [PATCH 9/9] remove comm_is_empty_gfx --- src/p4est_communication.c | 15 --------------- src/p4est_communication.h | 16 ---------------- src/p4est_search.c | 9 +++++++-- src/p4est_to_p8est.h | 1 - src/p8est_communication.h | 15 --------------- 5 files changed, 7 insertions(+), 49 deletions(-) diff --git a/src/p4est_communication.c b/src/p4est_communication.c index 7b9faa409..92c737b30 100644 --- a/src/p4est_communication.c +++ b/src/p4est_communication.c @@ -604,21 +604,6 @@ p4est_comm_is_empty_gfp (const p4est_quadrant_t *gfp, int num_procs, int p) return p4est_quadrant_is_equal_piggy (&gfp[p], &gfp[p + 1]); } -int -p4est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, const p4est_quadrant_t *gfp, - int num_procs, int p) -{ - P4EST_ASSERT (gfp != NULL); - P4EST_ASSERT (0 <= p && p < num_procs); - - if (gfq != NULL) { - return gfq[p] == gfq[p + 1]; - } - else { - return p4est_quadrant_is_equal_piggy (&gfp[p], &gfp[p + 1]); - } -} - int p4est_comm_is_contained (p4est_t * p4est, p4est_locidx_t which_tree, const p4est_quadrant_t * q, int rank) diff --git a/src/p4est_communication.h b/src/p4est_communication.h index cf32651c0..2c37545c7 100644 --- a/src/p4est_communication.h +++ b/src/p4est_communication.h @@ -171,22 +171,6 @@ int p4est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int p4est_comm_is_empty_gfp (const p4est_quadrant_t *gfp, int num_procs, int p); -/** Query whether a processor has no quadrants. - * If \a gfq == NULL, the function uses p4est_quadrant_is_equal on \a gfp, else - * it compares the entries \a p and \a p+1 of \a gfq. - * \param [in] gfq An array encoding the partition offsets in the - * global quadrant array; length \a num_procs + 1. - * \param [in] gfp An array encoding the partition shape. - * Non-decreasing; length \a num_procs + 1. - * \param [in] num_procs Number of processes in the partition. - * \param [in] p Valid 0 <= \a p < \a num_procs. - * \return True if and only if processor \a p is empty. - */ -int p4est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, - const p4est_quadrant_t *gfp, - int num_procs, int p); - - /** Test whether a quadrant is fully contained in a rank's owned region. * This function may return false when \ref p4est_comm_is_owner returns true. * \param [in] rank Rank whose ownership is tested. diff --git a/src/p4est_search.c b/src/p4est_search.c index 59c256cc7..06bbcbce9 100644 --- a/src/p4est_search.c +++ b/src/p4est_search.c @@ -33,6 +33,11 @@ #endif #include +#define P4EST_COMM_IS_EMPTY_GFQ_GFP(gfq, gfp, num_procs, p) \ + (((gfq) != NULL) ? \ + p4est_comm_is_empty_gfq ((gfq), (num_procs), (p)) :\ + p4est_comm_is_empty_gfp ((gfp), (num_procs), (p))) + /** A callback function that describes the search window. * The idea is to define the type of an array entry as type 1, if * my_begin <= array[i], my_end > array[i] and as type 2, if the entry @@ -1347,7 +1352,7 @@ p4est_partition_recursion (const p4est_partition_recursion_t * rec, (rec->gfp, rec->num_procs, rec->num_trees, &child, cpfirst)) { /* cpfirst starts at the tree's first descendant but may be empty */ P4EST_ASSERT (i > 0); - while (p4est_comm_is_empty_gfx + while (P4EST_COMM_IS_EMPTY_GFQ_GFP (rec->gfq, rec->gfp, rec->num_procs, cpfirst)) { ++cpfirst; P4EST_ASSERT (p4est_traverse_type_childid @@ -1553,7 +1558,7 @@ void p4est_search_partition_internal if (p4est_traverse_is_clean_start (rec->gfp, rec->num_procs, rec->num_trees, &root, pfirst)) { /* pfirst starts at the tree's first descendant but may be empty */ - while (p4est_comm_is_empty_gfx + while (P4EST_COMM_IS_EMPTY_GFQ_GFP (rec->gfq, rec->gfp, rec->num_procs, pfirst)) { ++pfirst; P4EST_ASSERT (p4est_traverse_type_tree diff --git a/src/p4est_to_p8est.h b/src/p4est_to_p8est.h index 4b7caa168..8738c7cef 100644 --- a/src/p4est_to_p8est.h +++ b/src/p4est_to_p8est.h @@ -462,7 +462,6 @@ #define p4est_comm_is_empty p8est_comm_is_empty #define p4est_comm_is_empty_gfq p8est_comm_is_empty_gfq #define p4est_comm_is_empty_gfp p8est_comm_is_empty_gfp -#define p4est_comm_is_empty_gfx p8est_comm_is_empty_gfx #define p4est_comm_is_contained p8est_comm_is_contained #define p4est_comm_is_owner p8est_comm_is_owner #define p4est_comm_is_owner_gfp p8est_comm_is_owner_gfp diff --git a/src/p8est_communication.h b/src/p8est_communication.h index ac11a16d3..12d4cf841 100644 --- a/src/p8est_communication.h +++ b/src/p8est_communication.h @@ -171,21 +171,6 @@ int p8est_comm_is_empty_gfq (const p4est_gloidx_t *gfq, int p8est_comm_is_empty_gfp (const p8est_quadrant_t *gfp, int num_procs, int p); -/** Query whether a processor has no quadrants. - * If \a gfq == NULL, the function uses p4est_quadrant_is_equal on \a gfp, else - * it compares the entries \a p and \a p+1 of \a gfq. - * \param [in] gfq An array encoding the partition offsets in the - * global quadrant array; length \a num_procs + 1. - * \param [in] gfp An array encoding the partition shape. - * Non-decreasing; length \a num_procs + 1. - * \param [in] num_procs Number of processes in the partition. - * \param [in] p Valid 0 <= \a p < \a num_procs. - * \return True if and only if processor \a p is empty. - */ -int p8est_comm_is_empty_gfx (const p4est_gloidx_t *gfq, - const p4est_quadrant_t *gfp, - int num_procs, int p); - /** Test whether a quadrant is fully contained in a rank's owned region. * This function may return false when \ref p8est_comm_is_owner returns true. * \param [in] rank Rank whose ownership is tested.