|
| 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 >ree_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, <ree_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 | +} |
0 commit comments