Skip to content

Commit 4a06e41

Browse files
authored
Merge pull request #2026 from DLR-AMR/feature_pfc_revisited
Feature: Partition for Coarsening (PFC)
2 parents 89c02aa + cef46c4 commit 4a06e41

14 files changed

+1342
-21
lines changed

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ target_sources( T8 PRIVATE
172172
t8_data/t8_containers.cxx
173173
t8_forest/t8_forest_adapt.cxx
174174
t8_forest/t8_forest_partition.cxx
175+
t8_forest/t8_forest_partition_for_coarsening.cxx
176+
t8_forest/t8_forest_pfc_helper.cxx
175177
t8_forest/t8_forest.cxx
176178
t8_forest/t8_forest_private.cxx
177179
t8_forest/t8_forest_ghost.cxx

src/t8.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ typedef int32_t t8_locidx_t;
9898
#define T8_LOCIDX_MAX INT32_MAX
9999
/** Comparison function for t8_locidx_t */
100100
#define t8_compare_locidx(v, w) sc_int32_compare (v, w)
101-
101+
/** A type for holding process ids. */
102+
typedef int t8_procidx_t;
102103
/** A type for global indexing that holds really big numbers. */
103104
typedef int64_t t8_gloidx_t;
104105
/** The MPI Datatype of t8_gloidx_t */
@@ -146,7 +147,8 @@ typedef enum {
146147
T8_MPI_CMESH_UNIFORM_BOUNDS_START, /**< Used for cmesh uniform bounds computation. */
147148
T8_MPI_CMESH_UNIFORM_BOUNDS_END, /**< Used for cmesh uniform bounds computation. */
148149
T8_MPI_TEST_ELEMENT_PACK_TAG, /**< Used for testing mpi pack and unpack functionality */
149-
T8_MPI_TAG_LAST /**< Dummy last MPT tag. */
150+
T8_MPI_PFC_TAG, /**< Used for data exchange during partition for coarsening. */
151+
T8_MPI_TAG_LAST /**< Dummy last MPI tag. */
150152
} t8_MPI_tag_t;
151153

152154
/** Query the package identity as registered in libsc.

src/t8_eclass.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ typedef enum t8_eclass {
8080
#define T8_ECLASS_MAX_CORNERS 8
8181
/** The maximal possible dimension for an eclass */
8282
#define T8_ECLASS_MAX_DIM 3
83+
/** The maximal number of children any element may have.*/
84+
#define T8_ECLASS_MAX_CHILDREN 10
8385

8486
/* clang-format off */
8587

src/t8_forest/t8_forest.cxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,8 @@ t8_forest_tree_shared ([[maybe_unused]] t8_forest_t forest, [[maybe_unused]] int
12431243
T8_ASSERT (forest != NULL);
12441244
T8_ASSERT (forest->first_local_tree > -1);
12451245
T8_ASSERT (forest->first_local_tree <= forest->global_num_trees);
1246-
T8_ASSERT (forest->last_local_tree < forest->global_num_trees);
1246+
T8_ASSERT (forest->first_local_tree <= forest->last_local_tree + 1);
1247+
T8_ASSERT (forest->last_local_tree <= forest->global_num_trees);
12471248
#if T8_ENABLE_DEBUG
12481249
if (forest->first_local_tree == 0 && forest->last_local_tree == -1) {
12491250
T8_ASSERT (forest->last_local_tree < 0);

src/t8_forest/t8_forest_partition.cxx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <t8_forest/t8_forest_types.h>
2929
#include <t8_forest/t8_forest_private.h>
3030
#include <t8_forest/t8_forest_general.h>
31+
#include <t8_forest/t8_forest_partition_for_coarsening.h>
3132
#include <t8_cmesh/t8_cmesh_internal/t8_cmesh_offset.h>
3233
#include <t8_schemes/t8_scheme.hxx>
3334

@@ -540,6 +541,12 @@ t8_forest_partition_compute_new_offset (t8_forest_t forest)
540541
}
541542
}
542543
t8_shmem_array_end_writing (forest->element_offsets);
544+
545+
// In case the partition-for-coarsening flag is set, correct the partitioning if a family of elements is
546+
// split across process boundaries
547+
if (forest->set_for_coarsening != 0) {
548+
t8_forest_pfc_correction_offsets (forest);
549+
}
543550
}
544551

545552
/* Find the owner of a given element.

src/t8_forest/t8_forest_partition_for_coarsening.cxx

Lines changed: 404 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
This file is part of t8code.
3+
t8code is a C library to manage a collection (a forest) of multiple
4+
connected adaptive space-trees of general element classes in parallel.
5+
6+
Copyright (C) 2025 the developers
7+
8+
t8code is free software; you can redistribute it and/or modify
9+
it under the terms of the GNU General Public License as published by
10+
the Free Software Foundation; either version 2 of the License, or
11+
(at your option) any later version.
12+
13+
t8code is distributed in the hope that it will be useful,
14+
but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
GNU General Public License for more details.
17+
18+
You should have received a copy of the GNU General Public License
19+
along with t8code; if not, write to the Free Software Foundation, Inc.,
20+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21+
*/
22+
23+
/** \file t8_forest_partition_for_coarsening.h
24+
* adjust the partition of the receiving forest so that all elements from a family
25+
* belong to the same process before applying the partition
26+
*/
27+
28+
#ifndef T8_FOREST_PFC_H
29+
#define T8_FOREST_ITERATE_H
30+
31+
#include <t8.h>
32+
#include <t8_forest/t8_forest_general.h>
33+
34+
T8_EXTERN_C_BEGIN ();
35+
36+
/** \brief Correct the partitioning if element families are split accorss process boundaries.
37+
*
38+
* The default partitioning distributes the elements into equally-sized partitions. For coarsening, however,
39+
* all elements of a family have to be on the same process in order to be coarsened into their parent element.
40+
* This function corrects the partitioning such that no families are split across process boundaries.
41+
* The price to be paid is a slight deviation from the optimal balance of elements among processors.
42+
*
43+
* \param [in,out] forest the forest. On input, it has been partitioned into equally-sized element partitions.
44+
* On output, the partitioning has been adjusted such that no element families
45+
* are split across the process boundaries.
46+
*/
47+
void
48+
t8_forest_pfc_correction_offsets (t8_forest_t forest);
49+
50+
T8_EXTERN_C_END ();
51+
#endif /* T8_FOREST_ITERATE_H */
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
This file is part of t8code.
3+
t8code is a C library to manage a collection (a forest) of multiple
4+
connected adaptive space-trees of general element classes in parallel.
5+
6+
Copyright (C) 2025 the developers
7+
8+
t8code is free software; you can redistribute it and/or modify
9+
it under the terms of the GNU General Public License as published by
10+
the Free Software Foundation; either version 2 of the License, or
11+
(at your option) any later version.
12+
13+
t8code is distributed in the hope that it will be useful,
14+
but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
GNU General Public License for more details.
17+
18+
You should have received a copy of the GNU General Public License
19+
along with t8code; if not, write to the Free Software Foundation, Inc.,
20+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21+
*/
22+
23+
/**
24+
* \file t8_forest_pfc_helper.cxx
25+
* This file defines some helper functions used for the partition-for-coarsening feature.
26+
*/
27+
28+
#include <t8_forest/t8_forest_general.h>
29+
#include <t8_forest/t8_forest_private.h>
30+
#include <t8_forest/t8_forest_types.h>
31+
#include <t8_forest/t8_forest_pfc_helper.hxx>
32+
#include <t8_schemes/t8_scheme.h>
33+
#include <t8_schemes/t8_scheme.hxx>
34+
#include <t8_element.h>
35+
#include <algorithm>
36+
37+
t8_locidx_t
38+
t8_forest_pfc_extreme_local_sibling (const t8_scheme_c *scheme, const t8_tree_t tree,
39+
const t8_locidx_t start_element_id_in_tree, const int signed_increment)
40+
{
41+
// The increment may either be +1 or -1.
42+
T8_ASSERT (abs (signed_increment) == 1);
43+
44+
// Initialization and memory allocation.
45+
const t8_eclass_t tree_class = tree->eclass;
46+
t8_element_t *parent_possible_sibling, *parent_start;
47+
t8_element_new (scheme, tree_class, 1, &parent_possible_sibling);
48+
t8_element_new (scheme, tree_class, 1, &parent_start);
49+
50+
// Determine start element from tree and start ID within tree.
51+
const t8_element_t *start_element = t8_forest_get_tree_leaf_element (tree, start_element_id_in_tree);
52+
53+
// If the start element is of level zero, i.e., the root, it does not have any siblings.
54+
if (scheme->element_get_level (tree_class, start_element) == 0) {
55+
return start_element_id_in_tree;
56+
}
57+
58+
// Get parent of start element.
59+
scheme->element_get_parent (tree_class, start_element, parent_start);
60+
61+
// Determine the parent's number of children.
62+
const int num_children = scheme->element_get_num_children (tree_class, parent_start);
63+
64+
// Determine bound to be used within element loop (and make sure to stay within tree element range);
65+
t8_locidx_t extreme_check_id_in_tree = start_element_id_in_tree + signed_increment * num_children;
66+
extreme_check_id_in_tree
67+
= SC_MAX (0, SC_MIN (extreme_check_id_in_tree, t8_forest_get_tree_leaf_element_count (tree) - 1));
68+
69+
// Initialize extreme_sibling_id_in_tree.
70+
t8_locidx_t extreme_sibling_id_in_tree = start_element_id_in_tree;
71+
72+
// Loop over local IDs of all elements that may form a family
73+
for (t8_locidx_t ielem = start_element_id_in_tree; (ielem - extreme_check_id_in_tree) * signed_increment <= 0;
74+
ielem += signed_increment) {
75+
76+
// Get element from iteration index.
77+
const t8_element_t *possible_sibling = t8_forest_get_tree_leaf_element (tree, ielem);
78+
79+
// Determine parent and check whether it matches parent_start:
80+
// - if it does, the current element is a sibling of start_element. Thus, extreme_sibling_id_in_tree is updated.
81+
scheme->element_get_parent (tree_class, possible_sibling, parent_possible_sibling);
82+
if (scheme->element_is_equal (tree_class, parent_start, parent_possible_sibling)) {
83+
extreme_sibling_id_in_tree = ielem;
84+
}
85+
// - else, the iteration has left the family and we can exit.
86+
else {
87+
break;
88+
}
89+
}
90+
91+
// Deallocation
92+
t8_element_destroy (scheme, tree_class, 1, &parent_possible_sibling);
93+
t8_element_destroy (scheme, tree_class, 1, &parent_start);
94+
95+
// Return extreme sibling ID.
96+
return extreme_sibling_id_in_tree;
97+
}
98+
99+
void
100+
t8_forest_pfc_helper_index_in_tree_from_globalid (const t8_forest_t forest, const t8_gloidx_t gelement_id,
101+
t8_gloidx_t &gtree_id, t8_tree_t &tree, t8_locidx_t &index_in_tree,
102+
t8_element_t *&element)
103+
{
104+
// Determine local element ID by subtracting given and the process' first global ID.
105+
const t8_gloidx_t global_id_of_first_local_element = t8_forest_get_first_local_leaf_element_id (forest);
106+
const t8_locidx_t lelement_id = (t8_locidx_t) (gelement_id - global_id_of_first_local_element);
107+
108+
// Determine the element (as pointer) and the local tree ID.
109+
t8_locidx_t ltree_id;
110+
element = t8_forest_get_leaf_element (forest, lelement_id, &ltree_id);
111+
112+
// From local tree ID, get a pointer to the tree.
113+
tree = t8_forest_get_tree (forest, ltree_id);
114+
115+
// Determine the index within the tree - and run sanity check.
116+
index_in_tree = lelement_id - tree->elements_offset;
117+
T8_ASSERT (element == t8_forest_get_tree_leaf_element (tree, index_in_tree));
118+
119+
// Compute global tree ID as the local one plus the process' first tree ID.
120+
const t8_locidx_t first_local_tree_id = t8_forest_get_first_local_tree_id (forest);
121+
gtree_id = first_local_tree_id + ltree_id;
122+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
This file is part of t8code.
3+
t8code is a C library to manage a collection (a forest) of multiple
4+
connected adaptive space-trees of general element classes in parallel.
5+
6+
Copyright (C) 2025 the developers
7+
8+
t8code is free software; you can redistribute it and/or modify
9+
it under the terms of the GNU General Public License as published by
10+
the Free Software Foundation; either version 2 of the License, or
11+
(at your option) any later version.
12+
13+
t8code is distributed in the hope that it will be useful,
14+
but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
GNU General Public License for more details.
17+
18+
You should have received a copy of the GNU General Public License
19+
along with t8code; if not, write to the Free Software Foundation, Inc.,
20+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21+
*/
22+
23+
/**
24+
* \file t8_forest_pfc_helper.hxx
25+
* This file declares some helper functions used for the partition-for-coarsening feature.
26+
*/
27+
#ifndef T8_FOREST_PFC_HELPER_H
28+
#define T8_FOREST_PFC_HELPER_H
29+
30+
#include <t8.h>
31+
#include <t8_data/t8_shmem.h>
32+
#include <t8_eclass.h>
33+
34+
/** Determine the sibling with the biggest difference in IDs (in the given direction).
35+
*
36+
* \param[in] scheme the refinement scheme
37+
* \param[in] tree the considered tree
38+
* \param[in] start_element_id_in_tree the tree-internal ID of the considered element
39+
* \param[in] signed_increment increment determining the search direction. Has to be
40+
* either -1 (decreasing IDs) or +1 (increasing IDs).
41+
*
42+
* \return The extreme sibling ID within tree, i.e., the tree-internal ID of the sibling
43+
* with the biggest difference to start_element_id_in_tree.
44+
*/
45+
t8_locidx_t
46+
t8_forest_pfc_extreme_local_sibling (const t8_scheme_c *scheme, t8_tree_t tree,
47+
const t8_locidx_t start_element_id_in_tree, const int signed_increment);
48+
49+
/** Helper function for PFC that computes multiple indices for a given global element ID.
50+
*
51+
* \param[in] forest the forest
52+
* \param[in] gelement_id the global element ID
53+
* \param[out] gtree_id the global ID of the tree holding the element
54+
* \param[out] tree the tree holding the element
55+
* \param[out] index_in_tree index of the element within the tree
56+
* \param[out] element pointer to the considered element
57+
*/
58+
void
59+
t8_forest_pfc_helper_index_in_tree_from_globalid (const t8_forest_t forest, const t8_gloidx_t gelement_id,
60+
t8_gloidx_t &gtree_id, t8_tree_t &tree, t8_locidx_t &index_in_tree,
61+
t8_element_t *&element);
62+
#endif

0 commit comments

Comments
 (0)