From c829a8c12b867795e118e52cf02418266abf54b3 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 17 Apr 2024 16:03:25 +0200 Subject: [PATCH 01/55] Added transition scheme files and transition forest files --- src/Makefile.am | 2 + src/t8_forest/t8_forest_transition.cxx | 325 ++ src/t8_forest/t8_forest_transition.h | 78 + src/t8_schemes/t8_transition/Makefile.am | 15 + .../t8_transition_conformal_hex.cxx | 56 + .../t8_transition_conformal_hex_cxx.cxx | 3108 +++++++++++++++++ .../t8_transition_conformal_hex_cxx.hxx | 551 +++ .../t8_transition_conformal_quad.cxx | 53 + .../t8_transition_conformal_quad_cxx.cxx | 2463 +++++++++++++ .../t8_transition_conformal_quad_cxx.hxx | 545 +++ .../t8_transition/t8_transition_cxx.hxx | 49 + 11 files changed, 7245 insertions(+) create mode 100644 src/t8_forest/t8_forest_transition.cxx create mode 100644 src/t8_forest/t8_forest_transition.h create mode 100644 src/t8_schemes/t8_transition/Makefile.am create mode 100644 src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx create mode 100644 src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx create mode 100644 src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx create mode 100644 src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx create mode 100644 src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx create mode 100644 src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx create mode 100644 src/t8_schemes/t8_transition/t8_transition_cxx.hxx diff --git a/src/Makefile.am b/src/Makefile.am index 1720cb17dd..edf3dad376 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -102,6 +102,7 @@ libt8_internal_headers = \ src/t8_forest/t8_forest_cxx.h \ src/t8_forest/t8_forest_ghost.h \ src/t8_forest/t8_forest_balance.h src/t8_forest/t8_forest_types.h \ + src/t8_forest/t8_forest_transition.h \ src/t8_forest/t8_forest_private.h \ src/t8_windows.h libt8_compiled_sources = \ @@ -141,6 +142,7 @@ libt8_compiled_sources = \ src/t8_forest/t8_forest_ghost.cxx src/t8_forest/t8_forest_iterate.cxx \ src/t8_version.c \ src/t8_vtk.c src/t8_forest/t8_forest_balance.cxx \ + src/t8_forest/t8_forest_transition.cxx \ src/t8_forest/t8_forest_netcdf.cxx \ src/t8_element_shape.c \ src/t8_netcdf.c \ diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx new file mode 100644 index 0000000000..1774dffbf4 --- /dev/null +++ b/src/t8_forest/t8_forest_transition.cxx @@ -0,0 +1,325 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* Description: + * In this file, we define the call-back function that is used to construct transition cells. + */ + +#include "t8_eclass.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* We want to export the whole implementation to be callable from "C" */ +T8_EXTERN_C_BEGIN (); + +/* This is the conformal transition refine function for the 2D quad scheme. + * It will return a values p>1 in order to exchange the current element with a transition cell of type p, + * which is defined in the conformal_quad scheme. */ +int +t8_forest_transition_conformal_quad (t8_forest_t forest, + t8_forest_t forest_from, + t8_locidx_t ltree_id, + t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, + const int is_family, + int num_elements, + t8_element_t *elements[]) +{ + int iface, num_faces, neigh_face, transition_type = 0; + t8_gloidx_t neighbor_tree; + t8_eclass_t neigh_class; + t8_eclass_scheme_c *neigh_scheme; + t8_element_t *element = elements[0], **face_neighbor; + + /* hanging faces can only exist at non-maxlevel elements */ + if (forest_from->maxlevel_existing <= 0 || + ts->t8_element_level (element) < forest_from->maxlevel) { + + num_faces = ts->t8_element_num_faces (element); + + /* We use a binary encoding (depending on the face enumeration), to determine which subelement type to use. + * Every face has a flag parameter, wich is set to 1, if there is a neighbor with a higher level + * and to 0, if the level of the neighbor is at most the level of the element. + * + * f0 1 + * x - - x - - x x - - x - - x + * | | | \ | / | + * | | | \ | / | | f3 | f2 | f1 | f0 | + * f3 x | f2 --> 1 x - - x | 0 --> binary code (according to the face enumeration): | 1 | 0 | 0 | 1 | = 9 in base 10 + * | | | / \ | + * | elem | | / \ | + * x - - - - - x x - - - - - x + * f1 0 + * + * Note, that this procedure is independent of the eclass (we only show an example for the quad scheme). + * Each neighbor-structure will lead to a unique binary code. + * Within the element scheme of the given eclass, this binary code is used to construct the right subelement type, + * in order to remove hanging nodes from the mesh. */ + + for (iface = 0; iface < num_faces; iface++) { + /* Get the element class and scheme of the face neighbor */ + neigh_class = t8_forest_element_neighbor_eclass (forest_from, + ltree_id, element, + iface); + + neigh_scheme = t8_forest_get_eclass_scheme (forest_from, neigh_class); + + /* Allocate memory for the virtual face neighbor */ + face_neighbor = T8_ALLOC (t8_element_t *, 1); + + neigh_scheme->t8_element_new (1, face_neighbor); + + /* Compute the virtual face neighbor of element at this face */ + neighbor_tree = t8_forest_element_face_neighbor (forest_from, ltree_id, + element, + face_neighbor[0], + neigh_scheme, + iface, &neigh_face); + + if (neighbor_tree >= 0) { + if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, + face_neighbor[0], + neigh_scheme)) { + /* Compute transition type as the decimal represenation of the binary concatenation */ + transition_type += 1 << ((num_faces - 1) - iface); + } + } + /* clean-up */ + neigh_scheme->t8_element_destroy (1, face_neighbor); + T8_FREE (face_neighbor); + } + + /* returning the right subelement types */ + if (transition_type == 0) { /* no hanging faces in this case */ + return 0; + } + else if (transition_type == 15) { /* four hanging faces in this case */ + return 1; + } + else { /* use a transition cell of subelements and add 1 to every type, to avoid refine = 1 */ + return transition_type + 1; + } + } + return 0; /* if elem has maxlevel then keep it unchanged since there will never be hanging faces */ +} /* end of t8_forest_transition_conformal_quad */ + +int +t8_forest_transition_conformal_hex (t8_forest_t forest, + t8_forest_t forest_from, + t8_locidx_t ltree_id, + t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, + const int is_family, + int num_elements, + t8_element_t *elements[]) +{ + int iface, num_faces, neigh_face, transition_type = 0; + t8_gloidx_t neighbor_tree; + t8_eclass_t neigh_class; + t8_eclass_scheme_c *neigh_scheme; + t8_element_t *element = elements[0], **face_neighbor; + + /* Hanging faces can only exist at non-maxlevel elements */ + if (forest_from->maxlevel_existing <= 0 || + ts->t8_element_level (element) < forest_from->maxlevel) { + + num_faces = ts->t8_element_num_faces (element); + + /* TODO: Update this comment to HEX. */ + /* We use a binary encoding (depending on the face enumeration), to determine which subelement type to use. + * Every face has a flag parameter, wich is set to 1, if there is a neighbor with a higher level + * and to 0, if the level of the neighbor is at most the level of the element. + * + * f0 1 + * x - - x - - x x - - x - - x + * | | | \ | / | + * | | | \ | / | | f3 | f2 | f1 | f0 | + * f3 x | f2 --> 1 x - - x | 0 --> binary code (according to the face enumeration): | 1 | 0 | 0 | 1 | = 9 in base 10 + * | | | / \ | + * | elem | | / \ | + * x - - - - - x x - - - - - x + * f1 0 + * + * Note, that this procedure is independent of the eclass (we only show an example for the quad scheme). + * Each neighbor-structure will lead to a unique binary code. + * Within the element scheme of the given eclass, this binary code is used to construct the right subelement type, + * in order to remove hanging nodes from the mesh. */ + + for (iface = 0; iface < num_faces; iface++) { + /* Get the element class and scheme of the face neighbor */ + neigh_class = t8_forest_element_neighbor_eclass (forest_from, + ltree_id, element, + iface); + + neigh_scheme = t8_forest_get_eclass_scheme (forest_from, neigh_class); + + /* Allocate memory for the virtual face neighbor */ + // t8_element_t Array mit einem Element + face_neighbor = T8_ALLOC (t8_element_t *, 1); + + neigh_scheme->t8_element_new (1, face_neighbor); + + /* Compute the virtual face neighbor of element at this face */ + neighbor_tree = t8_forest_element_face_neighbor (forest_from, ltree_id, + element, + face_neighbor[0], + neigh_scheme, + iface, &neigh_face); + + /* TODO: Update this code block for hex / sub-pyramids. */ + if (neighbor_tree >= 0) { + if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, + face_neighbor[0], + neigh_scheme)) { + /* Compute transition type as the decimal represenation of the binary concatenation */ + transition_type += 1 << ((num_faces - 1) - iface); + } + } + /* clean-up */ + neigh_scheme->t8_element_destroy (1, face_neighbor); + T8_FREE (face_neighbor); + } + + /* returning the right subelement types */ + if (transition_type == 0) { /* no hanging faces in this case */ + return 0; + } + else if (transition_type == 63) { /* Six hanging faces in this case */ + return 1; + } + else { /* use a transition cell of subelements and add 1 to every type, to avoid refine = 1 */ + return transition_type + 1; + } + } + return 0; /* if elem has maxlevel then keep it unchanged since there will never be hanging faces */ +} + +/* This is the entry function for all transition schemes, called bei forest_adapt. + * The eclass of the current element hands off to the specific refine implementation above. + * Other schemes, for other eclasses can easily be added. */ +int +t8_forest_transition_entry (t8_forest_t forest, + t8_forest_t forest_from, + t8_locidx_t ltree_id, + t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, + const int is_family, + int num_elements, t8_element_t *elements[]) +{ + T8_ASSERT (forest->set_subelements == 1); + T8_ASSERT (forest->is_transitioned == 0 + && forest->set_from->is_transitioned == 0); + + /* TODO: there may be a better way for this than using switch statements and int functions */ + + /* the current element decides over the refine function. Normally, this function returns one fixed value per + * element scheme, but note that it would also possible to switch the refine function within one tree. */ + + switch (ts->t8_element_get_transition_refine_identifier ()) { + case T8_TRANSITION_CONFORMAL_ZERO_REFINE_FUNCTION: + /* if no transition scheme is implemented for the given element/tree, + * then return zero and keep the current element unchanged. + * The default_common implementation of the above function returns 0. */ + return 0; + case T8_TRANSITION_CONFORMAL_QUAD_REFINE_FUNCTION: + return t8_forest_transition_conformal_quad (forest, forest_from, ltree_id, + lelement_id, ts, is_family, + num_elements, elements); + case T8_TRANSITION_CONFORMAL_HEX_REFINE_FUNCTION: + return t8_forest_transition_conformal_hex (forest, forest_from, ltree_id, + lelement_id, ts, is_family, + num_elements, elements); + default: + SC_ABORT + ("The given eclass scheme must specify a valid transition refine function."); + } +} /* end of t8_forest_transition_entry */ + +void +t8_forest_transition (t8_forest_t forest) +{ + T8_ASSERT (forest->set_subelements == 1); + T8_ASSERT (forest->is_transitioned == 0 + && forest->set_from->is_transitioned == 0); + /* in the following, we will call forest_adapt to with the transition + * refinement function in order to transition the forest. The refinement is then + * based on forest->set_from, which must be balanced. */ + + t8_global_productionf ("Into t8_forest_transition.\n"); + + /* Set ghost layers of all processes */ + if (forest->set_from->ghosts == NULL) { + forest->set_from->ghost_type = T8_GHOST_FACES; + t8_forest_ghost_create (forest->set_from); + } + + forest->set_adapt_fn = t8_forest_transition_entry; + forest->set_adapt_recursive = 0; + t8_forest_copy_trees (forest, forest->set_from, 0); + t8_forest_adapt (forest); + + t8_global_productionf ("Done t8_forest_transition.\n"); +} /* end of t8_forest_transition */ + +/* Test whether the forest is transitioned. + * Note 1) We allow non-committed forests in this implementation since this check is used in forest_commit() + * Note 2) This test does only check whether there is at least one subelement in the forest. + * It is not tested whether the forest is conformal or has any other property. */ +int +t8_forest_is_transitioned (t8_forest_t forest) +{ + t8_eclass_scheme_c *tscheme; + t8_locidx_t tree_count, num_trees; + t8_tree_t current_tree; + t8_element_array_t *telements; + t8_locidx_t elem_count, num_elems; + + /* iterate through the forest and check for subelements */ + num_trees = t8_forest_get_num_local_trees (forest); + for (tree_count = 0; tree_count < num_trees; tree_count++) { + current_tree = t8_forest_get_tree (forest, tree_count); + telements = ¤t_tree->elements; + num_elems = (t8_locidx_t) t8_element_array_get_count (telements); + for (elem_count = 0; elem_count < num_elems; elem_count++) { + t8_element_t *current_element = + t8_element_array_index_locidx (telements, elem_count); + tscheme = forest->scheme_cxx->eclass_schemes[current_tree->eclass]; + if (tscheme->t8_element_is_subelement (current_element)) { + /* subelement found -> return true */ + return 1; + } + } + } + + /* only return false if there is no subelement in the forest */ + return 0; +} /* end of t8_forest_is_transitioned */ + +T8_EXTERN_C_END (); diff --git a/src/t8_forest/t8_forest_transition.h b/src/t8_forest/t8_forest_transition.h new file mode 100644 index 0000000000..50517d0189 --- /dev/null +++ b/src/t8_forest/t8_forest_transition.h @@ -0,0 +1,78 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/** \file t8_forest_transition.h + * We define the eliminate_hanging_nodes routine to transform a 2:1 balanced, nonconformal forest + * into a conformal forest. The routine relies on a 2D quad-scheme that has been balanced, such that + * there is a 2:1 balance between all elements. + */ + +/* TODO: begin documenting this file: make doxygen 2>&1 | grep t8_forest_balance */ + +#ifndef T8_FOREST_TRANSITION_H +#define T8_FOREST_TRANSITION_H + +#include +#include + +T8_EXTERN_C_BEGIN (); + +/* In this function, use a binary encoding (depending on the face enumeration), to determine which subelement type to use. + * Every face has a flag parameter, wich is set to 1, if there is a neighbour with a higher level + * and to 0, if the level of the neighbour is at most the level of the element. + * + * f0 1 + * x - - x - - x x - - x - - x + * | | | \ | / | + * | | | \ | / | | f3 | f2 | f1 | f0 | + * f3 x | f2 --> 1 x - - x | 0 --> binary code (according to the face enumeration): | 1 | 0 | 0 | 1 | = 9 in base 10 + * | | | / \ | + * | elem | | / \ | + * x - - - - - x x - - - - - x + * f1 0 + * + * Note, that this procedure is independent of the eclass (we only show an example for the quad scheme). + * Each neighbour-structure will lead to a unique binary code. + * Within the element scheme of the given eclass, this binary code is used to construct the right subelement type, + * in order to remove hanging nodes from the mesh. */ +int t8_forest_transition_adapt (t8_forest_t forest, + t8_forest_t + forest_from, + t8_locidx_t + ltree_id, + t8_locidx_t + lelement_id, + t8_eclass_scheme_c *ts, + int num_elements, + t8_element_t *elements[]); + +/* This function is the point of entry for the hanging-faces-removing subelements. + * In this function, the corresponding callback function for the refine value in forest_adapt is set + * and the forest is adapted. */ +void t8_forest_transition (t8_forest_t forest); + +/* Check whether the forest is transitioned, meaning that subelements exist. */ +int t8_forest_is_transitioned (t8_forest_t forest); + +T8_EXTERN_C_END (); + +#endif /* !T8_FOREST_TRANSITION_H! */ diff --git a/src/t8_schemes/t8_transition/Makefile.am b/src/t8_schemes/t8_transition/Makefile.am new file mode 100644 index 0000000000..5fb585d0f1 --- /dev/null +++ b/src/t8_schemes/t8_transition/Makefile.am @@ -0,0 +1,15 @@ +# This file is part of t8code +# Non-recursive Makefile.am in src/t8_schemes/t8_transition +# Included from toplevel directory + +libt8_installed_headers += \ + src/t8_schemes/t8_transition/t8_transition_cxx.hxx \ + src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx \ + src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx + +libt8_compiled_sources += \ + src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx \ + src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx \ + src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx \ + src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx + diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx new file mode 100644 index 0000000000..10caf35d4a --- /dev/null +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx @@ -0,0 +1,56 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +//#include +#include +#include +#include +#include +#include +#include +#include +#include "t8_transition_conformal_hex_cxx.hxx" + +/* We want to export the whole implementation to be callable from "C" */ +T8_EXTERN_C_BEGIN (); + +t8_scheme_cxx_t * +t8_scheme_new_transition_hex_cxx (void) +{ + t8_scheme_cxx_t *s; + + s = T8_ALLOC_ZERO (t8_scheme_cxx_t, 1); + t8_refcount_init (&s->rc); + + s->eclass_schemes[T8_ECLASS_VERTEX] = NULL; + s->eclass_schemes[T8_ECLASS_LINE] = NULL; /* Standard T8_ECLASS_LINE is used by the quad scheme */ + s->eclass_schemes[T8_ECLASS_QUAD] = new t8_default_scheme_quad_c (); + s->eclass_schemes[T8_ECLASS_HEX] = new t8_subelement_scheme_hex_c (); + s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); + s->eclass_schemes[T8_ECLASS_TET] = NULL; + s->eclass_schemes[T8_ECLASS_PRISM] = NULL; + s->eclass_schemes[T8_ECLASS_PYRAMID] = new t8_default_scheme_pyramid_c (); /* can be used for hybrid meshes - not conformal as long as no conformal transition pyr class exists */ + + return s; +} + +T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx new file mode 100644 index 0000000000..4668301959 --- /dev/null +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -0,0 +1,3108 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* Description: + * This is the low-level structure of 3D hexahedral elements with transition + * cells of pyramidal subelements. */ + +#include +#include +#include +#include +#include +#include "t8_transition_conformal_hex_cxx.hxx" +#include + +/* *INDENT-OFF* */ +/* Connectivity of subelement faces depends on which type of subelement is considered (6 pyramids = 6 types): + * | + * (Z) | / (Y) + * |/_____ (X) + * + * Type 0 = quadliteral face at face 0 from the hexahdron: Type 3: + * f_0 <-> f_0 f_0 <-> f_1 + * f_1 <-> f_0 f_1 <-> f_3 + * f_2 <-> f_0 f_2 <-> f_3 + * f_3 <-> f_0 f_3 <-> f_3 + * f_4 <-> f_4 (assuming a neighboring transition cell) f_4 <-> f_4 + * Type 1: Type 4: + * f_0 <-> f_1 f_0 <-> f_2 + * f_1 <-> f_1 f_1 <-> f_2 + * f_2 <-> f_1 f_2 <-> f_2 + * f_3 <-> f_1 f_3 <-> f_2 + * f_4 <-> f_4 (assuming a neighboring transition cell) f_4 <-> f_4 + * Type 0: Type 5: + * f_0 <-> f_0 f_0 <-> f_3 + * f_1 <-> f_2 f_1 <-> f_3 + * f_2 <-> f_0 f_2 <-> f_3 + * f_3 <-> f_2 f_3 <-> f_3 + * f_4 <-> f_4 (assuming a neighboring transition cell) f_4 <-> f_4 + */ + +const int subelement_face_dual[6][5] = { + {0, 0, 0, 0, 4}, + {1, 1, 1, 1, 4}, + {0, 2, 0, 2, 4}, + {1, 3, 3, 3, 4}, + {2, 2, 2, 2, 4}, + {3, 3, 3, 3, 4} + }; + +/* Connectivity of a subelements location within a transition cell + * and the parent hexs faces: + * location[0] = 0 -> parents dual face = 1 + * location[0] = 1 -> parents dual face = 0 + * location[0] = 2 -> parents dual face = 3 + * location[0] = 3 -> parents dual face = 2 + * location[0] = 4 -> parents dual face = 5 + * location[0] = 5 -> parents dual face = 4 */ +const int subelement_location_to_parent_dual_face[6] = { 1, 0, 3, 2, 5, 4 }; + +/* Connectivity of a subelements location within a transition cell (only if the subelements are not splitted) + * --> gets subelement_duals + */ +const int subelement_face_to_dual_subelement[6][5] = { + { 2, 3, 4, 5, -1 }, + { 2, 3, 4, 5, -1 }, + { 0, 1, 4, 5, -1 }, + { 0, 1, 4, 5, -1 }, + { 0, 1, 2, 3, -1 }, + { 0, 1, 2, 3, -1 }, +}; +/* Connectivity of a subelements location within a transition cell + * and the parent hexs faces: Wie in mit Koordinatensystem in Davids Masterarbeit + * starte links, dann rechts, vorne, hinten, unten oben. + * location[0] = 0 (left) -> parents face = 0 + * location[0] = 1 (right) -> parents face = 1 + * location[0] = 2 (front) -> parents face = 2 + * location[0] = 3 (back) -> parents face = 3 + * location[0] = 4 (bottom) -> parents face = 4 + * location[0] = 5 (up) -> parents face = 5 + */ +const int subelement_location_to_parent_face[6] = { 0, 1, 2, 3, 4, 5}; +/* *INDENT-ON* */ + +/* We want to export the whole implementation to be callable from "C" */ +T8_EXTERN_C_BEGIN (); + +/* This function is used by other element functions and we thus need to + * declare it up here */ +t8_linearidx_t t8_element_get_linear_id (const t8_element_t *elem, + int level); + +int +t8_subelement_scheme_hex_c::t8_element_maxlevel (void) const +{ + return P8EST_OLD_QMAXLEVEL; +} + +/* *INDENT-OFF* */ +t8_eclass_t +t8_subelement_scheme_hex_c::t8_element_child_eclass (int childid) const +{ + T8_ASSERT (0 <= childid && childid < P8EST_CHILDREN); + + return T8_ECLASS_HEX; +} + +int +t8_subelement_scheme_hex_c::t8_element_level (const t8_element_t *elem) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + T8_ASSERT (t8_element_is_valid (elem)); + return (int) ((const t8_hex_with_subelements *) phex_w_sub)->p8q.level; +} + +void +t8_subelement_scheme_hex_c::t8_element_copy (const t8_element_t *source, + t8_element_t *dest) const +{ + const t8_hex_with_subelements *phex_w_sub_source = + (const t8_hex_with_subelements *) source; + t8_hex_with_subelements *phex_w_sub_dest = + (t8_hex_with_subelements *) dest; + + const p8est_quadrant_t *q = &phex_w_sub_source->p8q; + p8est_quadrant_t *r = &phex_w_sub_dest->p8q; + + T8_ASSERT (t8_element_is_valid (source)); + T8_ASSERT (t8_element_is_valid (dest)); + if (q == r && + phex_w_sub_source->transition_type == + phex_w_sub_dest->transition_type && + phex_w_sub_source->subelement_id == phex_w_sub_dest->subelement_id) { + /* Do nothing if they are already the same hexahedra. */ + return; + } + *r = *q; + + t8_element_copy_subelement_values (source, dest); + //t8_element_copy(q,r); + // t8_element_copy_surround (q, r); +} + +int +t8_subelement_scheme_hex_c::t8_element_compare (const t8_element_t *elem1, + const t8_element_t *elem2) + const +{ + const t8_hex_with_subelements *phex_w_sub_elem1 = + (const t8_hex_with_subelements *) elem1; + const t8_hex_with_subelements *phex_w_sub_elem2 = + (const t8_hex_with_subelements *) elem2; + + const p8est_quadrant_t *q = &phex_w_sub_elem1->p8q; + const p8est_quadrant_t *r = &phex_w_sub_elem2->p8q; + + T8_ASSERT (t8_element_is_valid (elem1)); + T8_ASSERT (t8_element_is_valid (elem2)); + + int compare = p8est_quadrant_compare (q, r); + + if (compare == 0 && (t8_element_is_subelement (elem1) + || t8_element_is_subelement (elem2))) { + // t8_debugf ("Caution, t8_element_compare is used with subelements.\n"); + if (t8_element_is_subelement (elem1) + && t8_element_is_subelement (elem2)) { + /* Caution: The compare function is used for two subelements. */ + + if (phex_w_sub_elem1->transition_type == + phex_w_sub_elem2->transition_type + && phex_w_sub_elem1->subelement_id == + phex_w_sub_elem2->subelement_id) { + /* both subelements are identical */ + return 0; + } + /* return != 0 to avoid debug abortion in t8_ghost_add_remote */ + return 1; + } + else if (t8_element_is_subelement (elem1)) { + return -1; /* elem1 is subelement and therefore smaller */ + } + else if (t8_element_is_subelement (elem2)) { + return 1; /* elem2 is subelement and therefore smaller */ + } + } + + /* Note that for subelements, their parent quadrant is compared at this point */ + return compare; + + // SC_ABORT_NOT_REACHED(); +} + +void +t8_subelement_scheme_hex_c::t8_element_parent (const t8_element_t *elem, + t8_element_t *parent) const +{ + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_parent = + (t8_hex_with_subelements *) parent; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + p8est_quadrant_t *r = &phex_w_sub_parent->p8q; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (parent)); + + if (t8_element_is_subelement (elem)) { + phex_w_sub_parent->p8q = phex_w_sub_elem->p8q; + } + else { + p8est_quadrant_parent (q, r); + } + + /* the parent of any element will never be a subelement */ + t8_element_reset_subelement_values (parent); + + // t8_element_copy_surround (q, r); + + // SC_ABORT_NOT_REACHED(); +} + +void +t8_subelement_scheme_hex_c::t8_element_sibling (const t8_element_t *elem, + int sibid, + t8_element_t *sibling) const +{ + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_sibling = + (t8_hex_with_subelements *) sibling; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + p8est_quadrant_t *r = &phex_w_sub_sibling->p8q; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (sibling)); + + p8est_quadrant_sibling (q, r, sibid); + // t8_element_copy_surround (q, r); + + // SC_ABORT_NOT_REACHED(); +} + +int +t8_subelement_scheme_hex_c::t8_element_num_faces (const t8_element_t *elem) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + return (t8_element_is_subelement (elem) ? T8_HEX_SUBELEMENT_FACES : + P8EST_FACES); +} + +int +t8_subelement_scheme_hex_c::t8_element_max_num_faces (const t8_element_t + *elem) const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + return P8EST_FACES; +} + +int +t8_subelement_scheme_hex_c::t8_element_num_children (const t8_element_t + *elem) const +{ + /* Note that children of subelements equal the children of the parent hexahedra. + * Therefore, the number of children of a subelement equals P8EST_CHILDREN */ + T8_ASSERT (t8_element_is_valid (elem)); + return P8EST_CHILDREN; +} + +/* *INDENT-OFF* */ +/* indent bug, indent adds a second "const" modifier */ + +int +t8_subelement_scheme_hex_c::t8_element_num_siblings (const t8_element_t * + elem) const + +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + + //no hanging nodes + if (phex_w_sub->transition_type == 0){ + //eigentlich normale funktion t8_element_num_siblings + //könnte auch 2hoch dim returnen + return P8EST_CHILDREN; + } + + int num_hanging_faces = 0; + int iface; + for (iface = 0; iface < P8EST_FACES; iface++) { + /* Count the number of ones of the binary transition type. + * This number equals the number of hanging faces. */ + + // binary shift << 1 Left-shift, d.h. *2¹ + // Right shift >> 1 Right-shift, d.h. *2⁻¹ + // & (bitwise AND operator, num_hanging_faces wird nur erhöht, wenn mind. ein bit von transition_type != 0 ist. ) + num_hanging_faces += + (phex_w_sub->transition_type & (1 << iface)) >> iface; + } + return P8EST_FACES + 3*num_hanging_faces; +} + +int +t8_subelement_scheme_hex_c::t8_element_num_face_children (const t8_element_t + *elem, + int face) const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + /* if we use hex scheme without set_transition, then we are only balanced + * and four neighbors are possible */ + return 4; + +} + +//Wenn elements transition cell, dann immer alle seiten bis auf die Grundseite (f4) +int +t8_subelement_scheme_hex_c::t8_element_neighbor_is_sibling (const + t8_element_t + *elem, + const int face) + const +{ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_subelement (elem)); + + if (face == 0 || face == 1 || face == 2 || face == 3) { + return 1; + } + + return 0; +} + + +int +t8_subelement_scheme_hex_c::t8_element_get_num_sibling_neighbors_at_face (const t8_element_t *elem, + const int face) const +{ + const t8_hex_with_subelements *hex_w_sub = + (const t8_hex_with_subelements *) elem; + + + const t8_element_t *elem2 = (const t8_element *) elem; + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_subelement (elem)); + T8_ASSERT (face == 0 || face == 1 || face == 2 || face == 3); + +int location[3] = { }; + //( location[0] = face_number of transition cell, location[1] = if splitted or not ( 1 = splitted ), location[2] = sub_id + t8_element_get_location_of_subelement (elem, location); + int split = location[1]; + int hex_face = location[0]; + int neigh_hex_face; + int transition_type; +if( split == 1){ + return 1; +} +else{ +neigh_hex_face = subelement_face_to_dual_subelement[hex_face][face]; +transition_type = hex_w_sub->transition_type; + +if ((transition_type & (int) pow(2, 5 - neigh_hex_face)) != 0 ){ + return 2; +}else{ + return 1; +} + +} +} + +int +t8_subelement_scheme_hex_c::t8_element_get_transition_refine_identifier () const +{ + + return T8_TRANSITION_CONFORMAL_HEX_REFINE_FUNCTION; +} +/* *INDENT-ON* */ + +int +t8_subelement_scheme_hex_c::t8_element_get_face_corner (const t8_element_t + *elem, int face, + int corner) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + if (!t8_element_is_subelement (elem)) { + + //face has to be between 0 and 4 + //Corner has to be between 0 and 4 + T8_ASSERT (0 <= face && face < P8EST_FACES); + T8_ASSERT (0 <= corner && corner < 4); + + return p8est_face_corners[face][corner]; + } + else { + int t8_face_corners_subelement[5][4] = { + {0, 2, 4 ,-1}, //f0 + {1, 3, 4, -1}, //f1 + {0, 1, 4, -1}, //f2 + {2, 3, 4, -1}, //f3 + {0, 1, 2, 3} //f4 + }; + T8_ASSERT (0 <= face && face < T8_HEX_SUBELEMENT_FACES); + T8_ASSERT (0 <= corner && corner < 5); + + return t8_face_corners_subelement[face][corner]; + } + +} + +int +t8_subelement_scheme_hex_c::t8_element_get_corner_face (const t8_element_t + *elem, int corner, + int face) const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + SC_ABORT ("This function is not implemented yet.\n"); + return 0; +} + + +void +t8_subelement_scheme_hex_c::t8_element_child (const t8_element_t *elem, + int childid, + t8_element_t *child) const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_child = + (t8_hex_with_subelements *) child; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + p8est_quadrant_t *r = &phex_w_sub_child->p8q; + + const p4est_qcoord_t shift = P8EST_QUADRANT_LEN (q->level + 1); + + /* it should not be possible to construct a child of a subelement */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (child)); + T8_ASSERT (p8est_quadrant_is_extended (q)); + T8_ASSERT (q->level < P8EST_OLD_QMAXLEVEL); + T8_ASSERT (0 <= childid && childid < P8EST_CHILDREN); + + r->x = childid & 0x01 ? (q->x | shift) : q->x; + r->y = childid & 0x02 ? (q->y | shift) : q->y; + r->z = childid & 0x04 ? (q->z | shift) : q->z; + r->level = q->level + 1; + T8_ASSERT (p8est_quadrant_is_parent (q, r)); +} + +void +t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t + *elem, const int face, + const int num_neighbors, + t8_element_t + *neighbor_at_face[], + int *neigh_face) +{ + T8_ASSERT (t8_element_is_subelement (elem)); + T8_ASSERT (t8_element_neighbor_is_sibling (elem, face)); + T8_ASSERT ((num_neighbors == 1) || (num_neighbors == 2)); + T8_ASSERT (t8_element_is_valid (neighbor_at_face[0])); + + /* source = elem, destination = neighbor at face. --> They have the same anchor node + Morton index + level.*/ + t8_element_copy (elem, neighbor_at_face[0]); +/* Expand neighbor_at_face to a subelement (subelement_id + transititon_type) + copy it into phex_w_sub_neighbor_at_face*/ + t8_hex_with_subelements * + phex_w_sub_neighbor_at_face = + (t8_hex_with_subelements *) neighbor_at_face[0]; + + //iterator variable + int iter; + //Get informations about the location of the subelement. + int + num_siblings = t8_element_num_siblings (elem); + int location[3] = { }; + //( location[0] = face_number of transition cell, location[1] = if splitted or not ( 1 = splitted ), location[2] = sub_id + t8_element_get_location_of_subelement (elem, location); + + //Create a temporary variable to store the possible subelement_id of the neighbor + int subelement_id_tmp = 0; + int transition_type_tmp = 0; + int amount_subelements = 0; + int transition_type = t8_element_get_transition_type(elem); + int subelement_id = t8_element_get_subelement_id(elem); + int neigh_hex_face; + int hlp; + + /* There are 4 cases that can happen: + * 1. The subelement itself is not splitted, and its face neighbor is also not splitted. + * 2. The subelement itself is not splitted, but its face neighbor is splitted. (Two face neighbors) + * 3. The subelement itself is splitted, but its face neighbor is not splitted. + * 4. The subelement itself is splitted, and its face neighbor is also splitted. + */ + + neigh_face[0] = subelement_face_dual[location[0]][face]; + + //First check if (the own) face is splitted. + if(location[1] == 0){ //Not splitted + + //get hex_face_number of the face_neighbored subelement + // neigh_hex_face is only correct, if the neighbor lies not at the same hex face. + neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; + // t8_productionf("das ist neigh hex face (not splitted) : %i\n", neigh_hex_face); + + /*Check if the dual subelement is splitted. If it's splitted,the element has two neighbors + * as siblings (case 2). Then we always take the left, front or down (in this order) subelement (the subelement with the lower sub + * element ID). If the transition type is = 1 at the hex_face, it's splitted.*/ + +//-----------------------------CASE 1-------------------------------------------------------- + +//make rightshift until only the bits for the faces before our neighbors face are left. + transition_type_tmp = transition_type >> (5 - neigh_hex_face); + + amount_subelements = 0; + + + int i = (int) pow(2,5 - neigh_hex_face); + + if((transition_type & i) == 0){ //neighbor not splitted + + for(iter = 0 ; iter <= neigh_hex_face ; iter++){ + + //Count the elements until our neighbored hex_face. + if(((transition_type_tmp >> iter ) & 1) != 0 ){ + amount_subelements += 4; + } + else{ + amount_subelements += 1; + } + } + + + //The subelement_id of the neighbor is then the amount of subelements till then - 1 + subelement_id_tmp = amount_subelements - 1 ; + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; + + } +//-------------------------CASE 2-------------------------------------- + else { //neighbor is splitted. We have to return 2 subelements. + amount_subelements = 0; + int subelement_id_tmp2 = 0; // In here we store the second subelement ID in case 2 if elem has two neighbors + /* For case 2 we need a second face neighbor */ + + t8_hex_with_subelements * + phex_w_sub_neighbor_at_face2 = + (t8_hex_with_subelements *) neighbor_at_face[1]; + + t8_element_copy (elem, neighbor_at_face[1]); + + + + //make rightshift until only the bits for the faces before our neighbors face are left. + transition_type_tmp = transition_type >> (5 - neigh_hex_face); + + for(iter = 0 ; iter <= neigh_hex_face ; iter++){ + + //Count the elements until our neighbored hex_face. + if(((transition_type_tmp >> iter ) & 1) != 0 ){ + amount_subelements += 4; + } + else{ + amount_subelements += 1; + } + } + + + //If we know the hex_face_number of the neighbored element, we know which subelement_IDs to take. + if (location[0] == 0){ //For hex_face 0 its always the "front" two sub-ids + subelement_id_tmp = amount_subelements - 4; + subelement_id_tmp2 = amount_subelements - 2; + } + if (location[0] == 1){ //For hex_face 1 its always the right to sub-ids + subelement_id_tmp = amount_subelements - 3; + subelement_id_tmp2 = amount_subelements - 1; + } + if (location[0] == 2){ //for hex_face 2 its the "front" sub-ids + if( ( face == 0 ) || ( face == 1 ) ){ + subelement_id_tmp = amount_subelements - 4; + subelement_id_tmp2 = amount_subelements - 2; + } + if( ( face == 2 ) || ( face == 3 ) ){ + subelement_id_tmp = amount_subelements - 4; + subelement_id_tmp2 = amount_subelements - 3; + } + } + if (location[0] == 3){ //for hex_face 3 its the "back" sub-ids + if( ( face == 0 ) || ( face == 1 ) ){ + subelement_id_tmp = amount_subelements - 3; + subelement_id_tmp2 = amount_subelements - 1; + } + else if( ( face == 2 ) || ( face == 3 ) ){ + subelement_id_tmp = amount_subelements - 2; + subelement_id_tmp2 = amount_subelements - 1; + } + } //for hex_face 4 ist the "down" sub-ids + if (location[0] == 4){ + subelement_id_tmp = amount_subelements - 4; + subelement_id_tmp2 = amount_subelements - 3; + } + if (location[0] == 5){ //for hex_face 5 its the "up" sub-ids + subelement_id_tmp = amount_subelements - 2; + subelement_id_tmp2 = amount_subelements - 1; + } + + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; + phex_w_sub_neighbor_at_face2->subelement_id = subelement_id_tmp2; + + if ( neigh_face != NULL ){ + neigh_face[1] = neigh_face[0]; + } + } +} + + + //-------------------------CASE 3-------------------------------------- + else{ + //The own face is splitted + //get hex_face_number of the face_neighbored subelement + //Condition that the neighbor lies not on the same hex face: + hlp = 0; +//hex face 0 and 1 + if( location[0] == 0 || location[0] == 1){ + if( ((location[2] & 2) == 0 ) && (face == 1)) {//front + hlp += 1 ; + } + if( ((location[2] & 2) != 0 ) && (face == 0)) {//back + hlp += 1 ; + } + + if( ((location[2] & 1) == 0 ) && (face == 3)) {//bottom + hlp +=1 ; + } + if( ((location[2] & 1) != 0 ) && (face == 2)) {//up + hlp +=1 ; + } + } + //hex face 2 and 3 + if( location[0] == 2 || location[0] == 3){ + if( ((location[2] & 4) == 0 ) && (face == 1)) {//left + hlp +=1 ; + } + if( ((location[2] & 4) != 0 ) && (face == 0)) {//right + hlp +=1 ; + } + + if( ((location[2] & 1) == 0 ) && (face == 3)) {//bottom + hlp +=1 ; + } + if( ((location[2] & 1) != 0 ) && (face == 2)) {//up + hlp +=1 ; + } + } + + //hex face 4 and 5 + if( location[0] == 4 || location[0] == 5){ + if( ((location[2] & 4) == 0 ) && (face == 1)) {//left + hlp +=1 ; + } + if( ((location[2] & 4) != 0 ) && (face == 0)) {//right + hlp +=1 ; + } + + if( ((location[2] & 2) == 0 ) && (face == 3)) {//front + hlp +=1 ; + } + if( ((location[2] & 2) != 0 ) && (face == 2)) {//back + hlp +=1 ; + } + } + +//if none of these conditions is true, we are in case 3 +neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; +if( (hlp == 0) && ((transition_type & (int) pow(2,5 - neigh_hex_face)) == 0)){ + + if((transition_type & (int) pow(2,5 - neigh_hex_face)) == 0){ //neighbor not splitted + + //it's not possible, that the neighbor lies on the same hex face here, because the own face is splitted here and if the neighbor would lie on the same face + //its face would obviously be splitted too. + neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; + //make rightshift until only the bits for the faces before our neighbors face are left. + transition_type_tmp = transition_type >> (5 - neigh_hex_face); + + for(iter = 0; iter <= neigh_hex_face; iter++){ + + //Count the elements until our neighbored hex_face. + if(((transition_type_tmp >> iter ) & 1) != 0 ){ + amount_subelements += 4; + } + else{ + amount_subelements += 1; + } + } + + subelement_id_tmp = amount_subelements - 1; + + } + +phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; +} + + +//---------------------------CASE 4-------------------------------------- + else{ + //It's possible, that the neighbored subelement has the same face_hex number as the element itself + // + amount_subelements = 0; + subelement_id_tmp = 0; + hlp = 0; + + +//Now we need the subelement_id_type (location[2]) to determine the exact location of the +//subelement in the transition cell + + /* We have to go through all hex_faces + */ + if(location[0] == 0 || location[0] == 1){ // hex_face = 0/1 + if((location[2] & 2) != 0 ){//back + if(face == 0){ //then it's the element before. + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; + hlp += 1; + } + } + else{ + if(face == 1){ //then it's the element after. + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; + hlp += 1; + } + } + if((location[2] & 1) != 0){//up + if(face == 2){ //then it's the element below + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; + hlp += 1; + } + } + else{ //down + if(face == 3){// down + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 2; + hlp += 1; + } + } + } + + if(location[0] == 2 || location[0] == 3){ // hex_face = 2/3 + if((location[2] & 4) != 0 ){ //right + if( face == 0){ //then it's the element before. + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; + hlp += 1; + } + } + else{ //left + if ( face == 1 ){ // then it's the next element + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; + hlp += 1; + + } + } + if((location[2] & 1) != 0){//up + if(face == 2 ){ //then it's the element below + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; + hlp += 1; + } + } + else{ //down + if(face == 3){//then its the element above + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 2; + hlp += 1; + } + } + } + + if(location[0] == 4 || location[0] == 5){ // hex_face = 4/5 + if((location[2] & 4) != 0 ){//right + if(face == 0){ //then it's the element before. + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; + hlp += 1; + } + else{ //left + if(face == 1){ //then it's the next element. + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; + hlp += 1; + } + } + } + if((location[2] & 2) != 0){//back + if(face == 2){ //then it's the element in front + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; + hlp += 1; + } + } + else{ //front + if(face == 3){ + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 2; + hlp += 1; + } + } + } + neigh_face[0] = subelement_location_to_parent_dual_face[face]; + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; + +if( hlp = 0 ){ //if the neighbor lies not on the same hex face as elem + //get hex_face_number of the face_neighbored subelement + neigh_face[0] = subelement_face_dual[location[0]][face]; + + neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; + + + //The neighbored element is not at the same hex face + //First count the amount of subelements until the hex_face of the neighbored subelement is reached. + //make rightshift until only the bits for the faces before our neighbors face are left. + transition_type_tmp = transition_type >> (5 - neigh_hex_face); + + for(iter = 0; iter <= neigh_hex_face; iter++){ + + //Count the elements until our neighbored hex_face. + if(((transition_type_tmp >> iter ) & 1) != 0 ){ + amount_subelements += 4; + } + else{ + amount_subelements += 1; + } + } + + + //For the hex_faces 0 or 1 all possible neighbors will have a subelement_id that is greater than the own subelement_id + if( (location[0] == 0) || (location[0] == 1)){ + if(face == 0){ + subelement_id_tmp = amount_subelements - 4 + phex_w_sub_neighbor_at_face->subelement_id; + } + if(face == 1){ + subelement_id_tmp = amount_subelements - 5 + phex_w_sub_neighbor_at_face->subelement_id; + } + if(face == 2 || face == 3){ + //We have to distinguish if the element is in the front or back. + if((location[2] & 2) == 0){//front + subelement_id_tmp = amount_subelements - 4 + location[0]; + } + else{ + subelement_id_tmp = amount_subelements - 2 + location[0]; + } + } + } + /* Because all faces = 0 of subelements at hex face 2,3,4 and 5 touch the hex_face 0, + * all faces = 1 touch hex_face 1 and all faces = 2 touch the hex_face 4, + * and all faces = 3 touch hex_face 5, we can hardcode these cases */ + else{ + if( face == 0){ + //We have to distinguish if the element is in the front or back. + if(location[0] >= 4 ){ + if((location[2] & 2) == 0){//front + if(location[0] == 4){ // we are at hex_face 4 + subelement_id_tmp = 0; + } + else{ //hex face 5 + subelement_id_tmp = 2; + } + } + + else{//back + if(location[0] == 4){ // we are at hex_face 4 + subelement_id_tmp = 1; + } + if(location[0] == 5){ + subelement_id_tmp = 4; + } + } + } + if (location[0] <= 3 ) { //only for hex faces 2 and the the subelements can be up or down + + if((location[2] & 1) == 0){//down + if(location[0] == 2){ // we are at hex_face 2 + subelement_id_tmp = 0; + } + if(location[0] == 3){ + subelement_id_tmp = 1; + } + else{ //up + if(location[0] == 2){ // we are at hex_face 2 + subelement_id_tmp = 2; + } + if(location[0] == 3){ + subelement_id_tmp = 3; + } + } + } + + } + + } + //same for face = 1 + if(face == 1){ + //We have to distinguish if the element is in the front or back. + if((location[2] & 2) == 0){//front + if(location[0] == 4){ // we are at hex_face 4 + subelement_id_tmp = amount_subelements - 4; + } + if(location[0] == 5){ + subelement_id_tmp = amount_subelements - 2; + } + } + else{//back + if(location[0] == 4){ // we are at hex_face 4 + subelement_id_tmp = amount_subelements - 3; + } + if(location[0] == 5){ + subelement_id_tmp = amount_subelements - 1; + } + } + if(location[2] & 1 == 0){//down + if(location[0] == 2){ // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 4; + } + if(location[0] == 3){ + subelement_id_tmp = amount_subelements - 3; + } + else{ //up + if(location[0] == 2){ // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 2; + } + if(location[0] == 3){ + subelement_id_tmp = amount_subelements - 1; + } + } + } + + } + //same for face = 2 + if(face == 3 || face == 2){ + //We have to distinguish if the element is in the front or back. + if((location[2] & 4) == 1){//left + if(location[0] == 2){ // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 4; + } + if(location[0] == 3){ + subelement_id_tmp = amount_subelements - 2; + } + } + else{//right + if(location[0] == 2){ // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 3; + } + if(location[0] == 3){ + subelement_id_tmp = amount_subelements - 1; + } + } + + } + + } + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; + } + } + +} + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; +} + + + + +void +t8_subelement_scheme_hex_c::t8_element_children (const t8_element_t *elem, + int length, + t8_element_t *c[]) const +{ + /* if elem is a subelement, then this function will construct the children of its parent p8est quadrant */ + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements **phex_w_sub_children = + (t8_hex_with_subelements **) c; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + + int ichild; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (length == P8EST_CHILDREN); + +#ifdef T8_ENABLE_DEBUG + { + int i; + for (i = 0; i < P8EST_CHILDREN; i++) { + T8_ASSERT (t8_element_is_valid (c[i])); + } + } +#endif + + /* set coordinates and levels of the children */ + p8est_quadrant_children (q, &phex_w_sub_children[0]->p8q, + &phex_w_sub_children[1]->p8q, + &phex_w_sub_children[2]->p8q, + &phex_w_sub_children[3]->p8q, + &phex_w_sub_children[4]->p8q, + &phex_w_sub_children[5]->p8q, + &phex_w_sub_children[6]->p8q, + &phex_w_sub_children[7]->p8q +); + + for (ichild = 0; ichild < P8EST_CHILDREN; ++ichild) { + t8_element_reset_subelement_values (c[ichild]); + // t8_element_copy_surround (q, &phex_w_sub_children[ichild]->p8q); + } + + // SC_ABORT_NOT_REACHED(); +} + +int +t8_subelement_scheme_hex_c::t8_element_child_id (const t8_element_t *elem) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + const p8est_quadrant_t *q = &phex_w_sub->p8q; + + T8_ASSERT (t8_element_is_valid (elem)); + + return (t8_element_is_subelement (elem) ? phex_w_sub->subelement_id : + p8est_quadrant_child_id (q)); + + +} + +int +t8_subelement_scheme_hex_c::t8_element_ancestor_id (const t8_element_t *elem, + int level) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + const p8est_quadrant_t *q = &phex_w_sub->p8q; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + return p8est_quadrant_ancestor_id (q, level); +} + +int +t8_subelement_scheme_hex_c::t8_element_is_family (t8_element_t **fam) const +{ + /* Note that this test is very rudimentary, especially when there subelements are in fam */ + t8_hex_with_subelements **phex_w_sub_family = + (t8_hex_with_subelements **) fam; + +#ifdef T8_ENABLE_DEBUG + { + int i; + int num_siblings = t8_element_num_siblings (fam[0]); + for (i = 0; i < num_siblings; i++) { + T8_ASSERT (t8_element_is_valid (fam[i])); + } + } +#endif + + /* Subelements can not be refined into other elements of a higher level. + * So if the first element of fam is a subelement, we assume that the following num_siblings + * many elements are its siblings and therefore form a family. */ + if (phex_w_sub_family[0]->transition_type != 0) { + return 1; + } + /* If the first element of fam is no subelement we check the following elements of fam */ + else { + /* If any of the following elements is a subelement, then they can not form a family */ + if ((phex_w_sub_family[1]->transition_type != 0) || + (phex_w_sub_family[2]->transition_type != 0) || + (phex_w_sub_family[3]->transition_type != 0) || + (phex_w_sub_family[4]->transition_type != 0) || + (phex_w_sub_family[5]->transition_type != 0) || + (phex_w_sub_family[6]->transition_type != 0) || + (phex_w_sub_family[7]->transition_type != 0)) { + return 0; + } + /* If all elements of fam are no subelements, then we can use the p8est check is_family */ + else { + return p8est_quadrant_is_family (&phex_w_sub_family[0]->p8q, + &phex_w_sub_family[1]->p8q, + &phex_w_sub_family[2]->p8q, + &phex_w_sub_family[3]->p8q, + &phex_w_sub_family[4]->p8q, + &phex_w_sub_family[5]->p8q, + &phex_w_sub_family[6]->p8q, + &phex_w_sub_family[7]->p8q); + } + } +} + +void +t8_subelement_scheme_hex_c::t8_element_set_linear_id (t8_element_t *elem, + int level, + t8_linearidx_t id) + const +{ + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; + p8est_quadrant_t *q = &phex_w_sub->p8q; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); + T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << P8EST_DIM * level); + + p8est_quadrant_set_morton (q, level, id); + +} + +t8_linearidx_t + t8_subelement_scheme_hex_c::t8_element_get_linear_id (const t8_element_t + *elem, + int level) const +{ + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; + p8est_quadrant_t *q = &phex_w_sub->p8q; + + /* Note that the id of a subelement equals the id of its parent quadrant. + * Therefore, the binary search (for example used in the leaf_face_neighbor function) + * will find a random subelement of the transition cell which might not be the desired neighbor of a given element. */ + T8_ASSERT (t8_element_subelement_values_are_valid (elem)); + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); + + // return p8est_quadrant_linear_id ((p8est_quadrant_t *) q, level); + return p8est_quadrant_linear_id ( q, level); +} + +void +t8_subelement_scheme_hex_c::t8_element_first_descendant (const t8_element_t + *elem, + t8_element_t *desc, + int level) const +{ + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_desc = + (t8_hex_with_subelements *) desc; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + p8est_quadrant_t *r = &phex_w_sub_desc->p8q; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (desc)); + T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); + + p8est_quadrant_first_descendant (q, r, level); + + /* We allow constructing a last descendant from a subelement. + * Keep in mind, that transforming a hex element to a subelement does not change the + * p8est quadrant. Therefore, we are constructing the last descendant of the parent + * hex element of the given subelement. Since the last descendant is not meant to be + * a subelement, we reset the corresponding subelement values. */ + t8_element_reset_subelement_values (desc); + + // SC_ABORT_NOT_REACHED(); +} + +void +t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t + *elem, + t8_element_t *desc, + int level) const +{ + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_desc = + (t8_hex_with_subelements *) desc; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + p8est_quadrant_t *r = &phex_w_sub_desc->p8q; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (desc)); + T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); + + p8est_quadrant_last_descendant (q, r, level); + + /* We allow constructing a last descendant from a subelement. + * Keep in mind, that transforming a hex element to a subelement does not change the + * p8est quadrant. Therefore, we are constructing the last descendant of the parent + * hex element of the given subelement. Since the last descendant is not meant to be + * a subelement, we reset the corresponding subelement values. */ + t8_element_reset_subelement_values (desc); + + //t8_global_productionf("das ist sub id nach zurück setzten %i\n", phex_w_sub_desc->subelement_id); + + // SC_ABORT_NOT_REACHED(); +} + +void +t8_subelement_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, + t8_element_t *elem2, + int level) const +{ + const t8_hex_with_subelements *phex_w_sub_elem1 = + (const t8_hex_with_subelements *) elem1; + t8_hex_with_subelements *phex_w_sub_elem2 = + (t8_hex_with_subelements *) elem2; + + const p8est_quadrant_t *q = &phex_w_sub_elem1->p8q; + p8est_quadrant_t *r = &phex_w_sub_elem2->p8q; + + t8_linearidx_t id; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem1)); + + T8_ASSERT (t8_element_is_valid (elem1)); + T8_ASSERT (t8_element_is_valid (elem2)); + T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); + p8est_quadrant_successor ((p8est_quadrant_t *) elem1, + (p8est_quadrant_t *) elem2); +} + +void +t8_subelement_scheme_hex_c::t8_element_nca (const t8_element_t *elem1, + const t8_element_t *elem2, + t8_element_t *nca) const +{ + const t8_hex_with_subelements *phex_w_sub_elem1 = + (const t8_hex_with_subelements *) elem1; + const t8_hex_with_subelements *phex_w_sub_elem2 = + (const t8_hex_with_subelements *) elem2; + t8_hex_with_subelements *phex_w_sub_nca = + (t8_hex_with_subelements *) nca; + + const p8est_quadrant_t *q1 = &phex_w_sub_elem1->p8q; + const p8est_quadrant_t *q2 = &phex_w_sub_elem2->p8q; + p8est_quadrant_t *r = &phex_w_sub_nca->p8q; + + T8_ASSERT (t8_element_is_valid (elem1)); + T8_ASSERT (t8_element_is_valid (elem2)); +#if 0 + /* TODO: This assertions throws an error since it expects a 3D hex. + * this does not make sense. investigate. */ + T8_ASSERT (t8_element_surround_matches (q1, q2)); +#endif + + /* In case of subelements, we use the parent quadrant and construct nca of the parent quadrant */ + t8_element_reset_subelement_values (nca); + p8est_nearest_common_ancestor (q1, q2, r); + // t8_element_copy_surround (q1, r); + + // SC_ABORT_NOT_REACHED(); +} + +//Nummerierung der Seiten(der Pyramiden) wie in Davids Masterarbeit +t8_element_shape_t +t8_subelement_scheme_hex_c::t8_element_face_shape (const t8_element_t *elem, + int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + if( t8_element_is_subelement (elem)){ + if(face == 4){ + return T8_ECLASS_QUAD; + } + else{ + return T8_ECLASS_TRIANGLE; + } + + } + else{ + return T8_ECLASS_QUAD; + } +} + + +void +t8_subelement_scheme_hex_c::t8_element_children_at_face (const t8_element_t + *elem, int face, + t8_element_t + *children[], + int num_children, + int *child_indices) + const +{ + int child_ids_local[4], i, *child_ids; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (num_children == 4); + +#ifdef T8_ENABLE_DEBUG + { + int j; + for (j = 0; j < P4EST_CHILDREN; j++) { + T8_ASSERT (t8_element_is_valid (children[j])); + } + } +#endif + T8_ASSERT (0 <= face && face < P8EST_FACES); + T8_ASSERT (num_children == t8_element_num_face_children (elem, face)); + + if (child_indices != NULL) { + child_ids = child_indices; + } + else { + child_ids = child_ids_local; + } + /* + * Compute the child id of the first and second child at the face. + * + * The faces of the quadrant are enumerated like this: + * + * f_3 + * x ---- x + * / f_5 /| z y + * x ---- x | |/ + * f_0 | | x f_1 -- x + * | f_2 |/ + * x ---- x + * f_4 + */ + for (i = 0; i < P8EST_HALF; ++i) { + child_ids[i] = p8est_face_corners[face][i]; + } + + /* Create the four face children */ + /* We have to revert the order and compute the zeroth child last, since + * the usage allows for elem == children[0]. + */ + for (i = 3; i >= 0; i--) { + t8_element_child (elem, child_ids[i], children[i]); + } +} + + +int +t8_subelement_scheme_hex_c::t8_element_face_child_face (const t8_element_t + *elem, int face, + int face_child) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + /* For octants the face enumeration of children is the same as for the parent. */ + if (t8_element_is_subelement (elem)) { + T8_ASSERT (face == 4); + return t8_element_face_parent_face (elem, face); + } + else { + /* For quadrants the face enumeration of children is the same as for the parent. */ + return face; + } + +} + +int +t8_subelement_scheme_hex_c::t8_element_face_parent_face (const t8_element_t + *elem, + int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (face >= -1 && face < P8EST_FACES); + + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + const p8est_quadrant_t *q = &phex_w_sub->p8q; + + int child_id; + if (face == -1) { + return -1; + } + + /* For subelements we need to adjust the output of this function. + * A subelements face is a subface of the parent quadrant (the transition cell) if and only if the face number is 4. */ + if (t8_element_is_subelement (elem)) { + if (face == 4) { + /* In this case the face is a subface of the parent. We use the location function in order + * to determine which of the parents faces intersects the subelements face. */ + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + + return subelement_location_to_parent_face[location[0]]; + } + else { + return -1; + } + } + + if (q->level == 0) { + return face; + } + /* Determine whether face is a subface of the parent. + * This is the case if the child_id matches one of the faces corners */ + child_id = p8est_quadrant_child_id (q); + if (child_id == p8est_face_corners[face][0] + || child_id == p8est_face_corners[face][1] + || child_id == p8est_face_corners[face][2] + || child_id == p8est_face_corners[face][3]) { + return face; + } + return -1; + +} + +void +t8_subelement_scheme_hex_c::t8_element_transform_face (const t8_element_t + *elem1, + t8_element_t *elem2, + int orientation, + int sign, + int is_smaller_face) + const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem1)); + SC_ABORT ("This function is not implemented yet.\n"); + return; +} + +int +t8_subelement_scheme_hex_c::t8_element_extrude_face (const t8_element_t + *face, + const t8_eclass_scheme_c + *face_scheme, + t8_element_t *elem, + int root_face) const +{ + /* build (extrude) elem from a given face element */ + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; + p8est_quadrant_t *q = &phex_w_sub->p8q; + + const p4est_quadrant_t *b = (const p4est_quadrant_t *) face; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (face_scheme->eclass == T8_ECLASS_QUAD); + T8_ASSERT (face_scheme->t8_element_is_valid (face)); + T8_ASSERT (0 <= root_face && root_face < P8EST_FACES); + q->level = b->level; + /* + * The faces of the root quadrant are enumerated like this: + * + * x ---- x + * / f_5 /| + * x ---- x | + * f_0 | | x f_1 + * | f_2 |/ + * x ---- x + * f_4 + * + * We need to rescale the coordinates since a quadrant may have a different + * root length than an octant. + */ + switch (root_face) { + case 0: + q->x = 0; + q->y = ((int64_t) b->x * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + q->z = ((int64_t) b->y * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + break; + case 1: + q->x = P8EST_LAST_OFFSET (q->level); + q->y = ((int64_t) b->x * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + q->z = ((int64_t) b->y * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + break; + case 2: + q->x = ((int64_t) b->x * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + q->y = 0; + q->z = ((int64_t) b->y * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + break; + case 3: + q->x = ((int64_t) b->x * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + q->y = P8EST_LAST_OFFSET (q->level); + q->z = ((int64_t) b->y * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + break; + case 4: + q->x = ((int64_t) b->x * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + q->y = ((int64_t) b->y * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + q->z = 0; + break; + case 5: + q->x = ((int64_t) b->x * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + q->y = ((int64_t) b->y * P8EST_ROOT_LEN) / P4EST_ROOT_LEN; + q->z = P8EST_LAST_OFFSET (q->level); + break; + } + /* We return the face of q at which we extruded. This is the same number + * as root_face. */ + return root_face; +} + +int +t8_subelement_scheme_hex_c::t8_element_tree_face (const t8_element_t *elem, + int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + /* If elem is a subelement, then this function should only be called together with + * face = 4 since other faces will never intersect a tree face. */ + if (t8_element_is_subelement (elem)) { + T8_ASSERT (face == 4); + + return t8_element_face_parent_face (elem, face); + } + else { + T8_ASSERT (0 <= face && face < P8EST_FACES); + /* For hex the face and the tree face number are the same. */ + return face; + } + + // SC_ABORT_NOT_REACHED(); +} + +/** Construct the first descendant of an element that touches a given face. */ +void +t8_subelement_scheme_hex_c::t8_element_first_descendant_face (const + t8_element_t + *elem, + int face, + t8_element_t + *first_desc, + int level) + const +{ + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_first_desc = + (t8_hex_with_subelements *) first_desc; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + p8est_quadrant_t *desc = &phex_w_sub_first_desc->p8q; + + int first_face_corner; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (0 <= face && face < P8EST_FACES); + T8_ASSERT (0 <= level && level <= P8EST_QMAXLEVEL); + + /* Get the first corner of q that belongs to face */ + first_face_corner = p8est_face_corners[face][0]; + /* Construce the descendant in that corner */ + p8est_quadrant_corner_descendant (q, desc, first_face_corner, level); + t8_element_reset_subelement_values (first_desc); + + +} + +/** Construct the last descendant of an element that touches a given face. */ +void +t8_subelement_scheme_hex_c::t8_element_last_descendant_face (const + t8_element_t + *elem, int face, + t8_element_t + *last_desc, + int level) const +{ + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_last_desc = + (t8_hex_with_subelements *) last_desc; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + p8est_quadrant_t *desc = &phex_w_sub_last_desc->p8q; + + int last_face_corner; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (!t8_element_is_subelement (last_desc)); + T8_ASSERT (0 <= face && face < P8EST_FACES); + T8_ASSERT (0 <= level && level <= P8EST_QMAXLEVEL); + + /* Get the last corner of q that belongs to face */ + last_face_corner = p8est_face_corners[face][1]; + /* Construce the descendant in that corner */ + p8est_quadrant_corner_descendant (q, desc, last_face_corner, level); + t8_element_reset_subelement_values (last_desc); + + +} + +void +t8_subelement_scheme_hex_c::t8_element_boundary_face (const t8_element_t + *elem, int face, + t8_element_t *boundary, + const + t8_eclass_scheme_c + *boundary_scheme) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + const p8est_quadrant_t *q = &phex_w_sub->p8q; + + p4est_quadrant_t *b = (p4est_quadrant_t *) boundary; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (boundary_scheme->eclass == T8_ECLASS_QUAD); + T8_ASSERT (boundary_scheme->t8_element_is_valid (boundary)); + T8_ASSERT (0 <= face && face < P8EST_FACES); + + if (!t8_element_is_subelement (elem)) { + T8_ASSERT (0 <= face && face < P8EST_FACES); + /* The level of the boundary element is the same as the quadrant's level */ + b->level = q->level; + /* + * The faces of the quadrant are enumerated like this: + * + * x ---- x + * / f_5 /| + * x ---- x | + * f_0 | | x f_1 + * | f_2 |/ + * x ---- x + * f_4 + * + * If face = 0 or face = 1 then b->x = q->y, b->y = q->z + * if face = 2 or face = 3 then b->x = q->x, b->y = q->z + * if face = 4 or face = 5 then b->x = q->x, b->y = q->y + * + * We have to scale the coordinates since a root quadrant may have + * different length than a root hex. + */ + b->x = (face >> 1 ? q->x : q->y) * ((t8_linearidx_t) P4EST_ROOT_LEN / P8EST_ROOT_LEN); /* true if face >= 2 */ + b->y = (face >> 2 ? q->y : q->z) * ((t8_linearidx_t) P4EST_ROOT_LEN / P8EST_ROOT_LEN); /* true if face >= 4 */ + T8_ASSERT (!p8est_quadrant_is_extended (q) + || p4est_quadrant_is_extended (b)); + } + else { + /* face number 4 is the only face of a subelement that points outward of the transition cell */ + T8_ASSERT (face == 4); + /* + * for a split subelement, the boundary face has a higher level + * for a non split element, the boundary face has the same level. + */ + /* location = {location of subelement (face number of transition cell), split, subelement type (left/right, front/back, bottom/up)} */ + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + int split = location[1]; + int subelement_type = location[2]; + + if (split) { /* if the subelement lies at a split face */ + b->level = q->level + 1; + int len = + P8EST_QUADRANT_LEN (phex_w_sub->p8q.level + 1); + if ((location[0] == 0) || (location[0] == 1)) { /* left or right face */ + if( (subelement_type & 2) != 0){ //back + b->x = q->y + len; + } + else if((subelement_type & 1) != 0){ //up + b->y = q->z + len; + } + } + else if ((location[0] == 2) || (location[0] == 3)) { /* front or back face */ + if((subelement_type & 4) != 0){ //right + b->x = q->x + len; + } + else if ((subelement_type & 1) != 0) { // up + b->y = q->z + len; + } + } + else if ((location[0] == 2) || (location[0] == 3)) { /* bottom or up face */ + if((subelement_type & 4) != 0){ //right + b->x = q->x + len; + } + else if ((subelement_type & 2) != 0) { // back + b->y = q->y + len; + } + } + } + + } +} + +void +t8_subelement_scheme_hex_c::t8_element_boundary (const t8_element_t *elem, + int min_dim, int length, + t8_element_t **boundary) + const +{ + SC_ABORT ("Not implemented\n"); +#if 0 +#ifdef T8_ENABLE_DEBUG + int per_eclass[T8_ECLASS_COUNT]; +#endif + int iface; + + T8_ASSERT (length == + t8_eclass_count_boundary (T8_ECLASS_HEX, min_dim, per_eclass)); + + T8_ASSERT (length == P8EST_FACES); + for (iface = 0; iface < P8EST_FACES; iface++) { + t8_element_boundary_face (elem, iface, boundary[iface]); + } +#endif +} + +int +t8_subelement_scheme_hex_c::t8_element_is_root_boundary (const t8_element_t + *elem, + int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + const p8est_quadrant_t *q = &phex_w_sub->p8q; + + p4est_qcoord_t coord; + + /* In case of a subelement, we need to change its face number to the face number of the parent hex */ + if (t8_element_is_subelement (elem)) { + if (face == 4) { + /* adjust face of subelement to face of parent */ + face = t8_element_face_parent_face (elem, face); + } + else { /* in case of a subelement and face 0 or 2 the face is no subface of the root boundary */ + return 0; + } + } + + T8_ASSERT (0 <= face && face < P8EST_FACES); + + /* if face is 0 or 1 q->x + * 2 or 3 q->y + */ + coord = face >> 2 ? q->z : face >> 1 ? q->y : q->x; + /* If face is 0,2 or 4 check against 0. + * If face is 1,3 or 5 check against LAST_OFFSET */ + // t8_debugf("t8 element is root boundary %i\n", coord == (face & 1 ? P8EST_LAST_OFFSET (q->level) : 0)); + return coord == (face & 1 ? P8EST_LAST_OFFSET (q->level) : 0); + + +} + +int +t8_subelement_scheme_hex_c::t8_element_face_neighbor_inside (const + t8_element_t + *elem, + t8_element_t + *neigh, + int face, + int *neigh_face) + const +{ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (neigh)); + T8_ASSERT (0 <= face && face < P8EST_FACES); + + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_neigh = + (t8_hex_with_subelements *) neigh; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + p8est_quadrant_t *n = &phex_w_sub_neigh->p8q; + + // t8_debugf(" n: Koordinate x: %i, y %i, z %i, q Koordinaten: x %i, y %i, z %i \n", n->x, n->y, n->z, q->x, q->y, q->z); + // t8_debugf(" ist elem subelement? %i\n",t8_element_is_subelement (elem)); + + // /* In case of a subelement one should construct the face neighbor of the face-corresponding child quadrant + // * of the subelements parent quadrant. Therefore we might want to adjust the level and adapt the + // * anchor node. */ + if (t8_element_is_subelement (elem)) { /* if elem is a subelement */ + // t8_debugf(" Subelement: %i\n",t8_element_is_subelement (elem)); + T8_ASSERT (0 <= face && face < T8_HEX_SUBELEMENT_FACES); +int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + if (face < 4) { /* in this case the face neighbor of the subelement is a sibling */ + /* level and anchor stay the same */ + n->x = q->x; + n->y = q->y; + n->z = q->z; + n->level = q->level; + + T8_ASSERT (face != 4); + SC_ABORT_NOT_REACHED(); + /* return dual face with resprect to neighboring sibling subelement (note that the constructed neigh is NOT a subelement but the parent hex) */ + /* Compute the face number as seen from q. + * 0 -> 2 2 -> 0 + */ + *neigh_face = subelement_face_dual[location[0]][face]; + + + } + else { /* in this case the face neighbor is no sibling */ + // int location[3] = { }; + // t8_element_get_location_of_subelement (elem, location); + + /* setting the anchor node of the neighbor element */ + n->x = q->x; + n->y = q->y; + n->z = q->z; + + /* half the side length of the transition cell of the subelement */ + const p4est_qcoord_t shift = P8EST_QUADRANT_LEN (q->level + 1); + + int split = location[1]; + int subelement_type = location[2]; + + // t8_debugf(" Das ist location array location[0] = %i, location[2] = %i, location[2]=%i\n", location[0], location[1], location[2]); + /* we need to take into account whether the subelement is split or not */ + if (split) { /* split */ + /* increase the level by one */ + n->level = q->level + 1; + + /* adjust the anchor node of the neighbor of the subelement depending on its location */ + if (location[0] == 0) { /* left face */ + n->x = q->x - shift; + if ((subelement_type & 2) != 0 ) { //back + n->y = q->y + shift; + } + if ((subelement_type & 1) != 0 ){ //up + n->z = q->z + shift; + } + } + else if (location[0] == 1) { /* right face */ + n->x = q->x + 2 * shift; + if ((subelement_type & 2) != 0) { //back + n->y = q->y + shift; + } + if ((subelement_type & 1) != 0 ){ //up + n->z = q->z + shift; + } + } + else if (location[0] == 2) { /* front face */ + n->y = q->y - shift; + if ((subelement_type & 4) != 0) { //right + n->x = q->x + shift; + } + if ((subelement_type & 1) != 0 ) {//up + n->z = q->z + shift; + } + } + else if (location[0] == 3){ //back face + n->y = q->y + 2 * shift; + if ((subelement_type & 4) != 0) { //right + n->x = q->x + shift; + } + if((subelement_type & 1) != 0 ) {//up + n->z = q->z + shift; + } + } + else if (location[0] == 4){ //bottom face + if ((subelement_type & 4) != 0) { //right + n->x = q->x + shift; + } + if ((subelement_type & 2) != 0 ) {//back + n->z = q->z + shift; + } + } + else if (location[0] == 5){ //upper face + n->z = q->z + 2 * shift; + if ((subelement_type & 4) != 0) { //right + n->x = q->x + shift; + } + if ((subelement_type & 2) != 0 ) {//back + n->z = q->z + shift; + } + } + } + + else { /* not split */ + /* level stays the same */ + n->level = q->level; + + /* adjust the anchor node of the neighbor of the subelement depending on its location */ + if (location[0] == 0) { /* left face */ + n->x = q->x - 2 * shift; + } + else if (location[0] == 1) { /* right face */ + n->x = q->x + 2 * shift; + } + else if (location[0] == 2) { /* front face */ + n->y = q->y - 2 * shift; + } + else if (location[0] == 3) { /* back face */ + n->y = q->y + 2 * shift; + } + else if (location[0] == 4) { /* bottom face */ + n->z = q->z - 2 * shift; + } + else if (location[0] == 5) { /* upper face */ + n->z = q->z + 2 * shift; + } + } + + *neigh_face = subelement_location_to_parent_dual_face[location[0]]; + // t8_debugf(" Location array von mir: location[0] = %i, location[1]= %i, location[2]= %i \n", location[0], location[1], location[2]); + // t8_debugf(" n: Koordinate x: %i, y %i, z %i, q Koordinaten: x %i, y %i, z %i \n", n->x, n->y, n->z, q->x, q->y, q->z); + // t8_debugf(" Nachbar face %i\n", *neigh_face); + // t8_debugf(" Level von Nachbar %i\n", n->level); + // t8_debugf(" Level von mir %i\n", q->level); + } + + + } + else { /* if elem is no subelement */ + + /* Compute the face neighbor */ + p8est_quadrant_face_neighbor (q, face, n); + // t8_debugf(" n: Koordinate x: %i, y %i, z %i, q Koordinaten: x %i, y %i, z %i \n", n->x, n->y, n->z, q->x, q->y, q->z); + // t8_debugf("face %i\n", face); + /* Compute the face of q that coincides with face. + * face neigh_face face neigh_face + * 0 1 4 5 + * 1 0 5 4 + * 2 3 + * 3 2 + */ + //t8_element_reset_subelement_values (neigh); + T8_ASSERT (neigh_face != NULL); + *neigh_face = p8est_face_dual[face]; + // int sub_id = t8_element_get_subelement_id(neigh); + // t8_debugf( "neigh face: %i\n", *neigh_face); + + /* return true if neigh is inside the root */ + // T8_ASSERT(p8est_quadrant_is_inside_root (n)); + + + //return p8est_quadrant_is_inside_root (n); + + // t8_debugf(" n: Koordinate x: %i, y %i, z %i, q Koordinaten: x %i, y %i, z %i \n", n->x, n->y, n->z, q->x, q->y, q->z); + // t8_debugf(" Nachbar face %i\n", *neigh_face); + // t8_debugf(" Level von Nachbar %i\n", n->level); + // t8_debugf(" Level von mir %i\n", q->level); + // + } + t8_element_reset_subelement_values (neigh); + //t8_element_reset_subelement_values (neigh); + + // T8_QUAD_SET_TDIM (n, 2); + + /* In the following we set the dual faces of our element at the given face. */ + // if (t8_element_is_subelement (elem)) { + // if (face == 4) { + // /* return dual face with respect to neighboring hex element */ + // int location[3] = { }; + // t8_element_get_location_of_subelement (elem, location); + // *neigh_face = subelement_location_to_parent_dual_face[location[0]]; + // } + // else { + // T8_ASSERT (face != 4); + // int location[3] = { }; + // t8_element_get_location_of_subelement (elem, location); + // /* return dual face with resprect to neighboring sibling subelement (note that the constructed neigh is NOT a subelement but the parent hex) */ + // /* Compute the face number as seen from q. + // * 0 -> 2 2 -> 0 + // */ + // *neigh_face = subelement_face_dual[location[0]][face]; + // } + // } + + + + + if ( p8est_quadrant_is_inside_root(n) == 0){ + // t8_debugf("aus function: is inside root: %i\n", p8est_quadrant_is_inside_root (n)); + } + + + /* return true if neigh is inside the root */ + return p8est_quadrant_is_inside_root (n); + +} + +void +t8_subelement_scheme_hex_c::t8_element_anchor (const t8_element_t *elem, + int coord[3]) const +{ + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; + p8est_quadrant_t *q = &phex_w_sub->p8q; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + + coord[0] = q->x; + coord[1] = q->y; + coord[2] = q->z; + +} + +int +t8_subelement_scheme_hex_c::t8_element_root_len (const t8_element_t *elem) const +{ + return P8EST_ROOT_LEN; +} + +int +t8_subelement_scheme_hex_c::t8_element_refines_irregular () const +{ + /* In general, subelements do not refine regularly */ + return 1; +} + +void +t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t + *elem, + const double + *ref_coords, + const void + *user_data, + double *out_coords) + const +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} + +void +t8_subelement_scheme_hex_c::t8_element_vertex_reference_coords (const + t8_element_t + *t, + int vertex, + double + coords[]) + const +{ + int coords_int[3] = { }; + t8_element_vertex_coords (t, vertex, coords_int); + + /* We divide the integer coordinates by the root length of the hex + * to obtain the reference coordinates. */ + coords[0] = (double) coords_int[0] / (double) P8EST_ROOT_LEN; + coords[1] = (double) coords_int[1] / (double) P8EST_ROOT_LEN; + coords[2] = (double) coords_int[2] / (double) P8EST_ROOT_LEN; +} + +void +t8_subelement_scheme_hex_c::t8_element_vertex_coords (const t8_element_t + *elem, int vertex, + int coords[]) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + const p8est_quadrant_t *q1 = &phex_w_sub->p8q; + + T8_ASSERT (t8_element_is_valid (elem)); + + if (!t8_element_is_subelement (elem)) { + int len; + + //T8_ASSERT (0 <= vertex && vertex < 8); + /* Get the length of the quadrant */ + len = P8EST_QUADRANT_LEN (q1->level); + /* Compute the x, y and z coordinates of the vertex depending on the + * vertex number */ + coords[0] = q1->x + (vertex & 1 ? 1 : 0) * len; + coords[1] = q1->y + (vertex & 2 ? 1 : 0) * len; + coords[2] = q1->z + (vertex & 4 ? 1 : 0) * len; + + } + else { + t8_element_vertex_coords_of_subelement (elem, vertex, coords); + } + +} + +void +t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const + t8_element_t + *elem, + int + vertex, + int + coords[]) + const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + const p8est_quadrant_t *q1 = &phex_w_sub->p8q; + + int len; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_subelement (elem)); + T8_ASSERT (vertex >= 0 && vertex < T8_HEX_SUBELEMENT_FACES); /* all subelements are pyramids so T8_HEX_SUBELEMENT_FACES = 5 */ + /* get the length of the current quadrant */ + len = P8EST_QUADRANT_LEN (q1->level); + + + /* get location information of the given subelement */ + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + + /* the face number, the subelement is adjacent to */ + int face_number = location[0]; + /* = 1, if the adjacent face is split and = 0, if not */ + int split = location[1]; + /* subelement_id type. First bit (left) = 1 if right, = 0 if left, second bit( middle) = 1 if back , = 0 if front, third bit (right) = 0 if up and is = 1 if down + + * second bit front = 0, back = 1, third bit 0 = bottom 1 = up. For example: 110 stands for right and back (so only hex face f_4 and f_5 are possible.) + */ + int sub_face_id = location[2]; + + /* Check, whether the get_location function provides meaningful location data */ + T8_ASSERT ((face_number >=0) && face_number <= 5); + + coords[0] = q1->x; + coords[1] = q1->y; + coords[2] = q1->z; + + + switch(vertex){ + + case 4: //vertex 4 always equals the center of the hexahedron + coords[0] += (len / 2); + coords[1] += (len / 2); + coords[2] += (len / 2); + break; + + case 0: + if(split == 0){ //not splitted + //for face numbers 0,2 and 4 nothing happens + if(face_number == 1){ + coords[0] += len; + } + if(face_number == 3){ + coords[1] += len; + } + if(face_number == 5){ + coords[2] += len; + } + } +/* ----------- face 0 + 1 (splitted) --------------------*/ + else{ + if((face_number == 0) || (face_number == 1)){ + if((sub_face_id & 1)!= 0){ // up + coords[2] += (len / 2); + } + if((sub_face_id & 2) != 0 ){ // back + coords[1] += (len / 2); + } + + if(face_number == 1){ + coords[0] += len; + } + } +/* ----------- face 2 + 3 (splitted) --------------------*/ + if((face_number == 2) || (face_number == 3)){ + if((sub_face_id & 1) != 0){ // up + coords[2] += (len / 2); + } + if((sub_face_id & 4) != 0 ){ // right + coords[0] += (len / 2); + } + if(face_number == 3){ + coords[1] += len; + } + } +/* ----------- face 4 + 5 (splitted) --------------------*/ + if((face_number == 4) || (face_number == 5)){ + if((sub_face_id & 2) != 0){ // back + coords[1] += len / 2; + } + if((sub_face_id & 4) != 0 ){ // right + coords[0] += len / 2; + } + if(face_number == 5){ + coords[2] += len; + } + } + } + break; + + case 1: + if(split == 0){ + if((face_number == 0) || (face_number == 1 || (face_number == 3))){ + coords[1] += len; + } + if(face_number > 0){ + coords[0] += len; + } + if(face_number == 5){ + coords[2] += len; + } + + } +/* ----------- face 0 + 1 (splitted) --------------------*/ + else{ + if((face_number == 0) || (face_number == 1)){ + if((sub_face_id & 1) != 0){ // up + coords[2] += len / 2; + } + if((sub_face_id & 2) != 0 ){ // back + coords[1] += len; + + } + else if((sub_face_id & 2) == 0) { //front + coords[1] += len / 2; + } + + if(face_number == 1){ + coords[0] += len; + } + } +/* ----------- face 2 + 3 (splitted) --------------------*/ + if((face_number == 2) || (face_number == 3)){ + if((sub_face_id & 1) != 0){ // up + coords[2] += len / 2; + } + if((sub_face_id & 4) != 0 ){ // right + coords[0] += len; + } + else if((sub_face_id & 4) == 0){ //left + coords[0] += len / 2; + } + if(face_number == 3){ + coords[1] += len; + } + } + +/* ----------- face 4 + 5 (splitted) --------------------*/ + if((face_number == 4) || (face_number == 5)){ + if((sub_face_id & 2) != 0){ // back + coords[1] += (len / 2); + } + if((sub_face_id & 4) != 0){ // right + coords[0] += len; + } + else if ((sub_face_id & 4) == 0){ //left + coords[0] += (len / 2); + } + if(face_number == 5){ + coords[2] += len; + } + } + } + break; + case 2: + if(split == 0){ + if(face_number != 4){ + coords[2] += len; + } + if(face_number == 1){ + coords[0] += len; + } + if(face_number > 2){ + coords[1] += len; + } + } +/* ----------- face 0 + 1 (splitted) --------------------*/ + else{ + if((face_number == 0) || (face_number == 1)){ + if((sub_face_id & 2) != 0){ // back + coords[1] += len / 2; + } + if((sub_face_id & 1) != 0 ){ // up + coords[2] += len; + } + else if((sub_face_id & 1) == 0){ //bottom + coords[2] += len / 2; + } + if(face_number == 1){ + coords[0] += len; + } + } + +/* ----------- face 2 + 3 (splitted) --------------------*/ + if((face_number == 2) || (face_number == 3)){ + if((sub_face_id & 1) != 0){ // up + coords[2] += len; + } + else if((sub_face_id & 1) == 0){ + coords[2] += len / 2; + } + if((sub_face_id & 4) != 0 ){ // right + coords[0] += len / 2; + } + if(face_number == 3){ + coords[1] += len; + } + } +/* ----------- face 4 + 5 (splitted) --------------------*/ + + if((face_number == 4) || (face_number == 5)){ + if((sub_face_id & 2) != 0){ // back + coords[1] += len; + } + else if((sub_face_id & 2) == 0){ //front + coords[1] += len / 2; + } + if((sub_face_id & 4) != 0){ // right + coords[0] += len / 2; + } + if(face_number == 5){ + coords[2] += len; + } + } + } + + break; + case 3: + if(split == 0){ + if(face_number != 2){ + coords[1] += len; + } + if(face_number != 4){ + coords[2] += len; + } + if(face_number > 0){ + coords[0] += len; + } + } + /* ----------- face 0 + 1 (splitted) --------------------*/ + else{ + if((face_number == 0) || (face_number == 1)){ + if((sub_face_id & 2) != 0){ // back + coords[1] += len; + } + else if((sub_face_id & 2) == 0){ //front + coords[1] += len / 2; + } + if((sub_face_id & 1) != 0 ){ // up + coords[2] += len; + } + else if((sub_face_id & 1) == 0 ){ // bottom + coords[2] += len / 2; + } + if( face_number == 1){ + coords[0] += len; + } + } +/* ----------- face 2 + 3 (splitted) --------------------*/ + if((face_number == 2) || (face_number == 3)){ + if((sub_face_id & 1) != 0){ // up + coords[2] += len; + } + else if((sub_face_id & 1) == 0){ + coords[2] += len / 2; + } + if((sub_face_id & 4) != 0 ){ // right + coords[0] += len; + } + else if((sub_face_id & 4) == 0 ){ // left + coords[0] += len / 2; + } + if(face_number == 3){ + coords[1] += len; + } + } + +/* ----------- face 4 + 5 (splitted) --------------------*/ + if((face_number == 4) || (face_number == 5)){ + if((sub_face_id & 2) != 0){ // back + + coords[1] += len; + } + else if((sub_face_id & 2) == 0){ //front + coords[1] += len / 2; + } + if((sub_face_id & 4) != 0 ){ // right + coords[0] += len; + } + else if((sub_face_id & 4) == 0){ // left + coords[0] += len / 2; + } + if( face_number == 5){ + coords[2] += len; + } + } + } + + break; + } + +} + +void +t8_subelement_scheme_hex_c::t8_element_to_transition_cell (const t8_element_t + *elem, int transition_type, + t8_element_t *c[]) +{ + const t8_hex_with_subelements *phex_w_sub_elem = + (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements **phex_w_sub_subelement = + (t8_hex_with_subelements **) c; + + const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; + + /* this function should not be callable by subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (transition_type >= 0 && transition_type <= T8_SUB_HEX_MAX_TRANSITION_TYPE); + + int num_subelements = + t8_element_get_number_of_subelements (transition_type); + +#ifdef T8_ENABLE_DEBUG + { + int j; + for (j = 0; j < num_subelements; j++) { + T8_ASSERT (t8_element_is_valid (c[j])); + } + } +#endif + + /* get the length of a children-quadrant */ + const int8_t level = (int8_t) (q->level); + + T8_ASSERT (p8est_quadrant_is_extended (q)); + T8_ASSERT (q->level < P8EST_OLD_QMAXLEVEL); + + int sub_id_counter = 0; + for (sub_id_counter = 0; sub_id_counter < num_subelements; sub_id_counter++) { + phex_w_sub_subelement[sub_id_counter]->p8q.x = q->x; + phex_w_sub_subelement[sub_id_counter]->p8q.y = q->y; + phex_w_sub_subelement[sub_id_counter]->p8q.z = q->z; + phex_w_sub_subelement[sub_id_counter]->p8q.level = level; + + phex_w_sub_subelement[sub_id_counter]->transition_type = transition_type; + + //Überlegung transition type umwandeln in subelement id--> nicht einfach counter + phex_w_sub_subelement[sub_id_counter]->subelement_id = sub_id_counter; + T8_ASSERT (t8_element_is_valid (c[sub_id_counter])); + + } +} + +int +t8_subelement_scheme_hex_c::t8_element_get_number_of_subelements (int + transition_type) + const +{ + /* we could return 0 for transition type 0 but we will assert this case for safety reasons */ + T8_ASSERT (transition_type != 0); + + /* consider transition_type 16 = 010000 in base two -> there are 6 + (1)*3 = 9 subelements */ + int num_hanging_faces = 0; + int ichild; + for (ichild = 0; ichild < P8EST_FACES; ichild++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ + num_hanging_faces += (transition_type & (1 << ichild)) >> ichild; + } + + /* The number of subelements equals the number of neighbours: */ + //t8_productionf("number subs %i\n",P8EST_FACES + num_hanging_faces*3); + return P8EST_FACES + num_hanging_faces*3; +} + +void +t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const + t8_element_t + *elem, + int + location + []) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + + /* this function only works for subelements */ + T8_ASSERT (t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + + /* Consider the following transition cell of type 13: + * + * f0 1 + * x - - x - - x x - - x - - x + * | | | \ 2 | 3 / | faces: f3 f2 f1 f0 + * | | | 1 \ | / 4 | binary code: 1 1 0 1 (=13) + * f3 x x f2 --> 1 x - - x - - x 1 --> rearrange binaries s.t. the faces are enumerated clockwise: 1 1 1 0 + * | | | 0 / \ 5 | number subelements at face: 2 2 1 2 + * | elem | | / 6 \ | consider sub_id 3: x -> second subelement on the upper face + * + - - - - - x x - - - - - x + * f1 0 + * + * We will use the binary representation to determine the location of the given subelement. + * + * We need to know: + * i) the face number of the first vertex (values: {0,1,2,3}). + * ii) whether this face is split in half (values: {0,1}). + * iii) if the subelement is the first or second subelement at the face (values: {0,1}). + * + * These informations are then saved in the location array which will be used by the element_vertex function, + * to automatically determine the vertex coordinates of the given subelement. + * + * The location array for the above example would be {1,1,1} (upper face, split = true, second subelement at the upper face). */ + + /* 1) convert the transition type from a decimal to a binary representation */ + int type = phex_w_sub->transition_type; + int binary_array[P8EST_FACES] = { }; + + int iface; + + /* We need an array with 6 elements to store all subelement types of the hex scheme from 1 to 63 ({0, 0, 0, 0, 0, 1} to {1, 1, 1, 1, 1, 1}) */ + for (iface = 0; iface < P8EST_FACES; iface++) { + binary_array[(P8EST_FACES - 1) - iface] = (type & (1 << iface)) >> iface; + } /* we now got a binary represenation of the transition type, bitwise stored in an array */ + + int binary_array_temp[P8EST_FACES] = { }; + + for (iface = 0; iface < P8EST_FACES; iface++) { /* copying the binary array */ + binary_array_temp[iface] = binary_array[iface]; + } + /* 3) use the rearranged binary representation, and the sub_id to determine the location of the subelement and store these information in an array */ + /* 3.1) location[0] -> the face_number, the subelement is adjacent to */ + /* 3.2) location[1] -> if the face is split or not */ + /* 3.3) location[2] -> if the subelement is the left/right, front/back or bottom/up Same idea as with the transition type: first bit 0 = left, 1 = right, + * second bit front = 0, back = 1, third bit 0 = bottom 1 = up. For example: 110 stands for right and back (so only hex face f_4 and f_5 are possible.) */ + T8_ASSERT (phex_w_sub->subelement_id < + t8_element_get_number_of_subelements + (phex_w_sub->transition_type)); + + int sub_id = phex_w_sub->subelement_id; + + int sub_face_id_array[3] = {0,0,0}; + int sub_face_id = 0; + int face_number = -1; + int split; + + int cum_neigh_array[P8EST_FACES] = { }; + + /* construct a cumulative array of the number of neighbors from face 0 to face 5 */ + cum_neigh_array[0] = binary_array[0]*3 + 1; + cum_neigh_array[1] = cum_neigh_array[0] + binary_array[1]*3 + 1; + cum_neigh_array[2] = cum_neigh_array[1] + binary_array[2]*3 + 1; + cum_neigh_array[3] = cum_neigh_array[2] + binary_array[3]*3 + 1; + cum_neigh_array[4] = cum_neigh_array[3] + binary_array[4]*3 + 1; + cum_neigh_array[5] = cum_neigh_array[4] + binary_array[5]*3 + 1; + + /* 3.1) we can use the cumulative array to determine the face number of the given subelement */ + if (sub_id < cum_neigh_array[0]) { + face_number = 0; + } + else { + for (iface = 0; iface < P8EST_FACES - 1; ++iface) { + if (sub_id >= cum_neigh_array[iface] + && sub_id < cum_neigh_array[iface + 1]) { + face_number = iface + 1; + break; + } + } + } + +//t8_productionf("Das ist cum neigh_array[face_number %i]= %i \n", face_number,cum_neigh_array[iface + 1]); + /* make sure that a face_number has been found */ + T8_ASSERT (face_number >= 0); + + /* 3.2) determine, whether the face is split or not */ + if (binary_array[face_number] == 0) { + split = 0; /* the face is not split */ + } + else { + split = 1; /* the face is split */ + } + if(split == 1){ + + /* 3.3) determine, whether the subelement is the left/right, front/back or bottom/up subelement at the face */ + //First left/ right (only for face number 2, 3, 4, 5) + if( face_number > 1){ + if (((sub_id + 1) == cum_neigh_array[face_number] ) || ((sub_id + 3) == cum_neigh_array[face_number])) { + sub_face_id_array[0] = 1; /* right*/ + } + else if (((sub_id + 2) == cum_neigh_array[face_number] ) || ((sub_id + 4) == cum_neigh_array[face_number])){ + sub_face_id_array[0] = 0; /* left */ + } + } + //Second check front or back (only for face numbers 0, 1, 4, 5) + if( face_number <= 1 ){ + if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 3) == cum_neigh_array[face_number])) { + sub_face_id_array[1] = 1; /* back subelement */ + } + else if (((sub_id + 2) == cum_neigh_array[face_number]) || ((sub_id + 4) == cum_neigh_array[face_number])){ + sub_face_id_array[1] = 0; /* front subelement */ + } + } + else if( face_number >= 4 ){ + if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 2) == cum_neigh_array[face_number])) { + sub_face_id_array[1] = 1; /* back subelement */ + } + else if(((sub_id + 3) == cum_neigh_array[face_number]) || ((sub_id + 4) == cum_neigh_array[face_number])){ + sub_face_id_array[1] = 0; /* front subelement */ + } + } + //Third check up or down (only for face numbers 0, 1, 2, 3) + if( face_number < 4 ){ + if (((sub_id + 2) == cum_neigh_array[face_number] ) || ((sub_id + 1) == cum_neigh_array[face_number] )) { + sub_face_id_array[2] = 1; /* up subelement */ + } + else if (((sub_id + 3) == cum_neigh_array[face_number] ) || ((sub_id + 4) == cum_neigh_array[face_number] )){ + sub_face_id_array[2] = 0; /* bottom subelement */ + } + } + //Calculate the sub_face_id out of the sub_face_id_array + for(int i = 0; i < 3; i++ ){ + if( sub_face_id_array[i] == 1){ + sub_face_id += std::pow(2, 2-i); + } + } + } + + location[0] = face_number; + location[1] = split; + location[2] = sub_face_id; + + +} + +void +t8_subelement_scheme_hex_c::t8_element_reset_subelement_values (t8_element * + elem) const +{ + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; + + phex_w_sub->transition_type = 0; + phex_w_sub->subelement_id = 0; +} + +void +t8_subelement_scheme_hex_c::t8_element_copy_subelement_values (const + t8_element * + source, + t8_element * + dest) const +{ + const t8_hex_with_subelements *phex_w_sub_source = + (const t8_hex_with_subelements *) source; + t8_hex_with_subelements *phex_w_sub_dest = + (t8_hex_with_subelements *) dest; + // phex_w_sub_dest->transition_type = phex_w_sub_source->transition_type; + phex_w_sub_dest->transition_type = phex_w_sub_source->transition_type; + phex_w_sub_dest->subelement_id = phex_w_sub_source->subelement_id; +} + +int +t8_subelement_scheme_hex_c::t8_element_is_subelement (const + t8_element * + elem) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + + T8_ASSERT (phex_w_sub->transition_type >= 0); + + /* transition_type == 0 => elem is no subelement. + * transition_type != 0 => elem is subelement + */ + return (phex_w_sub->transition_type == 0 ? false : true); +} + +int +t8_subelement_scheme_hex_c::t8_element_get_transition_type (const + t8_element * + elem) +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + return phex_w_sub->transition_type; +} + +int +t8_subelement_scheme_hex_c::t8_element_get_subelement_id (const + t8_element * elem) +{ + T8_ASSERT (t8_element_is_valid (elem)); + + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + + return phex_w_sub->subelement_id; +} + +t8_element_shape_t +t8_subelement_scheme_hex_c::t8_element_shape (const t8_element_t *elem) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + return (t8_element_is_subelement (elem) ? T8_ECLASS_PYRAMID : + T8_ECLASS_HEX); +} + +int +t8_subelement_scheme_hex_c::t8_element_num_corners (const t8_element_t *elem) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + return (t8_element_is_subelement (elem) ? T8_HEX_SUBELEMENT_FACES : + 8); +} + +int +t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell + (const t8_element_t *elem, const t8_element_t *pseudo_neigh, int elem_face) +{ + /* In this function, we assume pseudo_neigh to be a random subelement of a transition cell that includes + * the real neighbor of elem at face elem_face. This function will output the subelement_id of the real neighbor of elem. */ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (pseudo_neigh)); + /* we expect neigh to be a element in a transition cell, thus to be a subelement */ + T8_ASSERT (t8_element_is_subelement (pseudo_neigh)); +//Case 1: the neighbor is ab sibling of elem --> function t8_element_get_sibling_neighbor_in_transition_cell +//Thus, we expect elem_face = 4 + T8_ASSERT (elem_face == 4); + + const t8_hex_with_subelements * + phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements * + phex_w_sub_pseudo_neigh = + (const t8_hex_with_subelements *) pseudo_neigh; + // t8_debugf("\n~~~~~~~~~~~Into find neighbor in transition cell ~~~~~~~~~~~~~~~\n"); + /* In the following, all possible neighbor configurations are defined, such that subelement neighbors can be + * identified in LFN_transitioned. */ + + + + /* Below are the cases in which the neighbor is no sibling. + * The idea is to fill a location array with the desired properties of the real neighbor. + * Togehter with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ + + //Case 2: The element is a subelement and we are looking for a face neighbor at face 4. + if (t8_element_is_subelement(elem)) { + + /* In this case, we have the following examplary situation in the 2D quad case: + * + * x - - - - - - - x - - - - - - - x + * | \ / | \ / | + * | \ / | \ / | + * | \ / | \ / | + * x - - - x neigh | elem x | + * | / \ | / | \ | + * | /pseudo \ | / | \ | + * | / neigh \ | / | \ | + * x - - - - - - - x - - - x - - - x + * + * A subelement elem is given as well as a random subelement pseudo_neigh from a neighboring transition cell. + * We are searching for the subelement id of the real neighbor neigh. + * Note that both transition cells can have different levels. */ + + /* get the location of elem */ + int + location_elem[3] = { }; /* {face, is_split, number of subelement at face} */ + t8_element_get_location_of_subelement (elem, location_elem); + + /* Initialize the location array of the real neighbor. */ + int + location_neigh[3] = { -1, -1, 0 }; + + //Check if the neighbor has a lower level than the element + if (phex_w_sub_pseudo_neigh->p8q.level < phex_w_sub_elem->p8q.level) { + + location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; + /* the pseudo_neigh transition cell has a lower level than the elem transition cell, so the second entry + of the location array has to be 1 (= splitted) */ + location_neigh[1] = 1; /* split */ + /* First, check left/right face of transition cell */ + if ((location_elem[0] == 0) || (location_elem[0] == 1)) { + //If the y-coordinates differ, we can derivate that the neighbor lies in the back. + //Thus, we need to increment the subelement_type by 2^1 + if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { + location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back*/ + } + //Analogously: if the z-coordinates differ, we can derivate that the neighbor lies up. + //Thus, we need to increment the subelement_type by 2^0 + if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { + location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ + } + } + /* Second, check front/back face of transition cell */ + if ((location_elem[0] == 2) || (location_elem[0] == 3)){ + if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { + location_neigh[2] = location_neigh[2] + (int) pow(2,2); /* right */ + } + if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { + location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ + } + } + /*Third, check lower/up face of transition cell */ + if ((location_elem[0] == 4) || (location_elem[0] == 5)) { + if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { + location_neigh[2] = location_neigh[2] + (int) pow(2,2); /* right */ + } + if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { + location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back */ + } + } + } + /* the pseudo_neigh transition cell has not a lower level than the elem transition cell, so it's face is not splitted */ + else { + location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; + location_neigh[1] = 0; /* not split */ + } + + /* check, that a neighbor is found and the location array is adjusted */ + T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 + && location_neigh[2] >= 0); + + /* Depending on the location of elem, we have filled location_neigh with the data of the real neighbor. + * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ + return + t8_element_get_id_from_location (t8_element_get_transition_type + (pseudo_neigh), location_neigh); + } + //Now, elem is no subelement. + else{ + /* In this case, we have the following examplary situation for the 2D quad case: + * + * x - - - - - - - x - - - - - - - x + * | \ / | | + * | \ / | | + * | \ / | | + * x - - - x neigh | elem | + * | / \ | | + * | /pseudo \ | | + * | / neigh \ | | + * x - - - - - - - x - - - - - - - x + * + * Subelement elem is given as well as a random subelement neigh from a neighboring transition cell. + * We are searching for the subelement id of the real neighbor neigh. + * Note that the transition cell of pseudo_neigh and elem can have different levels. */ + + /* Initialize the location array of the real neighbor. */ + int + location_neigh[3] = { 0, 0, 0 }; + + /* the pseudo_neigh transition cell has a lower level than elem */ + if (phex_w_sub_pseudo_neigh->p8q.level < phex_w_sub_elem->p8q.level) { //actually same case as case 2 just without location array of elem + location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; + location_neigh[1] = 1; /* split */ + if ((elem_face == 0) || (elem_face == 1)) { /* left/right face of transition cell */ + if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { + location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back*/ + } + if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { + location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ + } + } + if ((elem_face == 2) || (elem_face == 3) ){ /* front/back face of transition cell */ + if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { + + location_neigh[2] = location_neigh[2] + (int) pow(2,2); /* right */ + } + if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { + location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ + } + } + if ((elem_face == 4) || (elem_face == 5)) { /* lower/up face of transition cell */ + if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { + location_neigh[2] = location_neigh[2] + (int) pow(2,2); /* right */ + } + if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { + location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back */ + } + } + } + /* the pseudo_neigh transition cell has the same level as elem + * Note that the level of the transition cell can not be higher as the level of elem in this case, + * since elem would then be a subelement in a transtion cell. */ + if (phex_w_sub_pseudo_neigh->p8q.level == phex_w_sub_elem->p8q.level) { + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* default value */ + location_neigh[0] = subelement_location_to_parent_dual_face[elem_face]; + } + + /* check, that a neighbor is found and the location array is adjusted */ + T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 + && location_neigh[2] >= 0); + /* Depending on the location of elem, we have filled location_neigh with the data of the real neighbor. + * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ + return + t8_element_get_id_from_location (t8_element_get_transition_type + (pseudo_neigh), location_neigh); + } + + return -1; /* return negative if no neighbor element could be found */ + +} + +int +t8_subelement_scheme_hex_c::t8_element_get_id_from_location (int type, + int location[]) +{ + T8_ASSERT (type >= 0 && type <= T8_SUB_HEX_MAX_TRANSITION_TYPE); + + int sub_id, subelements_count = 0; + double type_temp = double (type); // would work for ints but we use libc pow(double, double) + int binary_type[P8EST_FACES] = { }; + + /* get the type as a binary array */ + int iface; + for (iface = 0; iface < P8EST_FACES; iface++) { + if (type_temp >= pow (2.0, 6 - (iface + 1))) { + binary_type[iface] = 1; + type_temp -= pow (2.0, 6 - (iface + 1)); + } + else { + binary_type[iface] = 0; + } + } + + + /* count the number of elements up to the given location */ + int element_count; + for (element_count = 0; element_count <= location[0]; element_count++) { + if (element_count == location[0]) { + if (location[1] == 0) { + subelements_count += 1; + } + else { + subelements_count += 4; + if( location[0] == 0 || location[0] == 1){ + + if ( (location[2] & 2) == 0 ) { // front + subelements_count -= 1; + } + if( (location[2] & 1) == 0 ) { //bottom + subelements_count -= 2; + } + } + if( location[0] == 2 || location[0] == 3){ + + if ( (location[2] & 4) == 0 ) { // left + subelements_count -= 1; + } + if( (location[2] & 1) == 0 ) { //bottom + subelements_count -= 2; + } + } + if( location[0] == 4 || location[0] == 5){ + if ( (location[2] & 4) == 0 ) { // left + subelements_count -= 1; + } + if( (location[2] & 2) == 0 ) { //front + subelements_count -= 2; + } + } + } + } + + else { + if(binary_type[element_count] == 1){ + subelements_count += 4; + } + else{ + subelements_count += 1; + } + } + + } +// t8_productionf("subelements count % i \n transition type %i, und location [0]= %i, location[1] = %i, location [2] = %i \n", subelements_count, type ,location[0] ,location[1] ,location[2] ); + /* get the sub_id */ + sub_id = subelements_count - 1; + + return sub_id; +} + +int +t8_subelement_scheme_hex_c::t8_element_get_face_number_of_hypotenuse (const + t8_element_t + *elem) +{ + SC_ABORT_NOT_REACHED(); + +} + +void +t8_subelement_scheme_hex_c::t8_element_new (int length, t8_element_t **elem) const +{ + /* allocate memory */ + t8_default_scheme_common_c::t8_element_new (length, elem); + + int elem_count; + for (elem_count = 0; elem_count < length; elem_count++) { + t8_hex_with_subelements *phex_w_sub = + (t8_hex_with_subelements *) elem[elem_count]; + t8_element_init (1, elem[elem_count], 0); + T8_QUAD_SET_TDIM ((p8est_quadrant_t *) & phex_w_sub->p8q, 3); + } +} + +void +t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem, + int new_called) const +{ + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; + + int elem_count; + + for (elem_count = 0; elem_count < length; elem_count++) { + /* initalize subelement parameters */ + phex_w_sub[elem_count].transition_type = 0; + phex_w_sub[elem_count].subelement_id = 0; + +#ifdef T8_ENABLE_DEBUG + /* In debugging mode we iterate over all length many elements and + * set their hex to the level 0 hex with ID 0. */ + if (!new_called) { + p8est_quadrant_t *hex = &phex_w_sub[elem_count].p8q; + p8est_quadrant_set_morton (hex, 0, 0); + T8_QUAD_SET_TDIM (hex, 3); + T8_ASSERT (p8est_quadrant_is_extended (hex)); + } +#endif + } +} + +int +t8_subelement_scheme_hex_c::t8_element_scheme_supports_transitioning (void) +{ + return T8_HEX_TRANSITION_IS_IMPLEMENTED; +} + +int +t8_subelement_scheme_hex_c::t8_element_transition_scheme_is_conformal (void) +{ + return T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL; +} + +#ifdef T8_ENABLE_DEBUG +void +t8_subelement_scheme_hex_c::t8_element_debug_print (const t8_element_t *elem) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + + t8_productionf ("\n|------------ t8_element_debug_print: ------------|" + "\n| Transition Type: %i" + "\n| Subelement ID: %i" + "\n| Anchor (Morton): (%i,%i,%i)" + "\n| Anchor (ref coords): (%lf,%lf,%lf)" + "\n| Level: %i" + "\n|-------------------------------------------------|\n", + phex_w_sub->transition_type, phex_w_sub->subelement_id, + phex_w_sub->p8q.x, phex_w_sub->p8q.y,phex_w_sub->p8q.z, + (double) phex_w_sub->p8q.x / (double) P8EST_ROOT_LEN, + (double) phex_w_sub->p8q.y / (double) P8EST_ROOT_LEN, + (double) phex_w_sub->p8q.z / (double) P8EST_ROOT_LEN, + phex_w_sub->p8q.level); + + /* if the element is not valid, abort, but after printing */ + T8_ASSERT (t8_element_is_valid (elem)); +} + +/* *INDENT-OFF* */ +/* indent bug, indent adds a second "const" modifier */ +int +t8_subelement_scheme_hex_c::t8_element_is_valid (const t8_element_t * elem) const +/* *INDENT-ON* */ + +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + const p8est_quadrant_t *q = &phex_w_sub->p8q; + + /* the p8est quadrant AND the subelement values must be valid such that the whole element is valid */ + return (p8est_quadrant_is_extended (q) + && t8_element_subelement_values_are_valid (elem)); +} + +/* *INDENT-OFF* */ +/* indent bug, indent adds a second "const" modifier */ +int +t8_subelement_scheme_hex_c::t8_element_subelement_values_are_valid (const + t8_element_t * + elem) const +/* *INDENT-ON* */ + +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + + return ((phex_w_sub->transition_type >= 0 && + phex_w_sub->transition_type <= T8_SUB_HEX_MAX_TRANSITION_TYPE) + && + ((phex_w_sub->subelement_id >= 0 && + phex_w_sub->subelement_id <= T8_SUB_HEX_MAX_SUBELEMENT_ID))); +} +#endif + +/* Constructor */ +t8_subelement_scheme_hex_c::t8_subelement_scheme_hex_c (void) +{ + eclass = T8_ECLASS_HEX; + element_size = sizeof (t8_phex_sub_t); + ts_context = sc_mempool_new (element_size); +} + +t8_subelement_scheme_hex_c::~t8_subelement_scheme_hex_c () +{ + /* This destructor is empty since the destructor of the + * default_common scheme is called automatically and it + * suffices to destroy the hex_scheme. + * However we need to provide an implementation of the destructor + * and hence this empty function. */ +} + +T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx new file mode 100644 index 0000000000..06aec744c3 --- /dev/null +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -0,0 +1,551 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/** \file t8_transition_conformal_HEX_cxx.hxx + * We use a p4est_HEXrant_t object as storage for the T8 HEXrant. + * Additionally, we store information for transition cells of triangular subelements: + * + * (i) transition_type - type of the transition cell of the current element + * (ii) subelement_id - subelement id of the current element + * + * In order to refine a HEX element into a transition cell, it is important to know these additional parameter. + */ + +#ifndef T8_TRANSITION_CONFORMAL_HEX_CXX_HXX +#define T8_TRANSITION_CONFORMAL_HEX_CXX_HXX + +#include +#include + +#include "t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.hxx" +#include "t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx" + +#include + +/** The structure holding a HEXrilateral element in the default scheme. + * We make this definition public for interoperability of element classes. + * We might want to put this into a private, scheme-specific header file. + */ + +/* Define the struct, that stores all information needed for the HEX scheme and subelements. + * + * p4est HEXrant recursive HEX refinement, using a transition + * refinement cell with subelements + * x - - - - - x x - - x - - x x - - - - - x + * | | | | | | \ 2 / | + * | | | | | | 1 \ / | + * | | --> x - - x - - x or x - - x 3 | + * | | | | | | 0 / | \ | + * | | | | | | / 5 | 4 \ | + * x - - - - - x x - - x - - x x - - x - - x + * + * A p4est HEXrant can be refined, using either the standard HEX scheme, or a transition cell, consisting of different subelements. + * The HEX refinement scheme is recursive, whereas a transition cell can only be used once, for example to remove hanging nodes, after the mesh has been adapted and balanced. + * There are different types of transition cells possible, which we will refer to as transition_type. + * Each transition cell consists of different subelements. The given example consists of 6 different subelements, whose ids range from 0 to 5. + * A dummy variable will store the information, whether a given element is a subelement or a standard HEX element. */ + +typedef struct +{ + /* p4est quadrant */ + p8est_quadrant_t p8q; + /* stores transition cell information (default for non-subelements is 0 and for subelements it is != 0 - is therefore used as a is_subelement check) */ + int transition_type; + /* stores subelement information (default for non-subelements is 0) */ + int subelement_id; +} t8_hex_with_subelements; + +typedef t8_hex_with_subelements t8_phex_sub_t; + +/** define some subelement related constants */ +#define T8_SUB_HEX_MAX_TRANSITION_TYPE 63 + +//Transition mit hängenden Kanten (nur Pyramiden) also höchstens vier Parymiden pro Seite. Ein Würfel hat sechs Seiten also maximal +// 6*4 = 24 subelement id's +#define T8_SUB_HEX_MAX_SUBELEMENT_ID 24 +//Pyramide hat 5 Seiten +#define T8_HEX_SUBELEMENT_FACES 5 + +#define T8_HEX_TRANSITION_IS_IMPLEMENTED 1 +#define T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL 1 + +/** Return the toplevel dimension. */ +//#define T8_QUAD_GET_TDIM(quad) ((int) (quad)->pad8) + +/** Return the direction of the third dimension. + * This is only valid to call if the toplevel dimension is three. + */ +#define T8_QUAD_GET_TNORMAL(quad) \ + ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ + ((int) (quad)->pad16) ) + +/** Return the coordinate in the third dimension. + * This is only valid to call if the toplevel dimension is three. + */ +#define T8_QUAD_GET_TCOORD(quad) \ + ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ + ((int) (quad)->p.user_long) ) + +/** Set the toplevel dimension of a hexahedron. */ +#define T8_QUAD_SET_TDIM(quad,dim) \ + do { T8_ASSERT ((dim) == 2 || (dim) == 3); \ + (quad)->pad8 = (int8_t) (dim); } while (0) + +/** Set the direction of the third demension. */ +#define T8_QUAD_SET_TNORMAL(quad,normal) \ + do { T8_ASSERT ((normal) >= 0 && (normal) < 3); \ + (quad)->pad16 = (int16_t) (normal); } while (0) + +/** Set the coordinate in the third dimension. */ +#define T8_QUAD_SET_TCOORD(quad,coord) \ + do { (quad)->p.user_long = (long) (coord); } while (0) + +#if 0 +/** Provide an implementation for the HEXrilateral element class with subelements. */ +t8_eclass_scheme_t *t8_subelement_scheme_new_hex (void); +#endif + + +// Die Klasse t8_subelement_scheme_HEX_c erbt von der Klasse t8_default_scheme_common_c +struct t8_subelement_scheme_hex_c:public t8_default_scheme_common_c +{ +public: + /** The virtual table for a particular implementation of an element class. */ + + /** Constructor. */ + t8_subelement_scheme_hex_c (); + + ~t8_subelement_scheme_hex_c (); + + /** Allocate memory for a given number of elements. + * In debugging mode, ensure that all elements are valid \ref t8_element_is_valid. + */ + virtual void t8_element_new (int length, t8_element_t **elem) const; + + /** Initialize an array of allocated elements. */ + virtual void t8_element_init (int length, t8_element_t *elem, + int called_new) const; + +/** Return the maximum level allowed for this element class. */ + virtual int t8_element_maxlevel (void) const; + +/** Return the type of each child in the ordering of the implementation. */ + virtual t8_eclass_t t8_element_child_eclass (int childid) const; + +/** Return the refinement level of an element. */ + virtual int t8_element_level (const t8_element_t *elem) const; + +/** Copy one element to another */ + virtual void t8_element_copy (const t8_element_t *source, + t8_element_t *dest) const; + +/** Compare to elements. returns negativ if elem1 < elem2, zero if elem1 equals elem2 + * and positiv if elem1 > elem2. + * If elem2 is a copy of elem1 then the elements are equal. + * If both elements are sibling subelements, return 0 if they are identical (same sub_id) and 1 otherwise. + */ + virtual int t8_element_compare (const t8_element_t *elem1, + const t8_element_t *elem2) const; + +/** Construct the parent of a given element. */ + virtual void t8_element_parent (const t8_element_t *elem, + t8_element_t *parent) const; + +/** Construct a same-size sibling of a given element. */ + virtual void t8_element_sibling (const t8_element_t *elem, + int sibid, + t8_element_t *sibling) const; + + /** Compute the number of face of a given element. */ + virtual int t8_element_num_faces (const t8_element_t *elem) const; + + /** Compute the maximum number of faces of a given element and all of its + * descendants. + * \param [in] elem The element. + * \return The maximum number of faces of \a elem and its descendants. + */ + virtual int t8_element_max_num_faces (const t8_element_t *elem) + const; + + /** Return the number of children of an element when it is refined. */ + virtual int t8_element_num_children (const t8_element_t *elem) + const; + + /** Return the number of siblings of an element (or the number of elements in the family of elem) */ + virtual int t8_element_num_siblings (const t8_element_t *elem) + const; + + /** Return the number of children of an element's face when the element is refined. */ + virtual int t8_element_num_face_children (const t8_element_t *elem, + const int face) const; + + /** Return the number of children of an element's face when the element is refined. */ + virtual int t8_element_neighbor_is_sibling (const t8_element_t + *elem, int face) const; + + /** Return the number of sibling neighbors at a given face. */ + virtual int t8_element_get_num_sibling_neighbors_at_face (const + t8_element_t + *elem, + int face) + const; + + /** Return zero refine value for schemes that do not have a transition implementation. */ + virtual int t8_element_get_transition_refine_identifier (void) + const; + + /** Return the corner number of an element's face corner. */ + virtual int t8_element_get_face_corner (const t8_element_t *element, + int face, int corner) const; + + /** Return the face numbers of the faces sharing an element's corner. */ + virtual int t8_element_get_corner_face (const t8_element_t *element, + int corner, int face) const; + + /** Construct the child element of a given number. */ + virtual void t8_element_child (const t8_element_t *elem, + int childid, + t8_element_t *child) const; + + /** Construct all sibling neighbors of elem at face - it is required that sibling neighbors of elem at face exist */ + virtual void + + + + t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t + *elem, + const int face, + const int + num_neighbors, + t8_element_t + *neighbor_at_face[], + int *neigh_face); + +/** Construct all children of a given element. */ + virtual void t8_element_children (const t8_element_t *elem, + int length, + t8_element_t *c[]) const; + +/** Return the child id of an element */ + virtual int t8_element_child_id (const t8_element_t *elem) const; + + /** Compute the ancestor id of an element */ + virtual int t8_element_ancestor_id (const t8_element_t *elem, + int level) const; + +/** Return nonzero if collection of elements is a family */ + virtual int t8_element_is_family (t8_element_t **fam) const; + +/** Construct the nearest common ancestor of two elements in the same tree. */ + virtual void t8_element_nca (const t8_element_t *elem1, + const t8_element_t *elem2, + t8_element_t *nca) const; + + /** Compute the element shape of the face of an element. */ + virtual t8_element_shape_t t8_element_face_shape (const t8_element_t *elem, + int face) const; + + /** Given an element and a face of the element, compute all children of + * the element that touch the face. */ + /** Given an element and a face of the element, compute all children of + * the element that touch the face. */ + virtual void t8_element_children_at_face (const t8_element_t *elem, + int face, + t8_element_t *children[], + int num_children, + int *child_indices) const; + + /** Given a face of an element and a child number of a child of that face, return the face number + * of the child of the element that matches the child face. */ + virtual int t8_element_face_child_face (const t8_element_t *elem, + int face, + int face_child) const; + + /** Given a face of an element return the face number + * of the parent of the element that matches the element's face. Or return -1 if + * no face of the parent matches the face. */ + virtual int t8_element_face_parent_face (const t8_element_t *elem, + int face) const; + + /** Transform the coordinates of a hexaliteral considered as boundary element + * in a tree-tree connection. */ + virtual void t8_element_transform_face (const t8_element_t *elem1, + t8_element_t *elem2, + int orientation, int sign, + int is_smaller_face) const; + + /** Given a boundary face inside a root tree's face construct + * the element inside the root tree that has the given face as a + * face. */ + virtual int t8_element_extrude_face (const t8_element_t *face, + const t8_eclass_scheme_c + *face_scheme, + t8_element_t *elem, + int root_face) const; + + /** Return the tree face id given a boundary face. */ + virtual int t8_element_tree_face (const t8_element_t *elem, + int face) const; + + /** Construct the first descendant of an element that touches a given face. */ + virtual void t8_element_first_descendant_face (const t8_element_t + *elem, int face, + t8_element_t + *first_desc, + int level) const; + + /** Construct the last descendant of an element that touches a given face. */ + virtual void t8_element_last_descendant_face (const t8_element_t + *elem, int face, + t8_element_t + *last_desc, + int level) const; + + /** Construct the boundary element at a specific face. */ + virtual void t8_element_boundary_face (const t8_element_t *elem, + int face, + t8_element_t *boundary, + const t8_eclass_scheme_c + *boundary_scheme) const; + +/** Construct all codimension-one boundary elements of a given element. */ + virtual void t8_element_boundary (const t8_element_t *elem, + int min_dim, int length, + t8_element_t **boundary) const; + + /** Compute whether a given element shares a given face with its root tree. + * \param [in] elem The input element. + * \param [in] face A face of \a elem. + * \return True if \a face is a subface of the element's root element. + */ + virtual int t8_element_is_root_boundary (const t8_element_t *elem, + int face) const; + + /** Construct the face neighbor of a given element if this face neighbor + * is inside the root tree. Return 0 otherwise. */ + virtual int t8_element_face_neighbor_inside (const t8_element_t + *elem, + t8_element_t *neigh, + int face, + int *neigh_face) const; + +/** Initialize an element according to a given linear id */ + virtual void t8_element_set_linear_id (t8_element_t *elem, + int level, + t8_linearidx_t id) const; + +/** Calculate the linear id of an element */ + virtual t8_linearidx_t t8_element_get_linear_id (const + t8_element_t *elem, + int level) const; + +/** Calculate the first descendant of a given element e. That is, the + * first element in a uniform refinement of e of the maximal possible level. + */ + virtual void t8_element_first_descendant (const t8_element_t *elem, + t8_element_t *desc, + int level) const; + +/** Calculate the last descendant of a given element e. That is, the + * last element in a uniform refinement of e of the maximal possible level. + */ + virtual void t8_element_last_descendant (const t8_element_t *elem, + t8_element_t *desc, + int level) const; + +/** Compute s as a successor of t*/ + virtual void t8_element_successor (const t8_element_t *t, + t8_element_t *s, int level) const; + +/** Get the integer coordinates of the anchor node of an element */ + virtual void t8_element_anchor (const t8_element_t *elem, + int anchor[3]) const; + +/** Get the integer root length of an element, that is the length of + * the level 0 ancestor. + */ + virtual int t8_element_root_len (const t8_element_t *elem) const; + +/** Compute the integer coordinates of a given element vertex. */ + virtual void t8_element_vertex_coords (const t8_element_t *t, + int vertex, + int coords[]) const; + +/** Convert a point in the reference space of an element to a point in the + * reference space of the tree. + * + * \param [in] elem The element. + * \param [in] coords_input The coordinates of the point in the reference space of the element. + * \param [in] user_data User data. + * \param [out] out_coords The coordinates of the point in the reference space of the tree. + */ + virtual void t8_element_reference_coords (const t8_element_t *elem, + const double *ref_coords, + const void *user_data, + double *out_coords) + const; + +/** Construct a transition cell of type type */ + virtual void t8_element_to_transition_cell (const t8_element_t *elem, + int type, + t8_element_t *c[]); + +/** Determine the number of sibling subelements, of a transition cell of a specific type */ + virtual int t8_element_get_number_of_subelements (int + transition_type) + const; + +/** Test wheter a given element is a subelement or not */ + virtual int t8_element_is_subelement (const t8_element * + elem) const; + +/** Get the subelement type of elem */ + virtual int t8_element_get_transition_type (const + t8_element * elem); + +/** Get the subelement id of elem */ + virtual int t8_element_get_subelement_id (const t8_element * elem); + +/** Get the subelement id of the neighbor subelement of elem at face elem_face + * that is a sibling of the subelement neigh. + */ + virtual int t8_element_find_neighbor_in_transition_cell (const + t8_element_t + *elem, + const + t8_element_t + *neigh, + int + elem_face); + +/** Get the face-number of the hypotenuse of the triangular subelement */ + virtual int t8_element_get_face_number_of_hypotenuse (const + t8_element_t + *elem); + +/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int t8_element_scheme_supports_transitioning (void); + +/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int t8_element_transition_scheme_is_conformal (void); + +/** Returns true, if there is one element in the tree, that does not refine into 2^dim children. + * Returns false otherwise. + * \return non-zero if there is one element in the tree that does not refine into 2^dim children. + */ + virtual int t8_element_refines_irregular (void) const; + +/** Get the shape of a given element. Subelements are pyramids */ + virtual t8_element_shape_t t8_element_shape (const t8_element_t *elem) + const; + +/** Return the number of vertices of an element */ + virtual int t8_element_num_corners (const t8_element_t *elem) const; + +/** Compute the coordinates of a given element vertex inside a reference tree + * that is embedded into [0,1]^d (d = dimension). + * \param [in] t The element to be considered. + * \param [in] vertex The id of the vertex whose coordinates shall be computed. + * \param [out] coords An array of at least as many doubles as the element's dimension + * whose entries will be filled with the coordinates of \a vertex. + */ + virtual void t8_element_vertex_reference_coords (const t8_element_t + *t, int vertex, + double coords[]) + const; + +#ifdef T8_ENABLE_DEBUG +/** TODO: this should be the new element_print_element funciton */ + virtual void t8_element_debug_print (const t8_element_t *elem) const; + +/** Query whether an element is valid */ + virtual int t8_element_is_valid (const t8_element_t *t) const; +#endif + +protected: + /** This function determines the vertex coordinates of subelements. + * \param [in] elem A valid subelement + * \param [in] vertex the number of the vertex whose coordinates should be determined + * \param [out] coords An array whose entries will be filled with the coordinates of the + * subelement. + * Note that subelements can have another number of vertices compared to the used + * eclass scheme. For example, subelements that remove hanging nodes from the HEX scheme + * are triangles with 3 instead of 4 verticies. + */ + void t8_element_vertex_coords_of_subelement (const + t8_element_t *t, + int vertex, + int coords[]) + const; + + /** This function will determine the location of a specific subelement in the parent element. + * Since different subelement types are possible, it is a priori not known where for example the + * subelement with id 3 is located. + * \param [in] elem A valid subelement + * \param [out] An array, whose entries are face_number, split and sub_face_id + * face_number: the face number (clockwise enumeration), the given subelement is adjacent to (value between 0 and 3) + * It can be translated to the HEX enumeration via subelement_location_to_parent_dual_face[location[0]] + * split: whether there is a hanging node at the face, the subelement is adjacent to + * (value 0 if there is not hanging node and 1 if there is one) + * sub_face_id: if there is a hanging node at the face, it is important to know if the given + * subelement is the first or the second subelement at this face + * (value 0 if it is the first and 1 if it is the second) + * The information in the location can be used to automatically determine the verticies of any subelement. + * Since this function is only used to determine the vertices of subelements, it can be declared as a private/protected function. + */ + void t8_element_get_location_of_subelement (const + t8_element_t + *elem, + int location[]) + const; + + /** This help function returns the subelement if of an element whose location and transition type is known. */ + int t8_element_get_id_from_location (int type, + int location[]); + + /** This function copies the subelement values from source to dest. + * \param [in] source A valid element + * \param [in,out] dest A valid element, whose subelement values are equal to those of source + */ + void t8_element_copy_subelement_values (const + t8_element_t *source, + t8_element_t *dest) + const; + + /** This function resets the subelement values of an element to the default value -1. + * \param [in,out] elem A valid element, whose subelement values have been resetted. + */ + void t8_element_reset_subelement_values (t8_element_t *elem) + const; + +#ifdef T8_ENABLE_DEBUG + /** Query whether an elements subelement values are valid + * \param [in] source A element + * \return true, if the subelement values are valid + */ + int t8_element_subelement_values_are_valid (const + t8_element_t + *elem) const; +#endif +}; + +#endif /* !T8_TRANSITION_HEX_CXX_HXX */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx new file mode 100644 index 0000000000..5838ab9c68 --- /dev/null +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx @@ -0,0 +1,53 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include "t8_transition_conformal_quad_cxx.hxx" + +/* We want to export the whole implementation to be callable from "C" */ +T8_EXTERN_C_BEGIN (); + +t8_scheme_cxx_t * +t8_scheme_new_transition_quad_cxx (void) +{ + t8_scheme_cxx_t *s; + + s = T8_ALLOC_ZERO (t8_scheme_cxx_t, 1); + t8_refcount_init (&s->rc); + + s->eclass_schemes[T8_ECLASS_VERTEX] = NULL; + s->eclass_schemes[T8_ECLASS_LINE] = new t8_default_scheme_line_c (); /* Standard T8_ECLASS_LINE is used by the quad scheme */ + s->eclass_schemes[T8_ECLASS_QUAD] = new t8_subelement_scheme_quad_c (); + s->eclass_schemes[T8_ECLASS_HEX] = NULL; + s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); /* can be used for hybrid meshes - not conformal as long as no conformal transition tri class exists */ + s->eclass_schemes[T8_ECLASS_TET] = NULL; + s->eclass_schemes[T8_ECLASS_PRISM] = NULL; + s->eclass_schemes[T8_ECLASS_PYRAMID] = NULL; + + return s; +} + +T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx new file mode 100644 index 0000000000..4a4bd796d3 --- /dev/null +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -0,0 +1,2463 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* Description: + * This is the low-level structure of 2D quadrilateral elements with transition cells of triangular subelements. */ + +#include +#include +#include +#include "t8.h" +#include "t8_transition_conformal_quad_cxx.hxx" + +/* *INDENT-OFF* */ +/* Connectivity of subelement faces: + * f_0 <-> f_2 + * f_1 <-> f_1 (assuming a neighboring transition cell) + * f_2 <-> f_0 */ +const int subelement_face_dual[3] = { 2, 1, 0}; + +/* Connectivity of a subelements location within a transition cell + * and the parent quads faces: + * location[0] = 0 -> parents face = 1 + * location[0] = 1 -> parents face = 2 + * location[0] = 2 -> parents face = 0 + * location[0] = 3 -> parents face = 3 */ +const int subelement_location_to_parent_dual_face[4] = {1, 2, 0, 3}; + +/* Connectivity of a subelements location within a transition cell + * and the parent quads faces: + * location[0] = 0 (clockwise) -> parents face = 0 + * location[0] = 1 (clockwise) -> parents face = 3 + * location[0] = 2 (clockwise) -> parents face = 1 + * location[0] = 3 (clockwise) -> parents face = 2 */ +const int subelement_location_to_parent_face[4] = {0, 3, 1, 2}; +/* *INDENT-ON* */ + +/* We want to export the whole implementation to be callable from "C" */ +T8_EXTERN_C_BEGIN (); + +/* This function is used by other element functions and we thus need to + * declare it up here */ +t8_linearidx_t t8_element_get_linear_id (const t8_element_t *elem, + int level); + +int +t8_subelement_scheme_quad_c::t8_element_maxlevel (void) const +{ + return P4EST_QMAXLEVEL; +} + +/* *INDENT-OFF* */ +t8_eclass_t +t8_subelement_scheme_quad_c::t8_element_child_eclass (int childid) const +/* *INDENT-ON* */ + +{ + T8_ASSERT (0 <= childid && childid < P4EST_CHILDREN); + + return T8_ECLASS_QUAD; +} + +int +t8_subelement_scheme_quad_c::t8_element_level (const t8_element_t *elem) const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + T8_ASSERT (t8_element_is_valid (elem)); + return (int) ((const t8_quad_with_subelements *) pquad_w_sub)->p4q.level; +} + +static void +t8_element_copy_surround (const p4est_quadrant_t * q, p4est_quadrant_t * r) +{ + T8_QUAD_SET_TDIM (r, T8_QUAD_GET_TDIM (q)); + if (T8_QUAD_GET_TDIM (q) == 3) { + T8_QUAD_SET_TNORMAL (r, T8_QUAD_GET_TNORMAL (q)); + T8_QUAD_SET_TCOORD (r, T8_QUAD_GET_TCOORD (q)); + } +} + +void +t8_subelement_scheme_quad_c::t8_element_copy (const t8_element_t *source, + t8_element_t *dest) const +{ + const t8_quad_with_subelements *pquad_w_sub_source = + (const t8_quad_with_subelements *) source; + t8_quad_with_subelements *pquad_w_sub_dest = + (t8_quad_with_subelements *) dest; + + const p4est_quadrant_t *q = &pquad_w_sub_source->p4q; + p4est_quadrant_t *r = &pquad_w_sub_dest->p4q; + + T8_ASSERT (t8_element_is_valid (source)); + T8_ASSERT (t8_element_is_valid (dest)); + if (q == r && + pquad_w_sub_source->transition_type == + pquad_w_sub_dest->transition_type && + pquad_w_sub_source->subelement_id == pquad_w_sub_dest->subelement_id) { + /* Do nothing if they are already the same quadrant. */ + return; + } + *r = *q; + + t8_element_copy_subelement_values (source, dest); + t8_element_copy_surround (q, r); +} + +int +t8_subelement_scheme_quad_c::t8_element_compare (const t8_element_t *elem1, + const t8_element_t *elem2) + const +{ + const t8_quad_with_subelements *pquad_w_sub_elem1 = + (const t8_quad_with_subelements *) elem1; + const t8_quad_with_subelements *pquad_w_sub_elem2 = + (const t8_quad_with_subelements *) elem2; + + const p4est_quadrant_t *q = &pquad_w_sub_elem1->p4q; + const p4est_quadrant_t *r = &pquad_w_sub_elem2->p4q; + + T8_ASSERT (t8_element_is_valid (elem1)); + T8_ASSERT (t8_element_is_valid (elem2)); + + int compare = p4est_quadrant_compare (q, r); + + if (compare == 0 && (t8_element_is_subelement (elem1) + || t8_element_is_subelement (elem2))) { + t8_debugf ("Caution, t8_element_compare is used with subelements.\n"); + if (t8_element_is_subelement (elem1) + && t8_element_is_subelement (elem2)) { + /* Caution: The compare function is used for two subelements. */ + + if (pquad_w_sub_elem1->transition_type == + pquad_w_sub_elem2->transition_type + && pquad_w_sub_elem1->subelement_id == + pquad_w_sub_elem2->subelement_id) { + /* both subelements are identical */ + return 0; + } + /* return != 0 to avoid debug abortion in t8_ghost_add_remote */ + return 1; + } + else if (t8_element_is_subelement (elem1)) { + return -1; /* elem1 is subelement and therefore smaller */ + } + else if (t8_element_is_subelement (elem2)) { + return 1; /* elem2 is subelement and therefore smaller */ + } + } + + /* Note that for subelements, their parent quadrant is compared at this point */ + return compare; +} + +void +t8_subelement_scheme_quad_c::t8_element_parent (const t8_element_t *elem, + t8_element_t *parent) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_parent = + (t8_quad_with_subelements *) parent; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + p4est_quadrant_t *r = &pquad_w_sub_parent->p4q; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (parent)); + + if (t8_element_is_subelement (elem)) { + pquad_w_sub_parent->p4q = pquad_w_sub_elem->p4q; + } + else { + p4est_quadrant_parent (q, r); + } + + /* the parent of any element will never be a subelement */ + t8_element_reset_subelement_values (parent); + + t8_element_copy_surround (q, r); +} + +void +t8_subelement_scheme_quad_c::t8_element_sibling (const t8_element_t *elem, + int sibid, + t8_element_t *sibling) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_sibling = + (t8_quad_with_subelements *) sibling; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + p4est_quadrant_t *r = &pquad_w_sub_sibling->p4q; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (sibling)); + + p4est_quadrant_sibling (q, r, sibid); + t8_element_copy_surround (q, r); +} + +int +t8_subelement_scheme_quad_c::t8_element_num_faces (const t8_element_t *elem) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + return (t8_element_is_subelement (elem) ? T8_QUAD_SUBELEMENT_FACES : + P4EST_FACES); +} + +int +t8_subelement_scheme_quad_c::t8_element_max_num_faces (const t8_element_t + *elem) const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + return P4EST_FACES; +} + +int +t8_subelement_scheme_quad_c::t8_element_num_children (const t8_element_t + *elem) const +{ + /* Note that children of subelements equal the children of the parent quadrant. + * Therefore, the number of children of a subelement equals P4EST_CHILDREN */ + T8_ASSERT (t8_element_is_valid (elem)); + return P4EST_CHILDREN; +} + +/* *INDENT-OFF* */ +/* indent bug, indent adds a second "const" modifier */ +int +t8_subelement_scheme_quad_c::t8_element_num_siblings (const t8_element_t * + elem) const +/* *INDENT-ON* */ + +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + + if (pquad_w_sub->transition_type == 0) + return P4EST_FACES; + + int num_hanging_faces = 0; + int iface; + for (iface = 0; iface < P4EST_FACES; iface++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ + num_hanging_faces += + (pquad_w_sub->transition_type & (1 << iface)) >> iface; + } + + return P4EST_CHILDREN + num_hanging_faces; +} + +int +t8_subelement_scheme_quad_c::t8_element_num_face_children (const t8_element_t + *elem, + int face) const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (t8_element_is_valid (elem)); + + /* if we use this scheme without set_transition, then we are only balanced and two neighbors are possible */ + return 2; +} + +int +t8_subelement_scheme_quad_c::t8_element_neighbor_is_sibling (const + t8_element_t + *elem, + const int face) + const +{ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_subelement (elem)); + + if (face == 0 || face == 2) { + return 1; + } + + return 0; +} + +/* *INDENT-OFF* */ +int +t8_subelement_scheme_quad_c::t8_element_get_num_sibling_neighbors_at_face (const t8_element_t *elem, + const int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_subelement (elem)); + T8_ASSERT (face == 0 || face == 2); + + return 1; +} + +int +t8_subelement_scheme_quad_c::t8_element_get_transition_refine_identifier () const +{ + return T8_TRANSITION_CONFORMAL_QUAD_REFINE_FUNCTION; +} +/* *INDENT-ON* */ + +int +t8_subelement_scheme_quad_c::t8_element_get_face_corner (const t8_element_t + *elem, int face, + int corner) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + if (!t8_element_is_subelement (elem)) { + /* + * 2 f_2 3 + * x -->-- x + * | | + * ^ ^ + * f_0 | | f_1 + * x -->-- x + * 0 f_3 1 + */ + + T8_ASSERT (0 <= face && face < P4EST_FACES); + T8_ASSERT (0 <= corner && corner < 4); + + return p4est_face_corners[face][corner]; + } + else { + int t8_face_corners_subelement[3][2] = { + {0, 1}, + {1, 2}, + {2, 0} + }; + /* + * + * x - - - - - x 1 + * | \ f0 / | + * | \ 0 / | + * x - - x el | f1 + * | / \ | + * | / f2 \ | + * x - - x - - x 2 + * + * The vertecies of a subelement are enumerated clockwise, starting with the center vertex of the transition cell + */ + + T8_ASSERT (0 <= face && face < T8_QUAD_SUBELEMENT_FACES); + T8_ASSERT (0 <= corner && corner < 3); + + return t8_face_corners_subelement[face][corner]; + } +} + +int +t8_subelement_scheme_quad_c::t8_element_get_corner_face (const t8_element_t + *elem, int corner, + int face) const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (0 <= corner && corner < P4EST_CHILDREN); + T8_ASSERT (0 <= face && face < 2); + + return p4est_corner_faces[corner][face]; +} + +void +t8_subelement_scheme_quad_c::t8_element_child (const t8_element_t *elem, + int childid, + t8_element_t *child) const +{ + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + /* + * + * x - - - - - x x - - x - - x + * | | | | | + * | | | 2 | 3 | + * | elem | => x - - x - - x + * | | | | | + * | | | 0 | 1 | + * x - - - - - x x - - x - - x + * + */ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_child = + (t8_quad_with_subelements *) child; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + p4est_quadrant_t *r = &pquad_w_sub_child->p4q; + + const p4est_qcoord_t shift = P4EST_QUADRANT_LEN (q->level + 1); + + /* it should not be possible to construct a child of a subelement */ + // T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (child)); + T8_ASSERT (p4est_quadrant_is_extended (q)); + T8_ASSERT (q->level < P4EST_QMAXLEVEL); + + T8_ASSERT (childid >= 0 && childid < P4EST_CHILDREN); + + r->x = childid & 0x01 ? (q->x | shift) : q->x; + r->y = childid & 0x02 ? (q->y | shift) : q->y; + r->level = q->level + 1; + + T8_ASSERT (p4est_quadrant_is_parent (q, r)); + + t8_element_reset_subelement_values (child); + + t8_element_copy_surround (q, r); +} + +/* *INDENT-OFF* */ +void +t8_subelement_scheme_quad_c::t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t + *elem, const int face, + const int num_neighbors, + t8_element_t + *neighbor_at_face[], + int *neigh_face[]) +{ + T8_ASSERT (t8_element_is_subelement (elem)); + T8_ASSERT (t8_element_neighbor_is_sibling (elem, face)); + T8_ASSERT (num_neighbors == 1); + T8_ASSERT (t8_element_is_valid (neighbor_at_face[0])); + + /* If face = 0, then the sibling subelement neighbor is the next subelement in counter clockwise enumeration, + * if face = 2, then it is the sibling subelement neighbor in clockwise enumeration. */ + t8_element_copy (elem, neighbor_at_face[0]); + + t8_quad_with_subelements * + pquad_w_sub_neighbor_at_face = + (t8_quad_with_subelements *) neighbor_at_face[0]; + + int + num_siblings = t8_element_num_siblings (elem); + + if (face == 0) { + /* adjust subelement id counter clockwise */ + if (pquad_w_sub_neighbor_at_face->subelement_id == 0) { + pquad_w_sub_neighbor_at_face->subelement_id += num_siblings - 1; + } + else { + pquad_w_sub_neighbor_at_face->subelement_id -= 1; + } + } + else { + /* adjust subelement id clockwise */ + if (pquad_w_sub_neighbor_at_face->subelement_id == num_siblings - 1) { + pquad_w_sub_neighbor_at_face->subelement_id = 0; + } + else { + pquad_w_sub_neighbor_at_face->subelement_id += 1; + } + } + + /* return dual face with resprect to neighboring sibling subelement */ + /* Compute the face number as seen from elem. + * 0 -> 2 2 -> 0 + */ + *neigh_face[0] = subelement_face_dual[face]; +} +/* *INDENT-ON* */ + +void +t8_subelement_scheme_quad_c::t8_element_children (const t8_element_t *elem, + int length, + t8_element_t *c[]) const +{ + /* if elem is a subelement, then this function will construct the children of its parent p4est quadrant */ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements **pquad_w_sub_children = + (t8_quad_with_subelements **) c; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + + int ichild; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (length == P4EST_CHILDREN); + +#ifdef T8_ENABLE_DEBUG + { + int i; + for (i = 0; i < P4EST_CHILDREN; i++) { + T8_ASSERT (t8_element_is_valid (c[i])); + } + } +#endif + + /* set coordinates and levels of the children */ + p4est_quadrant_children (q, &pquad_w_sub_children[0]->p4q, + &pquad_w_sub_children[1]->p4q, + &pquad_w_sub_children[2]->p4q, + &pquad_w_sub_children[3]->p4q); + + for (ichild = 0; ichild < P4EST_CHILDREN; ++ichild) { + t8_element_reset_subelement_values (c[ichild]); + t8_element_copy_surround (q, &pquad_w_sub_children[ichild]->p4q); + } +} + +int +t8_subelement_scheme_quad_c::t8_element_child_id (const t8_element_t *elem) const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + const p4est_quadrant_t *q = &pquad_w_sub->p4q; + + T8_ASSERT (t8_element_is_valid (elem)); + + return (t8_element_is_subelement (elem) ? pquad_w_sub->subelement_id : + p4est_quadrant_child_id (q)); +} + +int +t8_subelement_scheme_quad_c::t8_element_ancestor_id (const t8_element_t *elem, + int level) const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + const p4est_quadrant_t *q = &pquad_w_sub->p4q; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + return p4est_quadrant_ancestor_id (q, level); +} + +int +t8_subelement_scheme_quad_c::t8_element_is_family (t8_element_t **fam) const +{ + /* Note that this test is very rudimentary, especially when there subelements are in fam */ + t8_quad_with_subelements **pquad_w_sub_family = + (t8_quad_with_subelements **) fam; + +#ifdef T8_ENABLE_DEBUG + { + int i; + int num_siblings = t8_element_num_siblings (fam[0]); + for (i = 0; i < num_siblings; i++) { + T8_ASSERT (t8_element_is_valid (fam[i])); + } + } +#endif + + /* Subelements can not be refined into other elements of a higher level. + * So if the first element of fam is a subelement, we assume that the following num_siblings + * many elements are its siblings and therefore form a family. */ + if (pquad_w_sub_family[0]->transition_type != 0) { + return 1; + } + /* If the first element of fam is no subelement we check the following elements of fam */ + else { + /* If any of the following elements is a subelement, then they can not form a family */ + if (pquad_w_sub_family[1]->transition_type != 0 || + pquad_w_sub_family[2]->transition_type != 0 || + pquad_w_sub_family[3]->transition_type != 0) { + return 0; + } + /* If all elements of fam are no subelements, then we can use the p4est check is_family */ + else { + return p4est_quadrant_is_family (&pquad_w_sub_family[0]->p4q, + &pquad_w_sub_family[1]->p4q, + &pquad_w_sub_family[2]->p4q, + &pquad_w_sub_family[3]->p4q); + } + } +} + +void +t8_subelement_scheme_quad_c::t8_element_set_linear_id (t8_element_t *elem, + int level, + t8_linearidx_t id) + const +{ + t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; + p4est_quadrant_t *q = &pquad_w_sub->p4q; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << P4EST_DIM * level); + + p4est_quadrant_set_morton (q, level, id); + T8_QUAD_SET_TDIM (q, 2); +} + +t8_linearidx_t + t8_subelement_scheme_quad_c::t8_element_get_linear_id (const t8_element_t + *elem, + int level) const +{ + t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; + p4est_quadrant_t *q = &pquad_w_sub->p4q; + + /* Note that the id of a subelement equals the id of its parent quadrant. + * Therefore, the binary search (for example used in the leaf_face_neighbor function) + * will find a random subelement of the transition cell which might not be the desired neighbor of a given element. */ + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + + return p4est_quadrant_linear_id (q, level); +} + +void +t8_subelement_scheme_quad_c::t8_element_first_descendant (const t8_element_t + *elem, + t8_element_t *desc, + int level) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_desc = + (t8_quad_with_subelements *) desc; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + p4est_quadrant_t *r = &pquad_w_sub_desc->p4q; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (desc)); + T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + + p4est_quadrant_first_descendant (q, r, level); + T8_QUAD_SET_TDIM (r, 2); + + /* We allow constructing a last descendant from a subelement. + * Keep in mind, that transforming a quad element to a subelement does not change the + * p4est quadrant. Therefore, we are constructing the last descendant of the parent + * quad element of the given subelement. Since the last descendant is not meant to be + * a subelement, we reset the corresponding subelement values. */ + t8_element_reset_subelement_values (desc); +} + +void +t8_subelement_scheme_quad_c::t8_element_last_descendant (const t8_element_t + *elem, + t8_element_t *desc, + int level) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_desc = + (t8_quad_with_subelements *) desc; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + p4est_quadrant_t *r = &pquad_w_sub_desc->p4q; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (desc)); + T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + + p4est_quadrant_last_descendant (q, r, level); + T8_QUAD_SET_TDIM (r, 2); + + /* We allow constructing a last descendant from a subelement. + * Keep in mind, that transforming a quad element to a subelement does not change the + * p4est quadrant. Therefore, we are constructing the last descendant of the parent + * quad element of the given subelement. Since the last descendant is not meant to be + * a subelement, we reset the corresponding subelement values. */ + t8_element_reset_subelement_values (desc); +} + +void +t8_subelement_scheme_quad_c::t8_element_successor (const t8_element_t *elem1, + t8_element_t *elem2, + int level) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem1 = + (const t8_quad_with_subelements *) elem1; + t8_quad_with_subelements *pquad_w_sub_elem2 = + (t8_quad_with_subelements *) elem2; + + const p4est_quadrant_t *q = &pquad_w_sub_elem1->p4q; + p4est_quadrant_t *r = &pquad_w_sub_elem2->p4q; + + t8_linearidx_t id; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem1)); + + T8_ASSERT (t8_element_is_valid (elem1)); + T8_ASSERT (t8_element_is_valid (elem2)); + T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + + id = p4est_quadrant_linear_id (q, level); + T8_ASSERT (id + 1 < ((t8_linearidx_t) 1) << P4EST_DIM * level); + t8_element_reset_subelement_values (elem2); + p4est_quadrant_set_morton (r, level, id + 1); + t8_element_copy_surround (q, r); +} + +void +t8_subelement_scheme_quad_c::t8_element_nca (const t8_element_t *elem1, + const t8_element_t *elem2, + t8_element_t *nca) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem1 = + (const t8_quad_with_subelements *) elem1; + const t8_quad_with_subelements *pquad_w_sub_elem2 = + (const t8_quad_with_subelements *) elem2; + t8_quad_with_subelements *pquad_w_sub_nca = + (t8_quad_with_subelements *) nca; + + const p4est_quadrant_t *q1 = &pquad_w_sub_elem1->p4q; + const p4est_quadrant_t *q2 = &pquad_w_sub_elem2->p4q; + p4est_quadrant_t *r = &pquad_w_sub_nca->p4q; + + T8_ASSERT (t8_element_is_valid (elem1)); + T8_ASSERT (t8_element_is_valid (elem2)); +#if 0 + /* TODO: This assertions throws an error since it expects a 3D hex. + * this does not make sense. investigate. */ + T8_ASSERT (t8_element_surround_matches (q1, q2)); +#endif + + /* In case of subelements, we use the parent quadrant and construct nca of the parent quadrant */ + t8_element_reset_subelement_values (nca); + p4est_nearest_common_ancestor (q1, q2, r); + t8_element_copy_surround (q1, r); +} + +t8_element_shape_t +t8_subelement_scheme_quad_c::t8_element_face_shape (const t8_element_t *elem, + int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + return T8_ECLASS_LINE; +} + +void +t8_subelement_scheme_quad_c::t8_element_children_at_face (const t8_element_t + *elem, int face, + t8_element_t + *children[], + int num_children, + int *child_indices) + const +{ +#ifdef T8_ENABLE_DEBUG + { + int i; + for (i = 0; i < num_children; i++) { + T8_ASSERT (t8_element_is_valid (children[i])); + } + } +#endif + /* This function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (0 <= face && face < P4EST_FACES); + T8_ASSERT (num_children == t8_element_num_face_children (elem, face)); + + /* + * Compute the child id of the first and second child at the face. + * + * 3 + * + * x - - x - - x This picture shows a refined quadrant + * | | | with child_ids and the label for the faces. + * | 2 | 3 | For examle for face 2 (bottom face) we see + * 0 x - - x - - x 1 first_child = 0 and second_child = 1. + * | | | + * | 0 | 1 | + * x - - x - - x + * + * 2 + */ + + T8_ASSERT (num_children == 2); + int first_child; + int second_child; + /* TODO: Think about a short and easy bitwise formula. */ + switch (face) { + case 0: + first_child = 0; + second_child = 2; + break; + case 1: + first_child = 1; + second_child = 3; + break; + case 2: + first_child = 0; + second_child = 1; + break; + case 3: + first_child = 2; + second_child = 3; + break; + default: + SC_ABORT_NOT_REACHED (); + } + + /* From the child ids we now construct the children at the faces. */ + /* We have to revert the order and compute second child first, since + * the usage allows for elem == children[0]. + */ + this->t8_element_child (elem, second_child, children[1]); + this->t8_element_child (elem, first_child, children[0]); + if (child_indices != NULL) { + child_indices[0] = first_child; + child_indices[1] = second_child; + } +} + +int +t8_subelement_scheme_quad_c::t8_element_face_child_face (const t8_element_t + *elem, int face, + int face_child) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + if (t8_element_is_subelement (elem)) { + T8_ASSERT (face == 1); + return t8_element_face_parent_face (elem, face); + } + else { + /* For quadrants the face enumeration of children is the same as for the parent. */ + return face; + } +} + +int +t8_subelement_scheme_quad_c::t8_element_face_parent_face (const t8_element_t + *elem, + int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (face >= -1 && face <= P4EST_FACES); + + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + const p4est_quadrant_t *q = &pquad_w_sub->p4q; + + int child_id; + + if (face == -1) { + return -1; + } + + /* For subelements we need to adjust the output of this function. + * A subelements face is a subface of the parent quadrant (the transition cell) if and only if the face number is 1. */ + if (t8_element_is_subelement (elem)) { + if (face == 1) { + /* In this case the face is a subface of the parent. We use the location function in order + * to determine which of the parents faces intersects the subelements face. */ + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + + /* subelements in location are enumerated clockwise (not as quadrant faces) */ + return subelement_location_to_parent_face[location[0]]; + } + else { + return -1; + } + } + + if (q->level == 0) { + return face; + } + /* Determine whether face is a subface of the parent. + * This is the case if the child_id matches one of the faces corners */ + child_id = p4est_quadrant_child_id (q); + if (child_id == p4est_face_corners[face][0] + || child_id == p4est_face_corners[face][1]) { + return face; + } + return -1; +} + +void +t8_subelement_scheme_quad_c::t8_element_transform_face (const t8_element_t + *elem1, + t8_element_t *elem2, + int orientation, + int sign, + int is_smaller_face) + const +{ + const t8_quad_with_subelements *pquad_w_sub_elem1 = + (const t8_quad_with_subelements *) elem1; + t8_quad_with_subelements *pquad_w_sub_elem2 = + (t8_quad_with_subelements *) elem2; + + const p4est_quadrant_t *qin = &pquad_w_sub_elem1->p4q; + p4est_quadrant_t *p = &pquad_w_sub_elem2->p4q; + + const p4est_quadrant_t *q; + p4est_qcoord_t h = P4EST_QUADRANT_LEN (qin->level); + p4est_qcoord_t x = qin->x; /* temp storage for x coordinate in case elem1 = elem 2 */ + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem1)); + T8_ASSERT (t8_element_is_valid (elem1)); + T8_ASSERT (t8_element_is_valid (elem2)); + T8_ASSERT (0 <= orientation && orientation < P4EST_FACES); + + if (sign) { + /* The tree faces have the same topological orientation, and + * thus we have to perform a coordinate switch. */ + /* We use p as storage, since elem1 and elem2 are allowed to + * point to the same quad */ + q = (const p4est_quadrant_t *) p; + t8_element_copy_surround (qin, (p4est_quadrant_t *) q); + ((p4est_quadrant_t *) q)->x = qin->y; + ((p4est_quadrant_t *) q)->y = x; + x = q->x; /* temp storage in case elem1 = elem 2 */ + } + else { + q = qin; + } + + p->level = q->level; + /* + * The faces of the root quadrant are enumerated like this: + * + * v_2 v_3 + * x -->-- x + * | | + * ^ ^ + * | | + * x -->-- x + * v_0 v_1 + * + * Orientation is the corner number of the bigger face that coincides + * with the corner v_0 of the smaller face. + */ + /* If this face is not smaller, switch the orientation: + * sign = 0 sign = 1 + * 0 -> 0 0 -> 0 + * 1 -> 2 1 -> 1 + * 2 -> 1 2 -> 2 + * 3 -> 3 3 -> 3 + */ + if (!is_smaller_face && (orientation == 1 || orientation == 2) && !sign) { + orientation = 3 - orientation; + } + + switch (orientation) { + case 0: /* Nothing to do */ + p->x = q->x; + p->y = q->y; + break; + case 1: + p->x = P4EST_ROOT_LEN - q->y - h; + p->y = x; + break; + case 2: + p->x = q->y; + p->y = P4EST_ROOT_LEN - x - h; + break; + case 3: + p->x = P4EST_ROOT_LEN - q->x - h; + p->y = P4EST_ROOT_LEN - q->y - h; + break; + default: + SC_ABORT_NOT_REACHED (); + } + T8_QUAD_SET_TDIM (p, 2); + + t8_element_reset_subelement_values (elem2); +} + +int +t8_subelement_scheme_quad_c::t8_element_extrude_face (const t8_element_t + *face, + const t8_eclass_scheme_c + *face_scheme, + t8_element_t *elem, + int root_face) const +{ + /* build (extrude) elem from a given face element */ + t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; + p4est_quadrant_t *q = &pquad_w_sub->p4q; + + const t8_dline_t *l = (const t8_dline_t *) face; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (T8_COMMON_IS_TYPE + (face_scheme, const t8_default_scheme_line_c *)); + T8_ASSERT (face_scheme->eclass == T8_ECLASS_LINE); + T8_ASSERT (face_scheme->t8_element_is_valid (elem)); + T8_ASSERT (0 <= root_face && root_face < P4EST_FACES); + + /* + * The faces of the root quadrant are enumerated like this: + * + * f_2 + * x -->-- x + * | | + * ^ ^ + * f_0 | | f_1 + * x -->-- x + * f_3 + * + * The arrows >,^ denote the orientation of the faces. + * We need to scale the coordinates since a root line may have a different + * length than a root quad. + */ + q->level = l->level; + switch (root_face) { + case 0: + q->x = 0; + q->y = ((int64_t) l->x * P4EST_ROOT_LEN) / T8_DLINE_ROOT_LEN; + break; + case 1: + q->x = P4EST_LAST_OFFSET (q->level); + q->y = ((int64_t) l->x * P4EST_ROOT_LEN) / T8_DLINE_ROOT_LEN; + break; + case 2: + q->x = ((int64_t) l->x * P4EST_ROOT_LEN) / T8_DLINE_ROOT_LEN; + q->y = 0; + break; + case 3: + q->x = ((int64_t) l->x * P4EST_ROOT_LEN) / T8_DLINE_ROOT_LEN; + q->y = P4EST_LAST_OFFSET (q->level); + break; + default: + SC_ABORT_NOT_REACHED (); + } + t8_element_reset_subelement_values (elem); + /* We return the face of q at which we extruded. This is the same number + * as root_face. */ + return root_face; +} + +int +t8_subelement_scheme_quad_c::t8_element_tree_face (const t8_element_t *elem, + int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + /* If elem is a subelement, then this function should only be called together with + * face = 1 since other faces will never intersect a tree face. */ + if (t8_element_is_subelement (elem)) { + T8_ASSERT (face == 1); + + return t8_element_face_parent_face (elem, face); + } + else { + T8_ASSERT (0 <= face && face < P4EST_FACES); + /* For quadrants the face and the tree face number are the same. */ + return face; + } +} + +/** Construct the first descendant of an element that touches a given face. */ +void +t8_subelement_scheme_quad_c::t8_element_first_descendant_face (const + t8_element_t + *elem, + int face, + t8_element_t + *first_desc, + int level) + const +{ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_first_desc = + (t8_quad_with_subelements *) first_desc; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + p4est_quadrant_t *desc = &pquad_w_sub_first_desc->p4q; + + int first_face_corner; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (0 <= face && face < P4EST_FACES); + T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + + /* Get the first corner of q that belongs to face */ + first_face_corner = p4est_face_corners[face][0]; + /* Construce the descendant in that corner */ + p4est_quadrant_corner_descendant (q, desc, first_face_corner, level); + t8_element_reset_subelement_values (first_desc); +} + +/** Construct the last descendant of an element that touches a given face. */ +void +t8_subelement_scheme_quad_c::t8_element_last_descendant_face (const + t8_element_t + *elem, int face, + t8_element_t + *last_desc, + int level) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_last_desc = + (t8_quad_with_subelements *) last_desc; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + p4est_quadrant_t *desc = &pquad_w_sub_last_desc->p4q; + + int last_face_corner; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (!t8_element_is_subelement (last_desc)); + T8_ASSERT (0 <= face && face < P4EST_FACES); + T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + + /* Get the last corner of q that belongs to face */ + last_face_corner = p4est_face_corners[face][1]; + /* Construce the descendant in that corner */ + p4est_quadrant_corner_descendant (q, desc, last_face_corner, level); + t8_element_reset_subelement_values (last_desc); +} + +void +t8_subelement_scheme_quad_c::t8_element_boundary_face (const t8_element_t + *elem, int face, + t8_element_t *boundary, + const + t8_eclass_scheme_c + *boundary_scheme) const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + const p4est_quadrant_t *q = &pquad_w_sub->p4q; + + t8_dline_t *l = (t8_dline_t *) boundary; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (T8_COMMON_IS_TYPE + (boundary_scheme, const t8_default_scheme_line_c *)); + T8_ASSERT (boundary_scheme->eclass == T8_ECLASS_LINE); + T8_ASSERT (boundary_scheme->t8_element_is_valid (boundary)); + + if (!t8_element_is_subelement (elem)) { + T8_ASSERT (0 <= face && face < P4EST_FACES); + /* The level of the boundary element is the same as the quadrant's level */ + l->level = q->level; + /* + * The faces of the quadrant are enumerated like this: + * f_2 + * x ---- x + * | | + * f_0 | | f_1 + * x ---- x + * f_3 + * + * If face = 0 or face = 1 then l->x = q->y + * if face = 2 or face = 3 then l->x = q->x + */ + l->x = ((face >> 1 ? q->x : q->y) * + ((int64_t) T8_DLINE_ROOT_LEN) / P4EST_ROOT_LEN); + } + else { + /* face number 1 is the only face of a subelement that points outward of the transition cell */ + T8_ASSERT (face == 1); + /* boundary faces of subelements: + * + * x - - - - - x + * | \ / | + * | \ / | + * x - - x e2 | f1 + * |e1 / \ | + * f1 | / \ | + * x - - x - - x + * + * for a split subelement (e1), the boundary face has a higher level + * for a non split element (e2), the boundary face has the same level. + */ + + int location[3] = { }; /* location = {location of subelement (face number of transition cell), split, first or second element if split} */ + t8_element_get_location_of_subelement (elem, location); + int split = location[1]; + int second = location[2]; + + if (split) { /* if the subelement lies at a split face */ + l->level = q->level + 1; + int len = + P4EST_QUADRANT_LEN (pquad_w_sub->p4q.level + 1); + if (second) { /* second subelement */ + if (location[0] == 0) { /* left face */ + l->x = q->y + len; + } + else if (location[0] == 1) { /* upper face */ + l->x = q->x + len; + } + else if (location[0] == 2) { /* right face */ + l->x = q->y; + } + else { /* lower face */ + l->x = q->x; + } + } + else { /* first subelement */ + if (location[0] == 0) { /* left face */ + l->x = q->y; + } + else if (location[0] == 1) { /* upper face */ + l->x = q->x; + } + else if (location[0] == 2) { /* right face */ + l->x = q->y + len; + } + else { /* lower face */ + l->x = q->x + len; + } + } + } + else { /* if the subelement is not split */ + l->level = q->level; + if (location[0] == 0) { /* left face */ + l->x = q->y; + } + else if (location[0] == 1) { /* upper face */ + l->x = q->x; + } + else if (location[0] == 2) { /* right face */ + l->x = q->y; + } + else { /* lower face */ + l->x = q->x; + } + } + } +} + +void +t8_subelement_scheme_quad_c::t8_element_boundary (const t8_element_t *elem, + int min_dim, int length, + t8_element_t **boundary) + const +{ + SC_ABORT ("Not implemented\n"); +#if 0 +#ifdef T8_ENABLE_DEBUG + int per_eclass[T8_ECLASS_COUNT]; +#endif + int iface; + + T8_ASSERT (length == + t8_eclass_count_boundary (T8_ECLASS_QUAD, min_dim, per_eclass)); + + T8_ASSERT (length == P4EST_FACES); + for (iface = 0; iface < P4EST_FACES; iface++) { + t8_element_boundary_face (elem, iface, boundary[iface]); + } +#endif +} + +int +t8_subelement_scheme_quad_c::t8_element_is_root_boundary (const t8_element_t + *elem, + int face) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + const p4est_quadrant_t *q = &pquad_w_sub->p4q; + + p4est_qcoord_t coord; + + /* In case of a subelement, we need to change its face number to the face number of the parent quad */ + if (t8_element_is_subelement (elem)) { + if (face == 1) { + /* adjust face of subelement to face of parent */ + face = t8_element_face_parent_face (elem, face); + } + else { /* in case of a subelement and face 0 or 2 the face is no subface of the root boundary */ + return 0; + } + } + + T8_ASSERT (0 <= face && face < P4EST_FACES); + + /* if face is 0 or 1 q->x + * 2 or 3 q->y + */ + coord = face >> 1 ? q->y : q->x; + /* If face is 0 or 2 check against 0. + * If face is 1 or 3 check against LAST_OFFSET */ + return coord == (face & 1 ? P4EST_LAST_OFFSET (q->level) : 0); +} + +int +t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const + t8_element_t + *elem, + t8_element_t + *neigh, + int face, + int *neigh_face) + const +{ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (neigh)); + T8_ASSERT (0 <= face && face < P4EST_FACES); + + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_neigh = + (t8_quad_with_subelements *) neigh; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + p4est_quadrant_t *n = &pquad_w_sub_neigh->p4q; + + /* In case of a subelement one should construct the face neighbor of the face-corresponding child quadrant + * of the subelements parent quadrant. Therefore we might want to adjust the level and adapt the + * anchor node. */ + if (t8_element_is_subelement (elem)) { /* if elem is a subelement */ + + T8_ASSERT (0 <= face && face < T8_QUAD_SUBELEMENT_FACES); + + if (face == 0) { /* in this case the face neighbor of the subelement is a sibling */ + /* level and anchor stay the same */ + n->x = q->x; + n->y = q->y; + n->level = q->level; + } + if (face == 2) { /* in this case the face neighbor of the subelement is a sibling */ + /* level and anchor stay the same */ + n->x = q->x; + n->y = q->y; + n->level = q->level; + } + if (face == 1) { /* in this case the face neighbor is no sibling */ + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + + /* setting the anchor node of the neighbor element */ + n->x = q->x; + n->y = q->y; + + /* half the side length of the transition cell of the subelement */ + const p4est_qcoord_t shift = P4EST_QUADRANT_LEN (q->level + 1); + + int split = location[1]; + int second = location[2]; + + /* we need to take into account whether the subelement is split or not */ + if (split) { /* split */ + + /* increase the level by one */ + n->level = q->level + 1; + + /* adjust the anchor node of the neighbor of the subelement depending on its location */ + if (location[0] == 0) { /* left face */ + if (!second) { + n->x = q->x - shift; + } + else { + n->x = q->x - shift; + n->y = q->y + shift; + } + } + else if (location[0] == 2) { /* right face */ + if (!second) { + n->x = q->x + 2 * shift; + n->y = q->y + shift; + } + else { + n->x = q->x + 2 * shift; + } + } + else if (location[0] == 3) { /* lower face */ + if (!second) { + n->x = q->x + shift; + n->y = q->y - shift; + } + else { + n->y = q->y - shift; + } + } + else { /* upper face */ + if (!second) { + n->y = q->y + 2 * shift; + } + else { + n->x = q->x + shift; + n->y = q->y + 2 * shift; + } + } + } + + else { /* not split */ + /* level stays the same */ + n->level = q->level; + + /* adjust the anchor node of the neighbor of the subelement depending on its location */ + if (location[0] == 0) { /* left face */ + n->x = q->x - 2 * shift; + } + else if (location[0] == 2) { /* right face */ + n->x = q->x + 2 * shift; + } + else if (location[0] == 3) { /* lower face */ + n->y = q->y - 2 * shift; + } + else { /* upper face */ + n->y = q->y + 2 * shift; + } + } + } + } + else { /* if elem is no subelement */ + /* Directly construct the face neighbor */ + p4est_quadrant_face_neighbor (q, face, n); + } + + t8_element_reset_subelement_values (neigh); + + T8_QUAD_SET_TDIM (n, 2); + + /* In the following we set the dual faces of our element at the given face. */ + if (t8_element_is_subelement (elem)) { + if (face == 1) { + /* return dual face with respect to neighboring quad element */ + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + /* if the face is pointing outwards, then we set the face equal to the transition cell face and determine its dual face. + * Compute the face number as seen from q. + * 0 -> 1 1 -> 2 2 -> 0 3 -> 3 + */ + *neigh_face = subelement_location_to_parent_dual_face[location[0]]; + } + else { + T8_ASSERT (face == 0 || face == 2); + /* return dual face with resprect to neighboring sibling subelement (note that the constructed neigh is NOT a subelement but the parent quad) */ + /* Compute the face number as seen from q. + * 0 -> 2 2 -> 0 + */ + *neigh_face = subelement_face_dual[face]; + } + } + else { + /* Compute the face number as seen from q. + * 0 -> 1 1 -> 0 2 -> 3 3 -> 2 + */ + T8_ASSERT (neigh_face != NULL); + *neigh_face = p4est_face_dual[face]; + } + + /* return true if neigh is inside the root */ + return p4est_quadrant_is_inside_root (n); +} + +void +t8_subelement_scheme_quad_c::t8_element_anchor (const t8_element_t *elem, + int coord[3]) const +{ + t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; + p4est_quadrant_t *q = &pquad_w_sub->p4q; + + /* this function is not implemented for subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + + coord[0] = q->x; + coord[1] = q->y; + coord[2] = 0; + T8_QUAD_SET_TDIM (q, 2); +} + +int +t8_subelement_scheme_quad_c::t8_element_root_len (const t8_element_t *elem) const +{ + return P4EST_ROOT_LEN; +} + +int +t8_subelement_scheme_quad_c::t8_element_refines_irregular () const +{ + /* In general, subelements do not refine regularly */ + return 1; +} + +void +t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t + *elem, + const double + *ref_coords, + const void + *user_data, + double *out_coords) + const +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} + +void +t8_subelement_scheme_quad_c::t8_element_vertex_reference_coords (const + t8_element_t + *t, + int vertex, + double + coords[]) + const +{ + int coords_int[2] = { }; + t8_element_vertex_coords (t, vertex, coords_int); + + /* We divide the integer coordinates by the root length of the quad + * to obtain the reference coordinates. */ + coords[0] = (double) coords_int[0] / (double) P4EST_ROOT_LEN; + coords[1] = (double) coords_int[1] / (double) P4EST_ROOT_LEN; +} + +void +t8_subelement_scheme_quad_c::t8_element_vertex_coords (const t8_element_t + *elem, int vertex, + int coords[]) const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + const p4est_quadrant_t *q1 = &pquad_w_sub->p4q; + + T8_ASSERT (t8_element_is_valid (elem)); + + if (!t8_element_is_subelement (elem)) { + int len; + + T8_ASSERT (0 <= vertex && vertex < 4); + /* Get the length of the quadrant */ + len = P4EST_QUADRANT_LEN (q1->level); + + /* Compute the x and y coordinates of the vertex depending on the + * vertex number */ + coords[0] = q1->x + (vertex & 1 ? 1 : 0) * len; + coords[1] = q1->y + (vertex & 2 ? 1 : 0) * len; + } + else { + t8_element_vertex_coords_of_subelement (elem, vertex, coords); + } +} + +void +t8_subelement_scheme_quad_c::t8_element_vertex_coords_of_subelement (const + t8_element_t + *elem, + int + vertex, + int + coords[]) + const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + const p4est_quadrant_t *q1 = &pquad_w_sub->p4q; + + int len; + + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_subelement (elem)); + T8_ASSERT (vertex >= 0 && vertex < T8_QUAD_SUBELEMENT_FACES); /* all subelements are triangles */ + + /* get the length of the current quadrant */ + len = P4EST_QUADRANT_LEN (q1->level); + + /* Compute the x and y coordinates of subelement vertices, depending on the transition type, id and vertex number + * (faces enumerated clockwise, starting at the center of the transition cell): + * + * f1 V1 + * x - - - - - x x + * | \ 2 / | / | + * | 1 \ / 3 | / 3 | + * f0 x - - + - - x f2 --> + - - x + * | 0 / | \ 4 | V0 V2 + * | / 6 | 5 \ | + * x - - x - - x + * f3 + * + * In this example, the below location array would contain the values [2, 1, 1] + * (second face, split, first subelement at this face) */ + + /* get location information of the given subelement */ + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + + /* the face number, the subelement is adjacent to */ + int face_number = location[0]; + /* = 1, if the adjacent face is split and = 0, if not */ + int split = location[1]; + /* = 0, if the subelement is the first (of two) subelements, at the adjacent face and = 1 if it is the second */ + int sub_face_id = location[2]; + + /* Check, whether the get_location function provides meaningful location data */ + T8_ASSERT (face_number == 0 || face_number == 1 || face_number == 2 + || face_number == 3); + T8_ASSERT ((split == 0 && sub_face_id == 0) + || (split == 1 && (sub_face_id == 0 || sub_face_id == 1))); + + coords[0] = q1->x; + coords[1] = q1->y; + + /* using the location data to determine vertex coordinates */ + if (vertex == 0) { /* vertex 0 (the first vertex allways equals the center of the element) */ + coords[0] += len / 2; + coords[1] += len / 2; + } /* end of vertex == 0 */ + else if (vertex == 1) { /* vertex 1 */ + if (face_number == 0) { + if (split && sub_face_id) { + coords[1] += len / 2; + } + } + else if (face_number == 1) { + coords[1] += len; + if (split && sub_face_id) { + coords[0] += len / 2; + } + } + else if (face_number == 2) { + coords[0] += len; + coords[1] += len; + if (split && sub_face_id) { + coords[1] -= len / 2; + } + } + else { + coords[0] += len; + if (split && sub_face_id) { + coords[0] -= len / 2; + } + } + } /* end of vertex == 1 */ + else { /* vertex 2 */ + if (face_number == 0) { + coords[1] += len; + if (split && !sub_face_id) { + coords[1] -= len / 2; + } + } + else if (face_number == 1) { + coords[0] += len; + coords[1] += len; + if (split && !sub_face_id) { + coords[0] -= len / 2; + } + } + else if (face_number == 2) { + coords[0] += len; + if (split && !sub_face_id) { + coords[1] += len / 2; + } + } + else { + if (split && !sub_face_id) { + coords[0] += len / 2; + } + } + } /* end of vertex == 2 */ +} + +void +t8_subelement_scheme_quad_c::t8_element_to_transition_cell (const t8_element_t + *elem, int type, + t8_element_t *c[]) +{ + const t8_quad_with_subelements *pquad_w_sub_elem = + (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements **pquad_w_sub_subelement = + (t8_quad_with_subelements **) c; + + const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; + + /* this function should not be callable by subelements */ + T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (type >= 0 && type <= T8_SUB_QUAD_MAX_TRANSITION_TYPE); + + int num_subelements = + t8_element_get_number_of_subelements (type); + +#ifdef T8_ENABLE_DEBUG + { + int j; + for (j = 0; j < num_subelements; j++) { + T8_ASSERT (t8_element_is_valid (c[j])); + } + } +#endif + + /* get the length of a children-quadrant */ + const int8_t level = (int8_t) (q->level); + + T8_ASSERT (p4est_quadrant_is_extended (q)); + T8_ASSERT (q->level < P4EST_QMAXLEVEL); + + /* Setting the parameter values for different subelements. + * The different subelement types (up to rotation) are: + * + * x - - - - - - x x - - - - - x x - - - - - x x - - - - - x x - - x - - x x - - x - - x + * | | | \ 2 / | | \ / | | \ / | | \ | / | | \ | / | + * | | | 1 \ / | | \ / | | \ / | | \ | / | | \ | / | + * | | --> x - - X 3 | or x - - x | or x - - x - - x or x - - x - - x or x - - x - - x + * | | | 0 / \ | | / | \ | | / \ | | / \ | | / | \ | + * | elem | | / 4 \ | | / | \ | | / \ | | / \ | | / | \ | + * + - - - - - - x x - - - - - x x - - x - - x x - - - - - x x - - - - - x x - - x - - x + * + * Sub_ids are counted clockwise, starting with the (lower) left subelement with id 0. + * Note, that we do not change the p4est quadrant. */ + + int sub_id_counter = 0; + for (sub_id_counter = 0; sub_id_counter < num_subelements; sub_id_counter++) { + pquad_w_sub_subelement[sub_id_counter]->p4q.x = q->x; + pquad_w_sub_subelement[sub_id_counter]->p4q.y = q->y; + pquad_w_sub_subelement[sub_id_counter]->p4q.level = level; + + pquad_w_sub_subelement[sub_id_counter]->transition_type = type; + pquad_w_sub_subelement[sub_id_counter]->subelement_id = sub_id_counter; + + T8_ASSERT (t8_element_is_valid (c[sub_id_counter])); + t8_element_copy_surround (q, + &pquad_w_sub_subelement[sub_id_counter]->p4q); + } +} + +int +t8_subelement_scheme_quad_c::t8_element_get_number_of_subelements (int + transition_type) + const +{ + /* we could return 0 for transition type 0 but we will assert this case for safety reasons */ + T8_ASSERT (transition_type != 0); + + /* consider transition_type 13 = 1101 in base two -> there are 4 + (1+1+0+1) = 7 subelements */ + int num_hanging_faces = 0; + int ichild; + for (ichild = 0; ichild < P4EST_FACES; ichild++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ + num_hanging_faces += (transition_type & (1 << ichild)) >> ichild; + } + + /* The number of subelements equals the number of neighbours: */ + return P4EST_FACES + num_hanging_faces; +} + +void +t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const + t8_element_t + *elem, + int + location + []) const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + + /* this function only works for subelements */ + T8_ASSERT (t8_element_is_subelement (elem)); + + T8_ASSERT (t8_element_is_valid (elem)); + + /* Consider the following transition cell of type 13: + * + * f0 1 + * x - - x - - x x - - x - - x + * | | | \ 2 | 3 / | faces: f3 f2 f1 f0 + * | | | 1 \ | / 4 | binary code: 1 1 0 1 (=13) + * f3 x x f2 --> 1 x - - x - - x 1 --> rearrange binaries s.t. the faces are enumerated clockwise: 1 1 1 0 + * | | | 0 / \ 5 | number subelements at face: 2 2 2 1 + * | elem | | / 6 \ | consider sub_id 3: x -> second subelement on the upper face + * + - - - - - x x - - - - - x + * f1 0 + * + * We will use the binary representation to determine the location of the given subelement. + * + * We need to know: + * i) the face number of the first vertex (values: {0,1,2,3}). + * ii) whether this face is split in half (values: {0,1}). + * iii) if the subelement is the first or second subelement at the face (values: {0,1}). + * + * These informations are then saved in the location array which will be used by the element_vertex function, + * to automatically determine the vertex coordinates of the given subelement. + * + * The location array for the above example would be {1,1,1} (upper face, split = true, second subelement at the upper face). */ + + /* 1) convert the transition type from a decimal to a binary representation */ + int type = pquad_w_sub->transition_type; + int binary_array[P4EST_FACES] = { }; + + int iface; + + for (iface = 0; iface < P4EST_FACES; iface++) { /* need an array with 4 elements to store all subelement types of the quad scheme from 1 to 15 ({0,0,0,1} to {1,1,1,1}) */ + binary_array[(P4EST_FACES - 1) - iface] = (type & (1 << iface)) >> iface; + } /* we now got a binary represenation of the transition type, bitwise stored in an array */ + + /* 2) rearrange the binary representation to be in clockwise order */ + int binary_array_temp[P4EST_FACES] = { }; + + for (iface = 0; iface < P4EST_FACES; iface++) { /* copying the binary array */ + binary_array_temp[iface] = binary_array[iface]; + } + + for (iface = 0; iface < P4EST_FACES; iface++) { /* bringing the entries of binary array into clockwise order */ + binary_array[iface] = + binary_array_temp[subelement_location_to_parent_face[iface]]; + } + + /* 3) use the rearranged binary representation, and the sub_id to determine the location of the subelement and store these information in an array */ + /* 3.1) location[0] -> the face_number, the subelement is adjacent to */ + /* 3.2) location[1] -> if the face is split or not */ + /* 3.3) location[2] -> if the subelement is the first or second subelement of the face (always the first, if the face is not split) */ + T8_ASSERT (pquad_w_sub->subelement_id < + t8_element_get_number_of_subelements + (pquad_w_sub->transition_type)); + + int sub_id = pquad_w_sub->subelement_id; + int sub_face_id; + int face_number = -1; + int split; + + int cum_neigh_array[P4EST_FACES] = { }; + + /* construct a cumulative array of the number of neighbors from face 0 to face 3 */ + cum_neigh_array[0] = binary_array[0] + 1; + cum_neigh_array[1] = cum_neigh_array[0] + binary_array[1] + 1; + cum_neigh_array[2] = cum_neigh_array[1] + binary_array[2] + 1; + cum_neigh_array[3] = cum_neigh_array[2] + binary_array[3] + 1; + + /* 3.1) we can use the cumulative array to determine the face number of the given subelement */ + if (sub_id < cum_neigh_array[0]) { + face_number = 0; + } + else { + for (iface = 0; iface < P4EST_FACES - 1; ++iface) { + if (sub_id >= cum_neigh_array[iface] + && sub_id < cum_neigh_array[iface + 1]) { + face_number = iface + 1; + break; + } + } + } + + /* make sure that a face_number has been found */ + T8_ASSERT (face_number >= 0); + + /* 3.2) determine, whether the face is split or not */ + if (binary_array[face_number] == 0) { + split = 0; /* the face is not split */ + } + else { + split = 1; /* the face is split */ + } + + /* 3.3) determine, whether the subelement is the first or the second subelement at the face */ + if (sub_id + 1 == cum_neigh_array[face_number] && split == 1) { + sub_face_id = 1; /* second subelement */ + } + else { + sub_face_id = 0; /* first subelement */ + } + + location[0] = face_number; + location[1] = split; + location[2] = sub_face_id; +} + +void +t8_subelement_scheme_quad_c::t8_element_reset_subelement_values (t8_element * + elem) const +{ + t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; + + pquad_w_sub->transition_type = 0; + pquad_w_sub->subelement_id = 0; +} + +void +t8_subelement_scheme_quad_c::t8_element_copy_subelement_values (const + t8_element * + source, + t8_element * + dest) const +{ + const t8_quad_with_subelements *pquad_w_sub_source = + (const t8_quad_with_subelements *) source; + t8_quad_with_subelements *pquad_w_sub_dest = + (t8_quad_with_subelements *) dest; + + pquad_w_sub_dest->transition_type = pquad_w_sub_source->transition_type; + pquad_w_sub_dest->transition_type = pquad_w_sub_source->transition_type; + pquad_w_sub_dest->subelement_id = pquad_w_sub_source->subelement_id; +} + +int +t8_subelement_scheme_quad_c::t8_element_is_subelement (const + t8_element * + elem) const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + + T8_ASSERT (pquad_w_sub->transition_type >= 0); + + /* transition_type == 0 => elem is no subelement. + * transition_type != 0 => elem is subelement + */ + return (pquad_w_sub->transition_type == 0 ? false : true); +} + +int +t8_subelement_scheme_quad_c::t8_element_get_transition_type (const + t8_element * + elem) +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + + return pquad_w_sub->transition_type; +} + +int +t8_subelement_scheme_quad_c::t8_element_get_subelement_id (const + t8_element * elem) +{ + T8_ASSERT (t8_element_is_valid (elem)); + + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + + return pquad_w_sub->subelement_id; +} + +t8_element_shape_t +t8_subelement_scheme_quad_c::t8_element_shape (const t8_element_t *elem) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + return (t8_element_is_subelement (elem) ? T8_ECLASS_TRIANGLE : + T8_ECLASS_QUAD); +} + +int +t8_subelement_scheme_quad_c::t8_element_num_corners (const t8_element_t *elem) const +{ + T8_ASSERT (t8_element_is_valid (elem)); + + return (t8_element_is_subelement (elem) ? T8_QUAD_SUBELEMENT_FACES : + P4EST_FACES); +} + +int +t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell + (const t8_element_t *elem, const t8_element_t *pseudo_neigh, int elem_face) +{ + /* In this function, we assume pseudo_neigh to be a random subelement of a transition cell that includes + * the real neighbor of elem at face elem_face. This function will output the subelement_id of the real neighbor of elem. */ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (pseudo_neigh)); + + /* we expect neigh to be a element in a transition cell, thus to be a subelement */ + T8_ASSERT (t8_element_is_subelement (pseudo_neigh)); + + const t8_quad_with_subelements * + pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements * + pquad_w_sub_pseudo_neigh = + (const t8_quad_with_subelements *) pseudo_neigh; + + /* In the following, all possible neighbor configurations are defined, such that subelement neighbors can be + * identified in LFN_transitioned. */ + if (pquad_w_sub_elem->transition_type != 0 + && (elem_face == 0 || elem_face == 2)) { + /* In this case, we have the following situation: + * + * x - - - - - - - x + * | \ elem / | + * | \ / | + * |N_f0 \ / N_f2| + * x - - - + - - - x + * | / \ | + * | /pseudo \ | + * | / neigh \ | + * x - - - - - - - x + * + * Elem and face 0 or face 2 is given and a random sibling subelement neigh is given, too. + * We are searching for the subelement id of the real neighbor N_f0 or N_f2, depending on the face number. */ + int + shift; + if (elem_face == 0) { + shift = -1; + } + if (elem_face == 2) { + shift = 1; + } + int + num_subelements = + t8_element_get_number_of_subelements + (pquad_w_sub_elem->transition_type); + return ((pquad_w_sub_elem->subelement_id + shift) + num_subelements) % num_subelements; /* the neighbor is directly before or after elem modulo the number of subelements in the transition cell */ + } + /* Below are the cases in which the neighbor can not be identified as simple as above. + * The idea is to fill a location array with the desired properties of the real neighbor. + * Togehter with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ + + if (pquad_w_sub_elem->transition_type != 0 && elem_face == 1) { + /* In this case, we have the following situation: + * + * x - - - - - - - x - - - - - - - x + * | \ / | \ / | + * | \ / | \ / | + * | \ / | \ / | + * x - - - x neigh | elem x | + * | / \ | / | \ | + * | /pseudo \ | / | \ | + * | / neigh \ | / | \ | + * x - - - - - - - x - - - x - - - x + * + * A subelement elem is given as well as a random subelement pseudo_neigh from a neighboring transition cell. + * We are searching for the subelement id of the real neighbor neigh. + * Note that both transition cells can have different levels. */ + + /* get the location of elem */ + int + location_elem[3] = { }; /* {face, is_split, number of subelement at face} */ + t8_element_get_location_of_subelement (elem, location_elem); + + /* Initialize the location array of the real neighbor. */ + int + location_neigh[3] = { -1, -1, -1 }; + + /* the pseudo_neigh tranaition cell has a lower level than the elem transition cell */ + if (pquad_w_sub_pseudo_neigh->p4q.level < pquad_w_sub_elem->p4q.level) { + if (location_elem[0] == 0) { /* left face of transition cell */ + if (pquad_w_sub_pseudo_neigh->p4q.y == pquad_w_sub_elem->p4q.y) { + location_neigh[0] = 2; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* second subelement at face */ + } + if (pquad_w_sub_pseudo_neigh->p4q.y != pquad_w_sub_elem->p4q.y) { + location_neigh[0] = 2; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ + } + } + if (location_elem[0] == 1) { /* upper face of transition cell */ + if (pquad_w_sub_pseudo_neigh->p4q.x == pquad_w_sub_elem->p4q.x) { + location_neigh[0] = 3; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* first or second subelement at face */ + } + if (pquad_w_sub_pseudo_neigh->p4q.x != pquad_w_sub_elem->p4q.x) { + location_neigh[0] = 3; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ + } + } + if (location_elem[0] == 2) { /* right face of transition cell */ + if (pquad_w_sub_pseudo_neigh->p4q.y == pquad_w_sub_elem->p4q.y) { + location_neigh[0] = 0; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ + } + if (pquad_w_sub_pseudo_neigh->p4q.y != pquad_w_sub_elem->p4q.y) { + location_neigh[0] = 0; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* first or second subelement at face */ + } + } + if (location_elem[0] == 3) { /* lower face of transition cell */ + if (pquad_w_sub_pseudo_neigh->p4q.x == pquad_w_sub_elem->p4q.x) { + location_neigh[0] = 1; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ + } + if (pquad_w_sub_pseudo_neigh->p4q.x != pquad_w_sub_elem->p4q.x) { + location_neigh[0] = 1; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* second subelement at face */ + } + } + } + /* the pseudo_neigh tranaition cell has not a lower level than the elem transition cell */ + if (pquad_w_sub_pseudo_neigh->p4q.level >= pquad_w_sub_elem->p4q.level) { + if (location_elem[0] == 0) { /* left face of transition cell */ + location_neigh[0] = 2; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ + } + if (location_elem[0] == 1) { /* upper face of transition cell */ + location_neigh[0] = 3; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ + } + if (location_elem[0] == 2) { /* right face of transition cell */ + location_neigh[0] = 0; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ + } + if (location_elem[0] == 3) { /* lower face of transition cell */ + location_neigh[0] = 1; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ + } + } + + /* check, that a neighbor is found and the location array is adjusted */ + T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 + && location_neigh[2] >= 0); + + /* Depending on the location of elem, we have filled location_neigh with the data of the real neighbor. + * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ + return + t8_element_get_id_from_location (t8_element_get_transition_type + (pseudo_neigh), location_neigh); + } + if (!t8_element_is_subelement (elem)) { + /* In this case, we have the following situation: + * + * x - - - - - - - x - - - - - - - x + * | \ / | | + * | \ / | | + * | \ / | | + * x - - - x neigh | elem | + * | / \ | | + * | /pseudo \ | | + * | / neigh \ | | + * x - - - - - - - x - - - - - - - x + * + * Subelement elem is given as well as a random subelement neigh from a neighboring transition cell. + * We are searching for the subelement id of the real neighbor neigh. + * Note that the transition cell of pseudo_neigh and elem can have different levels. */ + + /* Initialize the location array of the real neighbor. */ + int + location_neigh[3] = { -1, -1, -1 }; + + /* the pseudo_neigh tranaition cell has a lower level than elem */ + if (pquad_w_sub_pseudo_neigh->p4q.level < pquad_w_sub_elem->p4q.level) { + if (elem_face == 0) { /* left face */ + if (pquad_w_sub_pseudo_neigh->p4q.y == pquad_w_sub_elem->p4q.y) { + location_neigh[0] = 2; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* second subelement at face */ + } + if (pquad_w_sub_pseudo_neigh->p4q.y != pquad_w_sub_elem->p4q.y) { + location_neigh[0] = 2; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ + } + } + if (elem_face == 1) { /* right face */ + if (pquad_w_sub_pseudo_neigh->p4q.y == pquad_w_sub_elem->p4q.y) { + location_neigh[0] = 0; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ + } + if (pquad_w_sub_pseudo_neigh->p4q.y != pquad_w_sub_elem->p4q.y) { + location_neigh[0] = 0; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* first or second subelement at face */ + } + } + if (elem_face == 2) { /* lower face */ + if (pquad_w_sub_pseudo_neigh->p4q.x == pquad_w_sub_elem->p4q.x) { + location_neigh[0] = 1; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ + } + if (pquad_w_sub_pseudo_neigh->p4q.x != pquad_w_sub_elem->p4q.x) { + location_neigh[0] = 1; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* second subelement at face */ + } + } + if (elem_face == 3) { /* upper face */ + if (pquad_w_sub_pseudo_neigh->p4q.x == pquad_w_sub_elem->p4q.x) { + location_neigh[0] = 3; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* first or second subelement at face */ + } + if (pquad_w_sub_pseudo_neigh->p4q.x != pquad_w_sub_elem->p4q.x) { + location_neigh[0] = 3; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ + } + } + } + /* the pseudo_neigh tranaition cell has the same level as elem + * Note that the level of the trnasition cell can not be higher as the level of elem in this case, + * since elem would then be a subelement in a transtion cell. */ + if (pquad_w_sub_pseudo_neigh->p4q.level == pquad_w_sub_elem->p4q.level) { + if (elem_face == 0) { /* left face */ + location_neigh[0] = 2; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ + } + if (elem_face == 1) { /* right face */ + location_neigh[0] = 0; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ + } + if (elem_face == 2) { /* lower face */ + location_neigh[0] = 1; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ + } + if (elem_face == 3) { /* upper face */ + location_neigh[0] = 3; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ + } + } + + /* check, that a neighbor is found and the location array is adjusted */ + T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 + && location_neigh[2] >= 0); + + /* Depending on the location of elem, we have filled location_neigh with the data of the real neighbor. + * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ + return + t8_element_get_id_from_location (t8_element_get_transition_type + (pseudo_neigh), location_neigh); + } + return -1; /* return negative if no neighbor element could be found */ +} + +int +t8_subelement_scheme_quad_c::t8_element_get_id_from_location (int type, + int location[]) +{ + T8_ASSERT (type >= 0 && type <= T8_SUB_QUAD_MAX_TRANSITION_TYPE); + + int sub_id, subelements_count = 0; + double type_temp = double (type); // would work for ints but we use libc pow(double, double) + int binary_type[4] = { }; + int binary_type_clockwise[4] = { }; + + /* get the type as a binary array */ + int iface; + for (iface = 0; iface < P4EST_FACES; iface++) { + if (type_temp >= pow (2.0, 4 - (iface + 1))) { + binary_type[iface] = 1; + type_temp -= pow (2.0, 4 - (iface + 1)); + } + else { + binary_type[iface] = 0; + } + } + + for (iface = 0; iface < P4EST_FACES; iface++) { /* rearrange the binary type to be in clockwise order of the faces, starting with the left face */ + binary_type_clockwise[iface] = + binary_type[subelement_location_to_parent_face[iface]]; + } + + /* count the number of elements up to the given location */ + int element_count; + for (element_count = 0; element_count <= location[0]; element_count++) { + if (element_count == location[0]) { + if (location[1] == 0) { + subelements_count += 1; + } + else { + if (location[2] == 0) { + subelements_count += 1; + } + else { + subelements_count += 2; + } + } + } + else { + subelements_count += binary_type_clockwise[element_count] + 1; + } + } + + /* get the sub_id */ + sub_id = subelements_count - 1; + + return sub_id; +} + +int +t8_subelement_scheme_quad_c::t8_element_get_face_number_of_hypotenuse (const + t8_element_t + *elem) +{ + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_subelement (elem)); + + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + + int split = location[1]; + int second = location[2]; + + if (!split) { /* if the face is not split, then the hypotenuse is always face number one */ + return 1; + } + else { + if (!second) { /* otherwise, the subelment is mirrored, depending on the value of 'second' */ + return 0; + } + else { + return 2; + } + } +} + +void +t8_subelement_scheme_quad_c::t8_element_new (int length, t8_element_t **elem) const +{ + /* allocate memory */ + t8_default_scheme_common_c::t8_element_new (length, elem); + + int elem_count; + for (elem_count = 0; elem_count < length; elem_count++) { + t8_quad_with_subelements *pquad_w_sub = + (t8_quad_with_subelements *) elem[elem_count]; + t8_element_init (1, elem[elem_count], 0); + /* set dimension of quad to 2 */ + T8_QUAD_SET_TDIM ((p4est_quadrant_t *) & pquad_w_sub->p4q, 2); + } +} + +void +t8_subelement_scheme_quad_c::t8_element_init (int length, t8_element_t *elem, + int new_called) const +{ + t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; + + int elem_count; + + for (elem_count = 0; elem_count < length; elem_count++) { + /* initalize subelement parameters */ + pquad_w_sub[elem_count].transition_type = 0; + pquad_w_sub[elem_count].subelement_id = 0; + +#ifdef T8_ENABLE_DEBUG + /* In debugging mode we iterate over all length many elements and + * set their quad to the level 0 quad with ID 0. */ + if (!new_called) { + p4est_quadrant_t *quad = &pquad_w_sub[elem_count].p4q; + p4est_quadrant_set_morton (quad, 0, 0); + T8_QUAD_SET_TDIM (quad, 2); + T8_ASSERT (p4est_quadrant_is_extended (quad)); + } +#endif + } +} + +int +t8_subelement_scheme_quad_c::t8_element_scheme_supports_transitioning (void) +{ + return T8_QUAD_TRANSITION_IS_IMPLEMENTED; +} + +int +t8_subelement_scheme_quad_c::t8_element_transition_scheme_is_conformal (void) +{ + return T8_QUAD_TRANSITION_SCHEME_IS_CONFORMAL; +} + +#ifdef T8_ENABLE_DEBUG +void +t8_subelement_scheme_quad_c::t8_element_debug_print (const t8_element_t *elem) const +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + + t8_productionf ("\n|------------ t8_element_debug_print: ------------|" + "\n| Transition Type: %i" + "\n| Subelement ID: %i" + "\n| Anchor (Morton): (%i,%i)" + "\n| Anchor (ref coords): (%lf,%lf)" + "\n| Level: %i" + "\n|-------------------------------------------------|\n", + pquad_w_sub->transition_type, pquad_w_sub->subelement_id, + pquad_w_sub->p4q.x, pquad_w_sub->p4q.y, + (double) pquad_w_sub->p4q.x / (double) P4EST_ROOT_LEN, + (double) pquad_w_sub->p4q.y / (double) P4EST_ROOT_LEN, + pquad_w_sub->p4q.level); + + /* if the element is not valid, abort, but after printing */ + T8_ASSERT (t8_element_is_valid (elem)); +} + +/* *INDENT-OFF* */ +/* indent bug, indent adds a second "const" modifier */ +int +t8_subelement_scheme_quad_c::t8_element_is_valid (const t8_element_t * elem) const +/* *INDENT-ON* */ + +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + const p4est_quadrant_t *q = &pquad_w_sub->p4q; + + /* the 4pest quadrant AND the subelement values must be valid such that the whole element is valid */ + return (p4est_quadrant_is_extended (q) + && t8_element_subelement_values_are_valid (elem)); +} + +/* *INDENT-OFF* */ +/* indent bug, indent adds a second "const" modifier */ +int +t8_subelement_scheme_quad_c::t8_element_subelement_values_are_valid (const + t8_element_t * + elem) const +/* *INDENT-ON* */ + +{ + const t8_quad_with_subelements *pquad_w_sub = + (const t8_quad_with_subelements *) elem; + + return ((pquad_w_sub->transition_type >= 0 && + pquad_w_sub->transition_type <= T8_SUB_QUAD_MAX_TRANSITION_TYPE) + || pquad_w_sub->transition_type == 0) && + ((pquad_w_sub->subelement_id >= 0 && + pquad_w_sub->subelement_id <= T8_SUB_QUAD_MAX_SUBELEMENT_ID) + || pquad_w_sub->subelement_id == 0); +} +#endif + +/* Constructor */ +t8_subelement_scheme_quad_c::t8_subelement_scheme_quad_c (void) +{ + eclass = T8_ECLASS_QUAD; + element_size = sizeof (t8_pquad_t); + ts_context = sc_mempool_new (element_size); +} + +t8_subelement_scheme_quad_c::~t8_subelement_scheme_quad_c () +{ + /* This destructor is empty since the destructor of the + * default_common scheme is called automatically and it + * suffices to destroy the quad_scheme. + * However we need to provide an implementation of the destructor + * and hence this empty function. */ +} + +T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx new file mode 100644 index 0000000000..f8c1b8b29a --- /dev/null +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -0,0 +1,545 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/** \file t8_transition_conformal_quad_cxx.hxx + * We use a p4est_quadrant_t object as storage for the T8 quadrant. + * Additionally, we store information for transition cells of triangular subelements: + * + * (i) transition_type - type of the transition cell of the current element + * (ii) subelement_id - subelement id of the current element + * + * In order to refine a quad element into a transition cell, it is important to know these additional parameter. + */ + +#ifndef T8_TRANSITION_CONFORMAL_QUAD_CXX_HXX +#define T8_TRANSITION_CONFORMAL_QUAD_CXX_HXX + +#include +#include + +#include + +#include "t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.hxx" +#include "t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx" + +/** The structure holding a quadrilateral element in the default scheme. + * We make this definition public for interoperability of element classes. + * We might want to put this into a private, scheme-specific header file. + */ + +/* Define the struct, that stores all information needed for the quad scheme and subelements. + * + * p4est quadrant recursive quad refinement, using a transition + * refinement cell with subelements + * x - - - - - x x - - x - - x x - - - - - x + * | | | | | | \ 2 / | + * | | | | | | 1 \ / | + * | | --> x - - x - - x or x - - x 3 | + * | | | | | | 0 / | \ | + * | | | | | | / 5 | 4 \ | + * x - - - - - x x - - x - - x x - - x - - x + * + * A p4est quadrant can be refined, using either the standard quad scheme, or a transition cell, consisting of different subelements. + * The quad refinement scheme is recursive, whereas a transition cell can only be used once, for example to remove hanging nodes, after the mesh has been adapted and balanced. + * There are different types of transition cells possible, which we will refer to as transition_type. + * Each transition cell consists of different subelements. The given example consists of 6 different subelements, whose ids range from 0 to 5. + * A dummy variable will store the information, whether a given element is a subelement or a standard quad element. */ + +typedef struct +{ + /* p4est quadrant */ + p4est_quadrant_t p4q; + /* stores transition cell information (default for non-subelements is 0 and for subelements it is != 0 - is therefore used as a is_subelement check) */ + int transition_type; + /* stores subelement information (default for non-subelements is 0) */ + int subelement_id; +} t8_quad_with_subelements; + +typedef t8_quad_with_subelements t8_pquad_t; + +/** define some subelement related constants */ +#define T8_SUB_QUAD_MAX_TRANSITION_TYPE 15 +#define T8_SUB_QUAD_MAX_SUBELEMENT_ID 7 +#define T8_QUAD_SUBELEMENT_FACES 3 + +#define T8_QUAD_TRANSITION_IS_IMPLEMENTED 1 +#define T8_QUAD_TRANSITION_SCHEME_IS_CONFORMAL 1 + +/** Return the toplevel dimension. */ +#define T8_QUAD_GET_TDIM(quad) ((int) (quad)->pad8) + +/** Return the direction of the third dimension. + * This is only valid to call if the toplevel dimension is three. + */ +#define T8_QUAD_GET_TNORMAL(quad) \ + ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ + ((int) (quad)->pad16) ) + +/** Return the coordinate in the third dimension. + * This is only valid to call if the toplevel dimension is three. + */ +#define T8_QUAD_GET_TCOORD(quad) \ + ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ + ((int) (quad)->p.user_long) ) + +/** Set the toplevel dimension of a quadrilateral. */ +#define T8_QUAD_SET_TDIM(quad,dim) \ + do { T8_ASSERT ((dim) == 2 || (dim) == 3); \ + (quad)->pad8 = (int8_t) (dim); } while (0) + +/** Set the direction of the third demension. */ +#define T8_QUAD_SET_TNORMAL(quad,normal) \ + do { T8_ASSERT ((normal) >= 0 && (normal) < 3); \ + (quad)->pad16 = (int16_t) (normal); } while (0) + +/** Set the coordinate in the third dimension. */ +#define T8_QUAD_SET_TCOORD(quad,coord) \ + do { (quad)->p.user_long = (long) (coord); } while (0) + +#if 0 +/** Provide an implementation for the quadrilateral element class with subelements. */ +t8_eclass_scheme_t *t8_subelement_scheme_new_quad (void); +#endif + +struct t8_subelement_scheme_quad_c:public t8_default_scheme_common_c +{ +public: + /** The virtual table for a particular implementation of an element class. */ + + /** Constructor. */ + t8_subelement_scheme_quad_c (); + + ~t8_subelement_scheme_quad_c (); + + /** Allocate memory for a given number of elements. + * In debugging mode, ensure that all elements are valid \ref t8_element_is_valid. + */ + virtual void t8_element_new (int length, t8_element_t **elem) const; + + /** Initialize an array of allocated elements. */ + virtual void t8_element_init (int length, t8_element_t *elem, + int called_new) const; + +/** Return the maximum level allowed for this element class. */ + virtual int t8_element_maxlevel (void) const; + +/** Return the type of each child in the ordering of the implementation. */ + virtual t8_eclass_t t8_element_child_eclass (int childid) const; + +/** Return the refinement level of an element. */ + virtual int t8_element_level (const t8_element_t *elem) const; + +/** Copy one element to another */ + virtual void t8_element_copy (const t8_element_t *source, + t8_element_t *dest) const; + +/** Compare to elements. returns negativ if elem1 < elem2, zero if elem1 equals elem2 + * and positiv if elem1 > elem2. + * If elem2 is a copy of elem1 then the elements are equal. + * If both elements are sibling subelements, return 0 if they are identical (same sub_id) and 1 otherwise. + */ + virtual int t8_element_compare (const t8_element_t *elem1, + const t8_element_t *elem2) const; + +/** Construct the parent of a given element. */ + virtual void t8_element_parent (const t8_element_t *elem, + t8_element_t *parent) const; + +/** Construct a same-size sibling of a given element. */ + virtual void t8_element_sibling (const t8_element_t *elem, + int sibid, + t8_element_t *sibling) const; + + /** Compute the number of face of a given element. */ + virtual int t8_element_num_faces (const t8_element_t *elem) const; + + /** Compute the maximum number of faces of a given element and all of its + * descendants. + * \param [in] elem The element. + * \return The maximum number of faces of \a elem and its descendants. + */ + virtual int t8_element_max_num_faces (const t8_element_t *elem) + const; + + /** Return the number of children of an element when it is refined. */ + virtual int t8_element_num_children (const t8_element_t *elem) + const; + + /** Return the number of siblings of an element (or the number of elements in the family of elem) */ + virtual int t8_element_num_siblings (const t8_element_t *elem) + const; + + /** Return the number of children of an element's face when the element is refined. */ + virtual int t8_element_num_face_children (const t8_element_t *elem, + const int face) const; + + /** Return the number of children of an element's face when the element is refined. */ + virtual int t8_element_neighbor_is_sibling (const t8_element_t + *elem, int face) const; + + /** Return the number of sibling neighbors at a given face. */ + virtual int t8_element_get_num_sibling_neighbors_at_face (const + t8_element_t + *elem, + int face) + const; + + /** Return zero refine value for schemes that do not have a transition implementation. */ + virtual int t8_element_get_transition_refine_identifier (void) + const; + + /** Return the corner number of an element's face corner. */ + virtual int t8_element_get_face_corner (const t8_element_t *element, + int face, int corner) const; + + /** Return the face numbers of the faces sharing an element's corner. */ + virtual int t8_element_get_corner_face (const t8_element_t *element, + int corner, int face) const; + + /** Construct the child element of a given number. */ + virtual void t8_element_child (const t8_element_t *elem, + int childid, + t8_element_t *child) const; + + /** Construct all sibling neighbors of elem at face - it is required that sibling neighbors of elem at face exist */ + virtual void + + + + t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t + *elem, + const int face, + const int + num_neighbors, + t8_element_t + *neighbor_at_face[], + int *neigh_face[]); + +/** Construct all children of a given element. */ + virtual void t8_element_children (const t8_element_t *elem, + int length, + t8_element_t *c[]) const; + +/** Return the child id of an element */ + virtual int t8_element_child_id (const t8_element_t *elem) const; + + /** Compute the ancestor id of an element */ + virtual int t8_element_ancestor_id (const t8_element_t *elem, + int level) const; + +/** Return nonzero if collection of elements is a family */ + virtual int t8_element_is_family (t8_element_t **fam) const; + +/** Construct the nearest common ancestor of two elements in the same tree. */ + virtual void t8_element_nca (const t8_element_t *elem1, + const t8_element_t *elem2, + t8_element_t *nca) const; + + /** Compute the element shape of the face of an element. */ + virtual t8_element_shape_t t8_element_face_shape (const t8_element_t *elem, + int face) const; + + /** Given an element and a face of the element, compute all children of + * the element that touch the face. */ + /** Given an element and a face of the element, compute all children of + * the element that touch the face. */ + virtual void t8_element_children_at_face (const t8_element_t *elem, + int face, + t8_element_t *children[], + int num_children, + int *child_indices) const; + + /** Given a face of an element and a child number of a child of that face, return the face number + * of the child of the element that matches the child face. */ + virtual int t8_element_face_child_face (const t8_element_t *elem, + int face, + int face_child) const; + + /** Given a face of an element return the face number + * of the parent of the element that matches the element's face. Or return -1 if + * no face of the parent matches the face. */ + virtual int t8_element_face_parent_face (const t8_element_t *elem, + int face) const; + + /** Transform the coordinates of a quadrilateral considered as boundary element + * in a tree-tree connection. */ + virtual void t8_element_transform_face (const t8_element_t *elem1, + t8_element_t *elem2, + int orientation, int sign, + int is_smaller_face) const; + + /** Given a boundary face inside a root tree's face construct + * the element inside the root tree that has the given face as a + * face. */ + virtual int t8_element_extrude_face (const t8_element_t *face, + const t8_eclass_scheme_c + *face_scheme, + t8_element_t *elem, + int root_face) const; + + /** Return the tree face id given a boundary face. */ + virtual int t8_element_tree_face (const t8_element_t *elem, + int face) const; + + /** Construct the first descendant of an element that touches a given face. */ + virtual void t8_element_first_descendant_face (const t8_element_t + *elem, int face, + t8_element_t + *first_desc, + int level) const; + + /** Construct the last descendant of an element that touches a given face. */ + virtual void t8_element_last_descendant_face (const t8_element_t + *elem, int face, + t8_element_t + *last_desc, + int level) const; + + /** Construct the boundary element at a specific face. */ + virtual void t8_element_boundary_face (const t8_element_t *elem, + int face, + t8_element_t *boundary, + const t8_eclass_scheme_c + *boundary_scheme) const; + +/** Construct all codimension-one boundary elements of a given element. */ + virtual void t8_element_boundary (const t8_element_t *elem, + int min_dim, int length, + t8_element_t **boundary) const; + + /** Compute whether a given element shares a given face with its root tree. + * \param [in] elem The input element. + * \param [in] face A face of \a elem. + * \return True if \a face is a subface of the element's root element. + */ + virtual int t8_element_is_root_boundary (const t8_element_t *elem, + int face) const; + + /** Construct the face neighbor of a given element if this face neighbor + * is inside the root tree. Return 0 otherwise. */ + virtual int t8_element_face_neighbor_inside (const t8_element_t + *elem, + t8_element_t *neigh, + int face, + int *neigh_face) const; + +/** Initialize an element according to a given linear id */ + virtual void t8_element_set_linear_id (t8_element_t *elem, + int level, + t8_linearidx_t id) const; + +/** Calculate the linear id of an element */ + virtual t8_linearidx_t t8_element_get_linear_id (const + t8_element_t *elem, + int level) const; + +/** Calculate the first descendant of a given element e. That is, the + * first element in a uniform refinement of e of the maximal possible level. + */ + virtual void t8_element_first_descendant (const t8_element_t *elem, + t8_element_t *desc, + int level) const; + +/** Calculate the last descendant of a given element e. That is, the + * last element in a uniform refinement of e of the maximal possible level. + */ + virtual void t8_element_last_descendant (const t8_element_t *elem, + t8_element_t *desc, + int level) const; + +/** Compute s as a successor of t*/ + virtual void t8_element_successor (const t8_element_t *t, + t8_element_t *s, int level) const; + +/** Get the integer coordinates of the anchor node of an element */ + virtual void t8_element_anchor (const t8_element_t *elem, + int anchor[3]) const; + +/** Get the integer root length of an element, that is the length of + * the level 0 ancestor. + */ + virtual int t8_element_root_len (const t8_element_t *elem) const; + +/** Compute the integer coordinates of a given element vertex. */ + virtual void t8_element_vertex_coords (const t8_element_t *t, + int vertex, + int coords[]) const; + +/** Convert a point in the reference space of an element to a point in the + * reference space of the tree. + * + * \param [in] elem The element. + * \param [in] coords_input The coordinates of the point in the reference space of the element. + * \param [in] user_data User data. + * \param [out] out_coords The coordinates of the point in the reference space of the tree. + */ + virtual void t8_element_reference_coords (const t8_element_t *elem, + const double *ref_coords, + const void *user_data, + double *out_coords) + const; + +/** Construct a transition cell of type type */ + virtual void t8_element_to_transition_cell (const t8_element_t *elem, + int type, + t8_element_t *c[]); + +/** Determine the number of sibling subelements, of a transition cell of a specific type */ + virtual int t8_element_get_number_of_subelements (int + transition_type) + const; + +/** Test wheter a given element is a subelement or not */ + virtual int t8_element_is_subelement (const t8_element * + elem) const; + +/** Get the subelement type of elem */ + virtual int t8_element_get_transition_type (const + t8_element * elem); + +/** Get the subelement id of elem */ + virtual int t8_element_get_subelement_id (const t8_element * elem); + +/** Get the subelement id of the neighbor subelement of elem at face elem_face + * that is a sibling of the subelement neigh. + */ + virtual int t8_element_find_neighbor_in_transition_cell (const + t8_element_t + *elem, + const + t8_element_t + *neigh, + int + elem_face); + +/** Get the face-number of the hypotenuse of the triangular subelement */ + virtual int t8_element_get_face_number_of_hypotenuse (const + t8_element_t + *elem); + +/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int t8_element_scheme_supports_transitioning (void); + +/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int t8_element_transition_scheme_is_conformal (void); + +/** Returns true, if there is one element in the tree, that does not refine into 2^dim children. + * Returns false otherwise. + * \return non-zero if there is one element in the tree that does not refine into 2^dim children. + */ + virtual int t8_element_refines_irregular (void) const; + +/** Get the shape of a given element. Subelements are triangles */ + virtual t8_element_shape_t t8_element_shape (const t8_element_t *elem) + const; + +/** Return the number of vertices of an element */ + virtual int t8_element_num_corners (const t8_element_t *elem) const; + +/** Compute the coordinates of a given element vertex inside a reference tree + * that is embedded into [0,1]^d (d = dimension). + * \param [in] t The element to be considered. + * \param [in] vertex The id of the vertex whose coordinates shall be computed. + * \param [out] coords An array of at least as many doubles as the element's dimension + * whose entries will be filled with the coordinates of \a vertex. + */ + virtual void t8_element_vertex_reference_coords (const t8_element_t + *t, int vertex, + double coords[]) + const; + +#ifdef T8_ENABLE_DEBUG +/** TODO: this should be the new element_print_element funciton */ + virtual void t8_element_debug_print (const t8_element_t *elem) const; + +/** Query whether an element is valid */ + virtual int t8_element_is_valid (const t8_element_t *t) const; +#endif + +protected: + /** This function determines the vertex coordinates of subelements. + * \param [in] elem A valid subelement + * \param [in] vertex the number of the vertex whose coordinates should be determined + * \param [out] coords An array whose entries will be filled with the coordinates of the + * subelement. + * Note that subelements can have another number of vertices compared to the used + * eclass scheme. For example, subelements that remove hanging nodes from the quad scheme + * are triangles with 3 instead of 4 verticies. + */ + void t8_element_vertex_coords_of_subelement (const + t8_element_t *t, + int vertex, + int coords[]) + const; + + /** This function will determine the location of a specific subelement in the parent element. + * Since different subelement types are possible, it is a priori not known where for example the + * subelement with id 3 is located. + * \param [in] elem A valid subelement + * \param [out] An array, whose entries are face_number, split and sub_face_id + * face_number: the face number (clockwise enumeration), the given subelement is adjacent to (value between 0 and 3) + * It can be translated to the quad enumeration via subelement_location_to_parent_dual_face[location[0]] + * split: whether there is a hanging node at the face, the subelement is adjacent to + * (value 0 if there is not hanging node and 1 if there is one) + * sub_face_id: if there is a hanging node at the face, it is important to know if the given + * subelement is the first or the second subelement at this face + * (value 0 if it is the first and 1 if it is the second) + * The information in the location can be used to automatically determine the verticies of any subelement. + * Since this function is only used to determine the vertices of subelements, it can be declared as a private/protected function. + */ + void t8_element_get_location_of_subelement (const + t8_element_t + *elem, + int location[]) + const; + + /** This help function returns the subelement if of an element whose location and transition type is known. */ + int t8_element_get_id_from_location (int type, + int location[]); + + /** This function copies the subelement values from source to dest. + * \param [in] source A valid element + * \param [in,out] dest A valid element, whose subelement values are equal to those of source + */ + void t8_element_copy_subelement_values (const + t8_element_t *source, + t8_element_t *dest) + const; + + /** This function resets the subelement values of an element to the default value -1. + * \param [in,out] elem A valid element, whose subelement values have been resetted. + */ + void t8_element_reset_subelement_values (t8_element_t *elem) + const; + +#ifdef T8_ENABLE_DEBUG + /** Query whether an elements subelement values are valid + * \param [in] source A element + * \return true, if the subelement values are valid + */ + int t8_element_subelement_values_are_valid (const + t8_element_t + *elem) const; +#endif +}; + +#endif /* !T8_TRANSITION_QUAD_CXX_HXX */ diff --git a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx new file mode 100644 index 0000000000..72973f9361 --- /dev/null +++ b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx @@ -0,0 +1,49 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/** \file t8_transition_cxx.hxx + * This file is the point of entry for our transition implementation. + * This scheme points to a consistent implementation of all element classes. + */ + +#ifndef T8_TRANSITION_CXX_HXX +#define T8_TRANSITION_CXX_HXX + +#include + +/* This is the unique identifier for the transition fucntion. */ + +enum T8_TRANSITION_REFINE_IDENTIFIER { + T8_TRANSITION_CONFORMAL_ZERO_REFINE_FUNCTION = 0, + T8_TRANSITION_CONFORMAL_QUAD_REFINE_FUNCTION, + T8_TRANSITION_CONFORMAL_HEX_REFINE_FUNCTION, +}; + +T8_EXTERN_C_BEGIN (); + +/** Return the subelement element implementations of t8code. */ +t8_scheme_cxx_t *t8_scheme_new_transition_quad_cxx (void); +t8_scheme_cxx_t *t8_scheme_new_transition_hex_cxx (void); + +T8_EXTERN_C_END (); + +#endif /* !T8_TRANSITION_CXX_HXX */ From 3d8fe6112e08a66af9c1f06d4ba0cadd2ae13420 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 17 Apr 2024 16:37:16 +0200 Subject: [PATCH 02/55] Added functions is_subelement and transition_refine_identifier --- src/t8_element_cxx.hxx | 15 +++++++++++++ src/t8_forest/t8_forest_types.h | 2 ++ .../t8_default_common_cxx.cxx | 22 +++++++++++++++++++ .../t8_default_common_cxx.hxx | 17 ++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/src/t8_element_cxx.hxx b/src/t8_element_cxx.hxx index 7085984311..716b49bc4f 100644 --- a/src/t8_element_cxx.hxx +++ b/src/t8_element_cxx.hxx @@ -739,6 +739,21 @@ struct t8_eclass_scheme * \param [in, out] position the position of the first byte that is not already packed * \param [in] comm MPI Communicator */ +/*-----------------------------------Functions for transition schemes------------------------------------------------*/ + /** Return zero refine value for schemes that do not have a transition implementation. + * \param [in] elem A valid element + * \return Integer, used as the refine value during transition adaptation. + */ + virtual int t8_element_get_transition_refine_identifier (void) const + = 0; + + /** Check whether a given element is a subelement + * \param [in] elem A valid element + * \return true if elem is a subelement + */ + virtual int t8_element_is_subelement (const t8_element * + elem) const = 0; + virtual void t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, void *send_buffer, int buffer_size, int *position, sc_MPI_Comm comm) const diff --git a/src/t8_forest/t8_forest_types.h b/src/t8_forest/t8_forest_types.h index 10f4c84b72..e868693477 100644 --- a/src/t8_forest/t8_forest_types.h +++ b/src/t8_forest/t8_forest_types.h @@ -97,6 +97,7 @@ typedef struct t8_forest See \ref t8_forest_set_balance. If 0, no balance. If 1 balance with repartitioning, if 2 balance without repartitioning, \see t8_forest_balance */ + int set_subelements; /**< Flag to decide whether subelements should be used in the forest */ int do_ghost; /**< If True, a ghost layer will be created when the forest is committed. */ t8_ghost_type_t ghost_type; /**< If a ghost layer will be created, the type of neighbors that count as ghost. */ int ghost_algorithm; /**< Controls the algorithm used for ghost. 1 = balanced only. 2 = also unbalanced @@ -134,6 +135,7 @@ typedef struct t8_forest t8_locidx_t local_num_elements; /**< Number of elements on this processor. */ t8_gloidx_t global_num_elements; /**< Number of elements on all processors. */ t8_profile_t *profile; /**< If not NULL, runtimes and statistics about forest_commit are stored here. */ + int is_transitioned; /* Flag parameter that states whether the forest is transitioned or not */ sc_statinfo_t stats[T8_PROFILE_NUM_STATS]; int stats_computed; } t8_forest_struct_t; diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx index 0826d81db0..45c1bd80f4 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx @@ -168,4 +168,26 @@ t8_default_scheme_common_c::t8_element_deinit (int length, t8_element_t *elem) c { } +/*----------------------------Functions for transition schemes--------------------------------------------*/ +int +t8_default_scheme_common_c::t8_element_get_transition_refine_identifier () const +{ + /* This function will be called by the transition_entry function. It defaults to zero such that + * the adapt routine will keep elem unchanged during the transition step. */ + return 0; +} + +int +t8_default_scheme_common_c::t8_element_is_subelement (const t8_element * elem) const +{ + /* We implement this function since it is a "check" function and + * should not abort the code even if no subelements are implemented in the given eclass. + * Schemes that support subelements must provide their own implementation of this function. */ + + /* No subelements are implemented and therefore we return false meaning "is no subelement". */ + t8_debugf + ("This is the default_common implementation of the t8_element_is_subelement check.\n"); + return 0; +} + T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx index e61efe5527..497b07df0b 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx @@ -127,6 +127,23 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { virtual void t8_element_anchor (const t8_element_t *elem, int anchor[3]) const = 0; +/*-----------------------------Functions for transition schemes---------------------------------*/ + + /** Return zero refine value for schemes that do not have a transition implementation. + * \param [in] elem A valid element + * \return Integer, used as the refine value during transition adaptation. + */ + virtual int t8_element_get_transition_refine_identifier (void) + const; + + /** Check whether a given element is a subelement + * \param [in] elem A valid element + * \return true if elem is a subelement + */ + + + virtual int t8_element_is_subelement (const t8_element * + elem) const; #if T8_ENABLE_DEBUG virtual void t8_element_debug_print (const t8_element_t *elem) const; From 5efb2fdbe2bd07e4c0097fd99db80ae548192411 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 23 Apr 2024 15:46:04 +0200 Subject: [PATCH 03/55] Adjusting t8_forest_adapt() for transitioning --- src/t8_element_cxx.hxx | 35 +++++++- src/t8_forest/t8_forest.c | 13 +++ src/t8_forest/t8_forest_adapt.cxx | 85 ++++++++++++++++++- src/t8_forest/t8_forest_general.h | 7 ++ src/t8_forest/t8_forest_types.h | 4 +- .../t8_default_common_cxx.cxx | 23 +++++ .../t8_default_common_cxx.hxx | 30 ++++++- 7 files changed, 186 insertions(+), 11 deletions(-) diff --git a/src/t8_element_cxx.hxx b/src/t8_element_cxx.hxx index 716b49bc4f..7fc815eebe 100644 --- a/src/t8_element_cxx.hxx +++ b/src/t8_element_cxx.hxx @@ -744,15 +744,44 @@ struct t8_eclass_scheme * \param [in] elem A valid element * \return Integer, used as the refine value during transition adaptation. */ - virtual int t8_element_get_transition_refine_identifier (void) const + virtual int + t8_element_get_transition_refine_identifier (void) const = 0; /** Check whether a given element is a subelement * \param [in] elem A valid element * \return true if elem is a subelement */ - virtual int t8_element_is_subelement (const t8_element * - elem) const = 0; + virtual int + t8_element_is_subelement (const t8_element *elem) const + = 0; + + /** Return the number of subelements in a transition cell of type transition_type + * \param [in] transition_type The subelement type as an integer + * \return the number of subelements, this transition cell consists of + */ + virtual int + t8_element_get_number_of_subelements (int transition_type) const + = 0; + + /** Return the subelement id of a given element. + * \param [in] elem A valid element + * \return the subelement id of elem (0 if elem is no subelement) + */ + virtual int + t8_element_get_subelement_id (const t8_element * elem) = 0; + + /** This function refines a parent element into subelements. + * Depending on the subelement type, the number of subelements + * to fill the parent element, can differ. + * \param [in] elem A valid element + * \param [in] type The subelement type + * \param [out] subelements An array of all subelements of the parent quad element elem + */ + virtual void + t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *subelements[]) + = 0; + /* --------------------------End functions of transition scheme---------------------*/ virtual void t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, void *send_buffer, int buffer_size, diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index 7a0a6c397c..9c377dbd13 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -318,6 +318,19 @@ t8_forest_comm_global_num_elements (t8_forest_t forest) forest->global_num_elements = global_num_el; } +void +t8_forest_comm_global_num_subelements (t8_forest_t forest) +{ + int mpiret; + t8_gloidx_t local_num_subel; + t8_gloidx_t global_num_subel; + + local_num_subel = (t8_gloidx_t) forest->local_num_subelements; + mpiret = sc_MPI_Allreduce (&local_num_subel, &global_num_subel, 1, + T8_MPI_GLOIDX, sc_MPI_SUM, forest->mpicomm); + SC_CHECK_MPI (mpiret); + forest->global_num_subelements = global_num_subel; +} /** Adapt callback function to refine every element in the forest. * It is merely used to build a new forest with pyramids. * diff --git a/src/t8_forest/t8_forest_adapt.cxx b/src/t8_forest/t8_forest_adapt.cxx index a0ef8a30ca..b3aef0d820 100644 --- a/src/t8_forest/t8_forest_adapt.cxx +++ b/src/t8_forest/t8_forest_adapt.cxx @@ -361,6 +361,36 @@ t8_forest_adapt_refine_recursive (t8_forest_t forest, t8_locidx_t ltreeid, t8_lo } /* End while loop */ } +/* There are several rules, the refine value needs to fulfill for transitioned forests, + * independent of the specific refine function that has been applied before. This function + * checks if these rules are fulfilled and may change the refine value. */ +void +t8_forest_adjust_refine_for_transitioned_forests (const t8_forest_t forest, + t8_eclass_scheme_c *tscheme, + const t8_element_t + *current_element, + const t8_locidx_t ltree_id, + int *prefine) +{ + /* refine values >1 are only allowed for eclass schemes that support transitioning */ + T8_ASSERT (! + (tscheme->t8_element_get_transition_refine_identifier () == 0 + && *prefine > 1)); + + /* Existing transition cells must be removed during adaptation. + * We establish the rule to coarsen a transition cell back to its parent in case of refine = 0. */ + if (tscheme->t8_element_is_subelement (current_element) && *prefine == 0) { + /* current_element is the first subelement in the transition cell (subelement_id = 0). We establish the rule to + * coarsen it back to its parent quad/ hex and skip all of its following sibling subelements. */ + T8_ASSERT (forest->set_from->is_transitioned == 1); + T8_ASSERT (*prefine >= -1 && *prefine <= 1); + T8_ASSERT (tscheme->t8_element_get_subelement_id (current_element) == 0); + *prefine = -1; + } + + return; +} + /* TODO: optimize this when we own forest_from */ void t8_forest_adapt (t8_forest_t forest) @@ -388,6 +418,8 @@ t8_forest_adapt (t8_forest_t forest) int num_elements_to_adapt_callback; int zz; int ci; + unsigned int num_subelements; /* This is only needed when transitioning is enabled. */ + t8_locidx_t subel_inserted; /* This is only needed when transitioning is enabled. */ int refine; int is_family; int element_removed = 0; @@ -420,6 +452,7 @@ t8_forest_adapt (t8_forest_t forest) refine_list = sc_list_new (NULL); } forest->local_num_elements = 0; + forest->local_num_subelements = 0; el_offset = 0; num_trees = t8_forest_get_num_local_trees (forest); /* Iterate over the trees and build the new element arrays for each one. */ @@ -442,6 +475,8 @@ t8_forest_adapt (t8_forest_t forest) el_considered = 0; /* Index into the newly inserted elements */ el_inserted = 0; + /* Index into the newly inserted subelements */ + subel_inserted = 0; /* el_coarsen is the index of the first element in the new element * array which could be coarsened recursively. */ el_coarsen = 0; @@ -519,13 +554,19 @@ t8_forest_adapt (t8_forest_t forest) * 0 if the element should remain as is * -1 if we passed a family and it should get coarsened * -2 if the element should be removed. + * >1 if the element should be refined into a transtion cell */ refine = forest->set_adapt_fn (forest, forest->set_from, ltree_id, el_considered, tscheme, is_family, num_elements_to_adapt_callback, elements_from); + /* make adjustments of the refine value in the context of transitioned forests */ + if (forest->set_from->is_transitioned == 1 || forest->set_subelements == 1) { + t8_forest_adjust_refine_for_transitioned_forests (forest, tscheme, + t8_element_array_index_locidx (telements_from, el_considered), + ltree_id, &refine);} T8_ASSERT (is_family || refine != -1); - if (refine > 0 && tscheme->t8_element_level (elements_from[0]) >= forest->maxlevel) { - /* Only refine an element if it does not exceed the maximum level */ + if (refine == 1 && tscheme->t8_element_level (elements_from[0]) >= forest->maxlevel) { + /* Only refine an element regularly if it does not exceed the maximum level */ refine = 0; } if (refine == 1) { @@ -560,6 +601,30 @@ t8_forest_adapt (t8_forest_t forest) } el_considered++; } + else if (refine > 1) { + /* refinement into transition cell */ + + /* determing the number of subelements of the given type for memory allocation */ + num_subelements = + tscheme->t8_element_get_number_of_subelements (refine - 1); + + /* We need to reallocate memory for the transition cell */ + elements = T8_REALLOC (elements, t8_element_t *, num_subelements); + + (void) t8_element_array_push_count (telements, num_subelements); + for (zz = 0; zz < num_subelements; zz++) { + elements[zz] = + t8_element_array_index_locidx (telements, el_inserted + zz); + } + tscheme->t8_element_to_transition_cell (elements_from[0], refine - 1, + elements); + el_inserted += num_subelements; + el_considered++; + + /* Each time we entry this case, a parent element is refined into subelements. + * We will count the global number of constructed subelements and give this number as additional output. */ + subel_inserted += num_subelements; + } else if (refine == -1) { /* The elements form a family and are to be coarsened. */ /* Make room for one more new element. */ @@ -624,6 +689,8 @@ t8_forest_adapt (t8_forest_t forest) el_offset += el_inserted; /* Add to the new number of local elements. */ forest->local_num_elements += el_inserted; + /* Add to the new number of local subelements */ + forest->local_num_subelements += subel_inserted; /* Possibly shrink the telements array to the correct size */ t8_element_array_resize (telements, el_inserted); @@ -639,6 +706,7 @@ t8_forest_adapt (t8_forest_t forest) /* We now adapted all local trees */ /* Compute the new global number of elements */ + /* Compute the new global number of elements and subelements */ t8_forest_comm_global_num_elements (forest); /* Updating other processes about local (in)complete trees. @@ -656,8 +724,17 @@ t8_forest_adapt (t8_forest_t forest) T8_ASSERT (forest_from->incomplete_trees == 1); forest->incomplete_trees = 1; } - - t8_global_productionf ("Done t8_forest_adapt with %lld total elements\n", (long long) forest->global_num_elements); + t8_forest_comm_global_num_subelements (forest); + /* If any subelement is constructed, give output this number as an additional information. */ + if (forest->global_num_subelements > 0) { + t8_global_productionf + ("Done t8_forest_adapt with %lld total elements, %li of which are subelements.\n", + (long long) forest->global_num_elements, forest->global_num_subelements); + } + else { + t8_global_productionf ("Done t8_forest_adapt with %lld total elements\n", (long long) forest->global_num_elements); + } + /* if profiling is enabled, measure runtime */ if (forest->profile != NULL) { diff --git a/src/t8_forest/t8_forest_general.h b/src/t8_forest/t8_forest_general.h index 9672f3db3f..7521aa1704 100644 --- a/src/t8_forest/t8_forest_general.h +++ b/src/t8_forest/t8_forest_general.h @@ -379,6 +379,13 @@ t8_forest_set_load (t8_forest_t forest, const char *filename); void t8_forest_comm_global_num_elements (t8_forest_t forest); +/** Compute the global number of subelements in a forest as the sum + * of the local subelement counts. + * \param [in] forest The forest. + */ +void +t8_forest_comm_global_num_subelements (t8_forest_t forest); + /** After allocating and adding properties to a forest, commit the changes. * This call sets up the internal state of the forest. * \param [in,out] forest Must be created with \ref t8_forest_init and diff --git a/src/t8_forest/t8_forest_types.h b/src/t8_forest/t8_forest_types.h index e868693477..ddefa77777 100644 --- a/src/t8_forest/t8_forest_types.h +++ b/src/t8_forest/t8_forest_types.h @@ -134,8 +134,10 @@ typedef struct t8_forest t8_locidx_t local_num_elements; /**< Number of elements on this processor. */ t8_gloidx_t global_num_elements; /**< Number of elements on all processors. */ + t8_locidx_t local_num_subelements; /**< Number of subelements on this processor. */ + t8_gloidx_t global_num_subelements; /**< Number of subelements on all processors. */ t8_profile_t *profile; /**< If not NULL, runtimes and statistics about forest_commit are stored here. */ - int is_transitioned; /* Flag parameter that states whether the forest is transitioned or not */ + int is_transitioned; /* Flag parameter that states whether the forest is transitioned or not */ sc_statinfo_t stats[T8_PROFILE_NUM_STATS]; int stats_computed; } t8_forest_struct_t; diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx index 45c1bd80f4..78287a53c1 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx @@ -190,4 +190,27 @@ t8_default_scheme_common_c::t8_element_is_subelement (const t8_element * elem) c return 0; } +int +t8_default_scheme_common_c::t8_element_get_subelement_id (const + t8_element * elem) +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} + + +int +t8_default_scheme_common_c::t8_element_get_number_of_subelements (int transition_type) const +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} + +void +t8_default_scheme_common_c::t8_element_to_transition_cell (const t8_element_t + *elem, int type, + t8_element_t *c[]) +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} + + T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx index 4c7b0637c7..196c3e9638 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx @@ -121,15 +121,39 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { */ virtual int t8_element_get_transition_refine_identifier (void) const; - + /** Check whether a given element is a subelement * \param [in] elem A valid element * \return true if elem is a subelement */ + virtual int + t8_element_is_subelement (const t8_element *elem) const; + + /** Return the number of subelements in a transition cell of type transition_type + * \param [in] transition_type The subelement type as an integer + * \return the number of subelements, this transition cell consists of + */ + virtual int + t8_element_get_number_of_subelements (int transition_type) const; - virtual int t8_element_is_subelement (const t8_element * - elem) const; + /** Return the subelement id of a given element. + * \param [in] elem A valid element + * \return the subelement id of elem (0 if elem is no subelement) + */ + virtual int t8_element_get_subelement_id (const t8_element * elem); + + /** This function refines a parent element into subelements. + * Depending on the subelement type, the number of subelements + * to fill the parent element, can differ. + * \param [in] elem A valid element + * \param [in] type The subelement type + * \param [out] subelements An array of all subelements of the parent quad element elem + */ + virtual void t8_element_to_transition_cell (const t8_element_t *elem, + int type, + t8_element_t *c[]); + #if T8_ENABLE_DEBUG virtual void t8_element_debug_print (const t8_element_t *elem) const; From 3b20e8f5cf88ce2669f3707f9121747763b3fdfd Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 24 Apr 2024 09:25:59 +0200 Subject: [PATCH 04/55] Add t8_forest_supports_transitioning --- src/t8_element_c_interface.cxx | 8 ++ src/t8_element_c_interface.h | 4 + src/t8_element_cxx.hxx | 5 ++ src/t8_forest/t8_forest.c | 75 +++++++++++++++++++ src/t8_forest/t8_forest_types.h | 2 + .../t8_default_common_cxx.cxx | 8 ++ .../t8_default_common_cxx.hxx | 17 +++-- 7 files changed, 113 insertions(+), 6 deletions(-) diff --git a/src/t8_element_c_interface.cxx b/src/t8_element_c_interface.cxx index 3cbd1be0ac..14332e5119 100644 --- a/src/t8_element_c_interface.cxx +++ b/src/t8_element_c_interface.cxx @@ -46,6 +46,14 @@ t8_element_refines_irregular (const t8_eclass_scheme_c *ts) return ts->t8_element_refines_irregular (); } +int +t8_element_scheme_supports_transitioning (t8_eclass_scheme_c *ts) +{ + T8_ASSERT (ts != NULL); + + return ts->t8_element_scheme_supports_transitioning (); +} + int t8_element_maxlevel (const t8_eclass_scheme_c *ts) { diff --git a/src/t8_element_c_interface.h b/src/t8_element_c_interface.h index f1fb8cea52..f1a5c524e9 100644 --- a/src/t8_element_c_interface.h +++ b/src/t8_element_c_interface.h @@ -49,6 +49,10 @@ t8_element_size (const t8_eclass_scheme_c *ts); int t8_element_refines_irregular (const t8_eclass_scheme_c *ts); +/** Returns true if the given eclass scheme has an implementation for subelements */ +int +t8_element_scheme_supports_transitioning (t8_eclass_scheme_c *ts); + /** Return the maximum allowed level for any element of a given class. * \param [in] ts Implementation of a class scheme. * \return The maximum allowed level for elements of class \b ts. diff --git a/src/t8_element_cxx.hxx b/src/t8_element_cxx.hxx index 7fc815eebe..70aeeaedf2 100644 --- a/src/t8_element_cxx.hxx +++ b/src/t8_element_cxx.hxx @@ -781,6 +781,11 @@ struct t8_eclass_scheme virtual void t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *subelements[]) = 0; + + /** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int + t8_element_scheme_supports_transitioning (void) = 0; + /* --------------------------End functions of transition scheme---------------------*/ virtual void diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index 9c377dbd13..7daa24f7d8 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,7 @@ t8_forest_init (t8_forest_t *pforest) forest->maxlevel_existing = -1; forest->stats_computed = 0; forest->incomplete_trees = -1; + forest->set_subelements = 0; } int @@ -68,6 +70,41 @@ t8_forest_is_initialized (t8_forest_t forest) return forest != NULL && t8_refcount_is_active (&forest->rc) && !forest->committed; } +/** Check whether at least one eclass scheme of forest supports transitioning + * \param [in] forest A forest + * \return True if at least one eclass scheme in forest has an implementation for subelements + */ +int +t8_forest_supports_transitioning (t8_forest_t forest) +{ + int supports_transition = 0; + int supports_transition_all_procs = 0; /* Result over all procs */ + int int_eclass; + int mpiret; + t8_eclass_scheme_c *tscheme; + + /* Iterate over all eclasses */ + for (int_eclass = (int) T8_ECLASS_ZERO; int_eclass < (int) T8_ECLASS_COUNT; + int_eclass++) { + /* If the forest has trees of the current eclass, check if elements of this + * eclass supports transitioning. */ + if (forest->cmesh->num_local_trees_per_eclass[int_eclass] > 0) { + tscheme = forest->scheme_cxx->eclass_schemes[int_eclass]; + // supports_transition = supports_transition + // || t8_element_scheme_supports_transitioning (tscheme); + supports_transition = t8_element_scheme_supports_transitioning (tscheme); + } + } + /* Combine the process-local results via a logic or and distribute the + * result over all procs (in the communicator).*/ + mpiret = + sc_MPI_Allreduce (&supports_transition, &supports_transition_all_procs, 1, + sc_MPI_INT, sc_MPI_LOR, forest->mpicomm); + SC_CHECK_MPI (mpiret); + + return supports_transition_all_procs; +} + int t8_forest_is_committed (const t8_forest_t forest) { @@ -218,6 +255,44 @@ t8_forest_set_balance (t8_forest_t forest, const t8_forest_t set_from, int no_re } } +void +t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, + int set_transition_with_balance) +{ + T8_ASSERT (t8_forest_is_initialized (forest)); + + if (set_transition_with_balance) { + /* balance with repartition */ + t8_forest_set_balance (forest, set_from, 0); + } + + + if (set_from != NULL) { + /* Note that it is possible to apply transitioning to a forest without transition implementation. + * In this case, the transition refine routine will return 0, keeping the forest unchanged. + * Nevertheless, we assert here in this case. */ + T8_ASSERT (t8_forest_supports_transitioning (set_from)); + /* If set_from = NULL, we assume a previous forest_from was set */ + forest->set_from = set_from; + } + else { + T8_ASSERT (forest->set_from != NULL); + T8_ASSERT (t8_forest_supports_transitioning (forest->set_from)); + } + + /* Add SUBELEMENTS to the from_method. + * This overwrites T8_FOREST_FROM_COPY */ + if (forest->from_method == T8_FOREST_FROM_LAST) { + forest->from_method = T8_FOREST_FROM_TRANSITION; + } + else { + forest->from_method |= T8_FOREST_FROM_TRANSITION; + } + + /* set the forests subelement flag, which is for example used by the LFN routine */ + forest->set_subelements = 1; +} + void t8_forest_set_ghost_ext (t8_forest_t forest, int do_ghost, t8_ghost_type_t ghost_type, int ghost_version) { diff --git a/src/t8_forest/t8_forest_types.h b/src/t8_forest/t8_forest_types.h index ddefa77777..72ca88acda 100644 --- a/src/t8_forest/t8_forest_types.h +++ b/src/t8_forest/t8_forest_types.h @@ -58,6 +58,8 @@ typedef int8_t t8_forest_from_t; #define T8_FOREST_FROM_NONE 0x8 /* A value that is not reached by adding up the other values. No from method used */ #define T8_FOREST_FROM_LAST T8_FOREST_FROM_NONE +#define T8_FOREST_FROM_TRANSITION 0x8 + #define T8_FOREST_BALANCE_REPART 1 /**< Value of forest->set_balance if balancing with repartitioning */ #define T8_FOREST_BALANCE_NO_REPART 2 /**< Value of forest->set_balance if balancing without repartitioning */ diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx index 78287a53c1..cc3fdf6b9d 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx @@ -213,4 +213,12 @@ t8_default_scheme_common_c::t8_element_to_transition_cell (const t8_element_t } +int +t8_default_scheme_common_c::t8_element_scheme_supports_transitioning (void) +{ + /* Default implementation - current scheme is no transition scheme */ + return 0; +} + + T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx index 196c3e9638..6cc75c71c5 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx @@ -119,8 +119,8 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { * \param [in] elem A valid element * \return Integer, used as the refine value during transition adaptation. */ - virtual int t8_element_get_transition_refine_identifier (void) - const; + virtual int + t8_element_get_transition_refine_identifier (void) const; /** Check whether a given element is a subelement * \param [in] elem A valid element @@ -141,7 +141,8 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { * \param [in] elem A valid element * \return the subelement id of elem (0 if elem is no subelement) */ - virtual int t8_element_get_subelement_id (const t8_element * elem); + virtual int + t8_element_get_subelement_id (const t8_element * elem); /** This function refines a parent element into subelements. * Depending on the subelement type, the number of subelements @@ -150,9 +151,13 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { * \param [in] type The subelement type * \param [out] subelements An array of all subelements of the parent quad element elem */ - virtual void t8_element_to_transition_cell (const t8_element_t *elem, - int type, - t8_element_t *c[]); + virtual void + t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *c[]); + + /** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int + t8_element_scheme_supports_transitioning (void); + #if T8_ENABLE_DEBUG virtual void From c8887e29f71b75b590b215fa6c105846fdc3a30f Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Thu, 25 Apr 2024 12:24:23 +0200 Subject: [PATCH 05/55] Add function forest_untransition() --- src/t8_forest/t8_forest.c | 38 ++++++++++++++----- src/t8_forest/t8_forest_adapt.cxx | 3 +- src/t8_forest/t8_forest_transition.cxx | 51 +++++++++++++++++++++++++- src/t8_forest/t8_forest_transition.h | 4 ++ src/t8_forest/t8_forest_types.h | 6 +-- 5 files changed, 88 insertions(+), 14 deletions(-) diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index 7daa24f7d8..01d9eb632c 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -77,7 +77,7 @@ t8_forest_is_initialized (t8_forest_t forest) int t8_forest_supports_transitioning (t8_forest_t forest) { - int supports_transition = 0; + int supports_transition = 1; int supports_transition_all_procs = 0; /* Result over all procs */ int int_eclass; int mpiret; @@ -90,16 +90,15 @@ t8_forest_supports_transitioning (t8_forest_t forest) * eclass supports transitioning. */ if (forest->cmesh->num_local_trees_per_eclass[int_eclass] > 0) { tscheme = forest->scheme_cxx->eclass_schemes[int_eclass]; - // supports_transition = supports_transition - // || t8_element_scheme_supports_transitioning (tscheme); - supports_transition = t8_element_scheme_supports_transitioning (tscheme); + supports_transition = supports_transition + && t8_element_scheme_supports_transitioning (tscheme); } } /* Combine the process-local results via a logic or and distribute the * result over all procs (in the communicator).*/ mpiret = sc_MPI_Allreduce (&supports_transition, &supports_transition_all_procs, 1, - sc_MPI_INT, sc_MPI_LOR, forest->mpicomm); + sc_MPI_INT, sc_MPI_LAND, forest->mpicomm); SC_CHECK_MPI (mpiret); return supports_transition_all_procs; @@ -290,7 +289,8 @@ t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, } /* set the forests subelement flag, which is for example used by the LFN routine */ - forest->set_subelements = 1; + //forest->set_subelements = 1; + forest->is_transitioned; } void @@ -601,8 +601,13 @@ t8_forest_commit (t8_forest_t forest) SC_CHECK_ABORT (forest->set_adapt_fn != NULL, "No adapt function specified"); forest->from_method -= T8_FOREST_FROM_ADAPT; if (forest->from_method > 0) { - /* The forest should also be partitioned/balanced. - * We first adapt the forest, then balance and then partition */ + /* The forest should also be partitioned/balanced/transitioned. + * We first untransition the forest, then adapt the forest, then balance and then partition and then possibly transition the forest again*/ + if (forest->is_transitioned){ + t8_forest_untransition(forest); + T8_ASSERT (!t8_forest_is_transitioned (forest)); + } + t8_forest_t forest_adapt; t8_forest_init (&forest_adapt); @@ -627,6 +632,12 @@ t8_forest_commit (t8_forest_t forest) else { /* This forest should only be adapted */ t8_forest_copy_trees (forest, forest->set_from, 0); + /* The input forest for forest_adapt() should always be a non-transitioned forest.*/ + if (forest->is_transitioned){ + t8_forest_untransition(forest); + T8_ASSERT (!t8_forest_is_transitioned (forest)); + } + t8_forest_adapt (forest); } } @@ -685,7 +696,16 @@ t8_forest_commit (t8_forest_t forest) t8_forest_balance (forest, 1); } } - + if (forest->from_method & T8_FOREST_FROM_TRANSITION) { + forest->from_method -= T8_FOREST_FROM_TRANSITION; + /* this is the last from method that we execute, + * nothing should be left todo */ + T8_ASSERT (forest->from_method == 0); + T8_ASSERT (t8_forest_is_balanced(forest)); + /* use subelements */ + t8_forest_transition (forest); + forest->is_transitioned = 1; + } if (forest_from != forest->set_from) { /* decrease reference count of intermediate input forest, possibly destroying it */ t8_forest_unref (&forest->set_from); diff --git a/src/t8_forest/t8_forest_adapt.cxx b/src/t8_forest/t8_forest_adapt.cxx index b3aef0d820..d8b3b1312e 100644 --- a/src/t8_forest/t8_forest_adapt.cxx +++ b/src/t8_forest/t8_forest_adapt.cxx @@ -559,7 +559,8 @@ t8_forest_adapt (t8_forest_t forest) refine = forest->set_adapt_fn (forest, forest->set_from, ltree_id, el_considered, tscheme, is_family, num_elements_to_adapt_callback, elements_from); /* make adjustments of the refine value in the context of transitioned forests */ - if (forest->set_from->is_transitioned == 1 || forest->set_subelements == 1) { + // if (forest->set_from->is_transitioned == 1 || forest->set_subelements == 1) { + if (forest->set_from->is_transitioned == 1){ t8_forest_adjust_refine_for_transitioned_forests (forest, tscheme, t8_element_array_index_locidx (telements_from, el_considered), ltree_id, &refine);} diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx index 1774dffbf4..a9332e2882 100644 --- a/src/t8_forest/t8_forest_transition.cxx +++ b/src/t8_forest/t8_forest_transition.cxx @@ -233,7 +233,7 @@ t8_forest_transition_entry (t8_forest_t forest, const int is_family, int num_elements, t8_element_t *elements[]) { - T8_ASSERT (forest->set_subelements == 1); + //T8_ASSERT (forest->set_subelements == 1); T8_ASSERT (forest->is_transitioned == 0 && forest->set_from->is_transitioned == 0); @@ -288,6 +288,55 @@ t8_forest_transition (t8_forest_t forest) t8_global_productionf ("Done t8_forest_transition.\n"); } /* end of t8_forest_transition */ + +/* This is the entry function for all untransition a forest, called bei forest_adapt + * in t8_forest_untransition. + */ +int +t8_forest_untransition_entry (t8_forest_t forest, + t8_forest_t forest_from, + t8_locidx_t ltree_id, + t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, + const int is_family, + int num_elements, t8_element_t *elements[]) +{ + T8_ASSERT (forest->is_transitioned == 1 + && forest->set_from->is_transitioned == 1); + + //Iterate through elements array and if an element is a subelement, return -1 for + //coarsening this element in forest_adapt. All other elements remain unchanged. + t8_element_t *element = elements[0]; + + if(ts->t8_element_is_subelement(element)){ + return -1; + } + else{ + return 0; + } + +} + + +void +t8_forest_untransition (t8_forest_t forest) +{ + T8_ASSERT (forest->is_transitioned == 1 + && forest->set_from->is_transitioned == 1); + /* In the following, we will call forest_adapt to coarsen all transition cells + * back to their regular parent element. So, forest->set_from is a transitioned forest and + * forest will be non-transitioned. */ + + t8_global_productionf ("Into t8_forest_untransition.\n"); + + forest->set_adapt_fn = t8_forest_untransition_entry; + forest->set_adapt_recursive = 0; + t8_forest_copy_trees (forest, forest->set_from, 0); + t8_forest_adapt (forest); + forest->is_transitioned = 0; + t8_global_productionf ("Done t8_forest_untransition.\n"); +} + /* Test whether the forest is transitioned. * Note 1) We allow non-committed forests in this implementation since this check is used in forest_commit() * Note 2) This test does only check whether there is at least one subelement in the forest. diff --git a/src/t8_forest/t8_forest_transition.h b/src/t8_forest/t8_forest_transition.h index 50517d0189..8c8a2b4713 100644 --- a/src/t8_forest/t8_forest_transition.h +++ b/src/t8_forest/t8_forest_transition.h @@ -70,6 +70,10 @@ int t8_forest_transition_adapt (t8_forest_t forest, * and the forest is adapted. */ void t8_forest_transition (t8_forest_t forest); +/* This function is the point of entry in order to untransition a forest before adapting it. + * Every transition cell gets coarsened back to its parent element. */ +void t8_forest_untransition (t8_forest_t forest); + /* Check whether the forest is transitioned, meaning that subelements exist. */ int t8_forest_is_transitioned (t8_forest_t forest); diff --git a/src/t8_forest/t8_forest_types.h b/src/t8_forest/t8_forest_types.h index 72ca88acda..0694d700ff 100644 --- a/src/t8_forest/t8_forest_types.h +++ b/src/t8_forest/t8_forest_types.h @@ -88,7 +88,7 @@ typedef struct t8_forest Once an element got removed, the flag sets to 1 (true) and stays. For a committed forest this flag is either true on all ranks or false on all ranks. */ - + int is_transitioned; /* Flag parameter that states whether the forest is transitioned or not */ t8_forest_t set_from; /**< Temporarily store source forest. */ t8_forest_from_t from_method; /**< Method to derive from \b set_from. */ t8_forest_adapt_t set_adapt_fn; /**< refinement and coarsen function. Called when \b from_method @@ -99,7 +99,7 @@ typedef struct t8_forest See \ref t8_forest_set_balance. If 0, no balance. If 1 balance with repartitioning, if 2 balance without repartitioning, \see t8_forest_balance */ - int set_subelements; /**< Flag to decide whether subelements should be used in the forest */ + int set_subelements; /**< Flag to decide whether subelements should be used in the forest */ int do_ghost; /**< If True, a ghost layer will be created when the forest is committed. */ t8_ghost_type_t ghost_type; /**< If a ghost layer will be created, the type of neighbors that count as ghost. */ int ghost_algorithm; /**< Controls the algorithm used for ghost. 1 = balanced only. 2 = also unbalanced @@ -139,7 +139,7 @@ typedef struct t8_forest t8_locidx_t local_num_subelements; /**< Number of subelements on this processor. */ t8_gloidx_t global_num_subelements; /**< Number of subelements on all processors. */ t8_profile_t *profile; /**< If not NULL, runtimes and statistics about forest_commit are stored here. */ - int is_transitioned; /* Flag parameter that states whether the forest is transitioned or not */ + sc_statinfo_t stats[T8_PROFILE_NUM_STATS]; int stats_computed; } t8_forest_struct_t; From a237cbbac4342421ea58456f3730a264c75cd4ce Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 7 May 2024 10:29:35 +0200 Subject: [PATCH 06/55] Added two example files, basic_hex and _global_hex --- Makefile.am | 1 + example/Makefile.am | 4 +- example/transition/Makefile.am | 10 + .../transition/t8_transition_basic_hex.cxx | 290 ++++++++++++++++++ .../transition/t8_transition_global_hex.cxx | 145 +++++++++ 5 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 example/transition/Makefile.am create mode 100644 example/transition/t8_transition_basic_hex.cxx create mode 100644 example/transition/t8_transition_global_hex.cxx diff --git a/Makefile.am b/Makefile.am index c5edcd6ca7..f0e35a18ee 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,6 +72,7 @@ DISTCLEANFILES += \ # non-recursive build include src/Makefile.am include src/t8_schemes/t8_default/Makefile.am +include src/t8_schemes/t8_transition/Makefile.am include test/Makefile.am include example/Makefile.am include tutorials/Makefile.am diff --git a/example/Makefile.am b/example/Makefile.am index 6080d75f4b..1d77724811 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -13,4 +13,6 @@ include example/geometry/Makefile.am include example/common/Makefile.am include example/version/Makefile.am -include example/remove/Makefile.am \ No newline at end of file +include example/remove/Makefile.am + +include example/transition/Makefile.am \ No newline at end of file diff --git a/example/transition/Makefile.am b/example/transition/Makefile.am new file mode 100644 index 0000000000..4467e1613a --- /dev/null +++ b/example/transition/Makefile.am @@ -0,0 +1,10 @@ +# This file is part of t8code +# Non-recursive Makefile.am in example/transition +# Included from toplevel directory + +bin_PROGRAMS += \ + example/transition/t8_transition_global_hex \ + example/transition/t8_transition_basic_hex + +example_transition_t8_transition_global_hex_SOURCES = example/transition/t8_transition_global_hex.cxx +example_transition_t8_transition_basic_hex_SOURCES = example/transition/t8_transition_basic_hex.cxx diff --git a/example/transition/t8_transition_basic_hex.cxx b/example/transition/t8_transition_basic_hex.cxx new file mode 100644 index 0000000000..f673ee5285 --- /dev/null +++ b/example/transition/t8_transition_basic_hex.cxx @@ -0,0 +1,290 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element types in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* This is step3 of the t8code tutorials. + * After generating a coarse mesh (step1) and building a uniform forest + * on it (step2), we will now adapt (= refine and coarsen) the forest + * according to our own criterion. + * + * The geometry (coarse mesh) is again a cube, this time modelled with + * 6 tetrahedra, 6 prisms and 4 cubes. + * We refine an element if its midpoint is whithin a sphere of given radius + * around the point (0.5, 0.5, 1) and we coarsen outside of a given radius. + * We will use non-recursive refinement, that means that the refinement level + * of any element will change by at most +-1. + * + * How you can experiment here: + * - Look at the paraview output files of the unifomr and the adapted forest. + * For the adapted forest you can apply a slice filter to look into the cube. + * - Run the program with different process numbers. You should see that refining is + * independent of the number of processes, but coarsening is not. + * This is due to the face that a family can only be coarsened if it is completely + * local to a single process and the distribution among the process may break this property. + * - Change the midpoint coordinates and the radii. + * - Change the adaptation criterion such that elements inside the sphere are coarsened + * and elements outside are refined. + * - Use t8_productionf to print the local number of elements on each process. + * Notice, that the uniform forest is evenly distributed, but that the adapted forest + * is not. This is due to the fact that we do not repartition our forest here. + * - Add a maximum refinement level to the adapt_data struct and use non-recursive refinement. + * Do not refine an element if it has reached the maximum level. (Hint: ts->t8_element_level) + */ + +#include /* General t8code header, always include this. */ +#include /* cmesh definition and basic interface. */ +#include /* A collection of exemplary cmeshes */ +#include /* forest definition and basic interface. */ +#include /* save forest */ +#include /* geometrical information of the forest */ +#include +#include +#include /* default refinement scheme. */ +#include +#include "t8_eclass.h" +#include + +// T8_EXTERN_C_BEGIN (); + +/* TODO (JM): Copied this function from `t8_transition_local.cxx`. Adapt to your needs. */ +#ifdef T8_ENABLE_DEBUG +static int +t8_check_coordinates (double *coords) +{ + /* The initial hex_element is the unit hex with vertices (0,0,0), (1,0,0), (0,1,0), (1,1,0), (0,0,1) ,(1,0,1), (0,1,1) and (1,1,1). + * We know that therefore, all children (even our subelements) will have vertices with coordinates 0, 0.5 or 1. */ + double eps = 1e-126; /* testing up to float precision */ + if ((fabs (coords[0] - 0.0) < eps || fabs (coords[0] - 0.5) < eps || fabs (coords[0] - 1.0) < eps) && + (fabs (coords[1] - 0.0) < eps || fabs (coords[1] - 0.5) < eps || fabs (coords[1] - 1.0) < eps) && + (fabs (coords[2] - 0.0) < eps || fabs (coords[2] - 0.5) < eps || fabs (coords[2] - 1.0) < eps)){ + return true; + } + return false; +} +#endif + +static void +t8_test_hex_local (t8_element_t *hex_element, + t8_eclass_scheme_c *class_scheme) +{ + t8_debugf ("~~~~~~~~~~ Into the t8_test_hex_local function ~~~~~~~~~~\n"); + + t8_element_t *parent; + int num_children, num_vertices; + int child_id; + double coords[3]; + + /* Allocate enough memory for hex children */ + num_children = class_scheme->t8_element_num_children (hex_element); + t8_element_t **children = T8_ALLOC (t8_element_t *, num_children); + class_scheme->t8_element_new (num_children, children); + + /* Create all subelements for the given type from the initial hex element. */ + class_scheme->t8_element_children (hex_element, P8EST_CHILDREN, children); + + /* transition cell must be a family of subelements */ + T8_ASSERT (class_scheme->t8_element_is_family (children)); + + t8_debugf + ("The children array consists of %i elements, whose IDs range from 0 to %i.\n", + num_children, num_children - 1); + + /* Iterate through all subelements and determine their vertex coordinates */ + for (child_id = 0; child_id < num_children; ++child_id) { + /* All children should be standard hex elements here */ + T8_ASSERT (!class_scheme->t8_element_is_subelement (children[child_id])); + +#if T8_ENABLE_DEBUG + /* Print the current subelement */ + class_scheme->t8_element_debug_print (children[child_id]); +#endif + + /* determine the shape of the subelement and use it to determine the number of vertices it has (pyramid -> 5 vertices) */ + const t8_element_shape_t shape = + class_scheme->t8_element_shape (children[child_id]); + + num_vertices = t8_eclass_num_vertices[shape]; + t8_debugf ("Num verticies %i \n", num_vertices); + T8_ASSERT (num_vertices == + class_scheme->t8_element_num_corners (children[child_id])); + + /* Iterate over all vertices of the subelement and determine their coordinates */ + int vertex_count; + for (vertex_count = 0; vertex_count < num_vertices; ++vertex_count) { + class_scheme->t8_element_vertex_reference_coords (children[child_id], + vertex_count, coords); + t8_debugf + ("Child ID: %d; Vertex: %d; Ref cords in [0,1]^2: (%lf,%lf,%lf)\n", + child_id, vertex_count, coords[0], coords[1], coords[2]); + T8_ASSERT (t8_check_coordinates (coords)); + } /* end of vertex loop */ + } /* end of subelement loop */ + + /* coarsen the transition cell back to its parent, which must be equal to the initial quad_element */ + class_scheme->t8_element_new (1, &parent); + class_scheme->t8_element_parent (children[0], parent); + T8_ASSERT (class_scheme->t8_element_compare (hex_element, parent) == 0); + + /* free memory */ + class_scheme->t8_element_destroy (1, &parent); + class_scheme->t8_element_destroy (num_children, children); + T8_FREE (children); + + t8_debugf + ("~~~~~~~~~~ The t8_test_hex_local function finshed successful ~~~~~~~~~~\n"); +} + + +static void +t8_transition_local (t8_eclass_t eclass) +{ + t8_debugf ("~~~~~~~~~~ Into the t8_transition_local function ~~~~~~~~~~\n"); + + t8_scheme_cxx_t *ts = t8_scheme_new_transition_hex_cxx (); + t8_eclass_scheme_c *class_scheme; + t8_element_t *hex_element, *parent; + int subelement_id; + double coords[3]; + int num_subelements; + int num_vertices; + + /* At the moment, subelements are only implemented for the quad and hex scheme. */ + T8_ASSERT (eclass = T8_ECLASS_HEX); + + class_scheme = ts->eclass_schemes[eclass]; + + /* Allocate memory for a new hex element and initialize it */ + class_scheme->t8_element_new (1, &hex_element); + class_scheme->t8_element_set_linear_id (hex_element, 0, 0); + T8_ASSERT (class_scheme->t8_element_is_valid (hex_element)); + + /* First, validate some element funcitons for this hex element */ + t8_test_hex_local (hex_element, class_scheme); + + /* Make checks for all transition types */ + int type; + for (type = 1; type <= T8_SUB_HEX_MAX_TRANSITION_TYPE; type++) { + /* Allocate enough memory for subelements of the given type and initialize them */ + + num_subelements = + class_scheme->t8_element_get_number_of_subelements (type); + + t8_element_t **transition_cell = + T8_ALLOC (t8_element_t *, num_subelements); + class_scheme->t8_element_new (num_subelements, transition_cell); + + /* Create all subelements for the given type from the initial hex element. */ + class_scheme->t8_element_to_transition_cell (hex_element, type, + transition_cell); + + /* transition cell must be a family of subelements */ + T8_ASSERT (class_scheme->t8_element_is_family (transition_cell)); + + t8_debugf ("The given type is type %i.\n", type); + t8_debugf + ("The transition cell of type %i consists of %i subelements, whose IDs range from 0 to %i.\n", + type, num_subelements, num_subelements - 1); + + /* Iterate through all subelements and determine their vertex coordinates */ + for (subelement_id = 0; subelement_id < num_subelements; ++subelement_id) { + /* All elements in a transition cell are subelements */ + T8_ASSERT (class_scheme->t8_element_is_subelement + (transition_cell[subelement_id])); + +#if T8_ENABLE_DEBUG + /* Print the current subelement */ + class_scheme->t8_element_debug_print (transition_cell[subelement_id]); +#endif + + /* determine the shape of the subelement and use it to determine the number of vertices it has (triangle -> 3 vertices) */ + const t8_element_shape_t shape = + class_scheme->t8_element_shape (transition_cell[subelement_id]); + num_vertices = t8_eclass_num_vertices[shape]; + T8_ASSERT (num_vertices == + class_scheme->t8_element_num_corners (transition_cell + [subelement_id])); + T8_ASSERT (num_vertices == + class_scheme->t8_element_num_faces (transition_cell + [subelement_id])); + + /* Iterate over all vertices of the subelement and determine their coordinates */ + int vertex_count; + for (vertex_count = 0; vertex_count < num_vertices; ++vertex_count) { + class_scheme->t8_element_vertex_reference_coords (transition_cell + [subelement_id], + vertex_count, + coords); + t8_debugf + ("Subelement ID: %d; Vertex: %d; Ref cords in [0,1]^3: (%lf,%lf,%lf)\n", + subelement_id, vertex_count, coords[0], coords[1], coords[2]); + T8_ASSERT (t8_check_coordinates (coords)); + } /* end of vertex loop */ + } /* end of subelement loop */ + + /* coarsen the transition cell back to its parent, which must be equal to the initial quad_element */ + class_scheme->t8_element_new (1, &parent); + class_scheme->t8_element_parent (transition_cell[0], parent); + T8_ASSERT (class_scheme->t8_element_compare (hex_element, parent) == 0); + + /* free memory */ + class_scheme->t8_element_destroy (1, &parent); + class_scheme->t8_element_destroy (num_subelements, transition_cell); + T8_FREE (transition_cell); + + } /* end of transition type loop */ + + /* free more memory */ + class_scheme->t8_element_destroy (1, &hex_element); + t8_scheme_cxx_unref (&ts); + + t8_debugf + ("~~~~~~~~~~ The t8_transition_local function finshed successful ~~~~~~~~~~\n"); + +} /* end of t8_transition_local */ + + + + +int +main (int argc, char **argv) +{ + int mpiret; +/* Initialize MPI. This has to happen before we initialize sc or t8code. */ + mpiret = sc_MPI_Init (&argc, &argv); + + SC_CHECK_MPI (mpiret); + /* Initialize the sc library, has to happen before we initialize t8code. */ + sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_ESSENTIAL); + + t8_init (SC_LP_DEFAULT); + + t8_transition_local (T8_ECLASS_HEX); + + sc_finalize (); + + mpiret = sc_MPI_Finalize (); + + SC_CHECK_MPI (mpiret); + + return 0; +} + + diff --git a/example/transition/t8_transition_global_hex.cxx b/example/transition/t8_transition_global_hex.cxx new file mode 100644 index 0000000000..6125b7c38c --- /dev/null +++ b/example/transition/t8_transition_global_hex.cxx @@ -0,0 +1,145 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element types in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* Description: + * This is the example file for refinement with transitioning. In this testcase, we are able to + * (i) refine a mesh according to some refinement criterion and use transiton cells to make the mesh conformal + * (ii) use multiple adaptation steps in which the refinement criterion changes (e.g. the geometry) + * (iii) decide, whether we want to check the LFN function for each mesh + * (iv) decide, whether we want to get statistics printed out, regarding # of elements in the meshes and runtime infos of the several functions or other debugging information + */ + +/* to switch between the default quad scheme and the transition implementation */ +#include "t8_eclass.h" + +#include "t8_forest/t8_forest_general.h" +#include +#include +#include +#include +#include // to write vtk +#include +#include +#include /* for cmesh initialization via for example t8_cmesh_new_hypercube */ +#include +#include + + +/* In this example, the left side of a unit cube with initial level 2 is refined to construct an adapted and transitioned forest. */ + +/* Refinement criterion: All elements with x-coordinate smaller than 0.5 are being refined. All other elements remain unchanged. */ +int +t8_adapt_callback (t8_forest_t forest, + t8_forest_t forest_from, + t8_locidx_t which_tree, + t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, + const int is_family, + const int num_elements, t8_element_t *elements[]) +{ + double coords[3] = {0.0,0.0,0.0}; + ts->t8_element_vertex_reference_coords(elements[0], 0, coords); + if (coords[0]* P8EST_ROOT_LEN < 0.5 ){ + return 1; + } + else if (coords[0] > 0.5){ + return -1; + } + return 0; +} + + + + + +/* Initializing, adapting balancing and transitioning a forest */ +static void +t8_transition_global (void) +{ + /* At the moment, subelements are only implemented for T8_ECLASS_HEX and quads */ + t8_eclass_t eclass = T8_ECLASS_HEX; /* depending on the include file, this will be the transitioned or default hex implementation */ + t8_scheme_cxx_t *ts = t8_scheme_new_transition_hex_cxx (); + t8_eclass_scheme_c *class_scheme; + t8_forest_t forest; + t8_forest_t forest_adapt; + t8_cmesh_t cmesh; + char filename[BUFSIZ]; + + /* refinement setting */ + int initlevel = 2; /* initial uniform refinement level */ + class_scheme = ts->eclass_schemes[eclass]; + + /* construct a single tree hex cmesh */ + cmesh = t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 0, 0); + + /* initialize a forest */ + t8_forest_init (&forest); + + /* set forest parameter via cmesh */ + t8_forest_set_cmesh (forest, cmesh, sc_MPI_COMM_WORLD); + t8_forest_set_level (forest, initlevel); + + t8_forest_set_scheme (forest, t8_scheme_new_transition_hex_cxx ()); + + /* commit the forest */ + t8_forest_commit (forest); + + // for (int adaptation_count = 1; adaptation_count <= 0; ++adaptation_count) { + // t8_forest_init (&forest_adapt); + + // t8_forest_set_adapt (forest_adapt, forest, t8_adapt_callback, 0); + // // t8_forest_set_balance (forest_adapt, forest, 0); + // t8_forest_set_transition (forest_adapt, forest, 1); + // t8_forest_commit (forest_adapt); + + // // t8_forest_commit (forest_adapt); /* adapt the forest */ + + // //snprintf (filename, BUFSIZ, "forest_REFINEMENT_half_element_adapted_mesh"); + // //t8_forest_write_vtk (forest, filename); + // forest = forest_adapt; + // } + + t8_forest_unref (&forest); +} /* end of t8_transition_global */ + + + +int +main (int argc, char **argv) +{ + int mpiret; + + mpiret = sc_MPI_Init (&argc, &argv); + SC_CHECK_MPI (mpiret); + + sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_DEFAULT); + t8_init (SC_LP_DEFAULT); + + t8_transition_global (); + + sc_finalize (); + mpiret = sc_MPI_Finalize (); + + SC_CHECK_MPI (mpiret); + + return 0; +} From a4ba651026867dcc319a81532a744a1c281330d8 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 7 May 2024 10:34:27 +0200 Subject: [PATCH 07/55] Add const keyword + forest_transition functions such as set_transition --- src/t8_element_cxx.hxx | 2 +- src/t8_forest/t8_forest.c | 9 ++++----- src/t8_forest/t8_forest_general.h | 15 +++++++++++++++ src/t8_forest/t8_forest_transition.cxx | 3 ++- src/t8_forest/t8_forest_types.h | 5 ++--- .../t8_default_common/t8_default_common_cxx.cxx | 3 +-- .../t8_default_common/t8_default_common_cxx.hxx | 2 +- 7 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/t8_element_cxx.hxx b/src/t8_element_cxx.hxx index 70aeeaedf2..0cb5ca382a 100644 --- a/src/t8_element_cxx.hxx +++ b/src/t8_element_cxx.hxx @@ -769,7 +769,7 @@ struct t8_eclass_scheme * \return the subelement id of elem (0 if elem is no subelement) */ virtual int - t8_element_get_subelement_id (const t8_element * elem) = 0; + t8_element_get_subelement_id (const t8_element * elem) const = 0; /** This function refines a parent element into subelements. * Depending on the subelement type, the number of subelements diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index 01d9eb632c..e1d98b0040 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -289,7 +289,7 @@ t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, } /* set the forests subelement flag, which is for example used by the LFN routine */ - //forest->set_subelements = 1; + forest->set_subelements = 1; forest->is_transitioned; } @@ -482,7 +482,6 @@ t8_forest_populate_irregular (t8_forest_t forest) t8_forest_set_cmesh (forest_zero, forest->cmesh, forest->mpicomm); t8_forest_set_scheme (forest_zero, forest->scheme_cxx); t8_forest_commit (forest_zero); - /* Up to the specified level we refine every element. */ for (int i = 1; i <= forest->set_level; i++) { t8_forest_init (&forest_tmp); @@ -637,7 +636,7 @@ t8_forest_commit (t8_forest_t forest) t8_forest_untransition(forest); T8_ASSERT (!t8_forest_is_transitioned (forest)); } - + t8_forest_adapt (forest); } } @@ -1666,6 +1665,6 @@ t8_forest_unref (t8_forest_t *pforest) T8_ASSERT (forest->rc.refcount > 0); T8_ASSERT (forest != NULL); if (t8_refcount_unref (&forest->rc)) { - t8_forest_reset (pforest); + t8_forest_reset (pforest); } -} +} \ No newline at end of file diff --git a/src/t8_forest/t8_forest_general.h b/src/t8_forest/t8_forest_general.h index 7521aa1704..f2b7c572fa 100644 --- a/src/t8_forest/t8_forest_general.h +++ b/src/t8_forest/t8_forest_general.h @@ -386,6 +386,21 @@ t8_forest_comm_global_num_elements (t8_forest_t forest); void t8_forest_comm_global_num_subelements (t8_forest_t forest); + +/** Set a source forest to use subelements during commit, that will remove hanging faces from the adapted mesh. + * \param [in, out] forest The forest. + * \param [in] set_from A second forest that should be transitioned. + * \param [in] set_transition_with_balance If 1, then set_balance will be applied. If 0 and set_balance + * has been used before, then balance will still be set (0 does not unset balance). + * \note This feature is currently only available for the 2D quad scheme. + */ +void +t8_forest_set_transition (t8_forest_t forest, + const t8_forest_t set_from, + int + set_transition_with_balance); + + /** After allocating and adding properties to a forest, commit the changes. * This call sets up the internal state of the forest. * \param [in,out] forest Must be created with \ref t8_forest_init and diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx index a9332e2882..3c41a4b497 100644 --- a/src/t8_forest/t8_forest_transition.cxx +++ b/src/t8_forest/t8_forest_transition.cxx @@ -24,6 +24,7 @@ * In this file, we define the call-back function that is used to construct transition cells. */ + #include "t8_eclass.h" #include #include @@ -233,7 +234,7 @@ t8_forest_transition_entry (t8_forest_t forest, const int is_family, int num_elements, t8_element_t *elements[]) { - //T8_ASSERT (forest->set_subelements == 1); + T8_ASSERT (forest->set_subelements == 1); T8_ASSERT (forest->is_transitioned == 0 && forest->set_from->is_transitioned == 0); diff --git a/src/t8_forest/t8_forest_types.h b/src/t8_forest/t8_forest_types.h index 0694d700ff..e11b727d76 100644 --- a/src/t8_forest/t8_forest_types.h +++ b/src/t8_forest/t8_forest_types.h @@ -55,10 +55,9 @@ typedef int8_t t8_forest_from_t; #define T8_FOREST_FROM_ADAPT 0x1 #define T8_FOREST_FROM_PARTITION 0x2 #define T8_FOREST_FROM_BALANCE 0x4 -#define T8_FOREST_FROM_NONE 0x8 /* A value that is not reached by adding up the other values. No from method used */ -#define T8_FOREST_FROM_LAST T8_FOREST_FROM_NONE - #define T8_FOREST_FROM_TRANSITION 0x8 +#define T8_FOREST_FROM_NONE 0x16 /* A value that is not reached by adding up the other values. No from method used */ +#define T8_FOREST_FROM_LAST T8_FOREST_FROM_NONE #define T8_FOREST_BALANCE_REPART 1 /**< Value of forest->set_balance if balancing with repartitioning */ #define T8_FOREST_BALANCE_NO_REPART 2 /**< Value of forest->set_balance if balancing without repartitioning */ diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx index cc3fdf6b9d..c97f75bb5c 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx @@ -191,8 +191,7 @@ t8_default_scheme_common_c::t8_element_is_subelement (const t8_element * elem) c } int -t8_default_scheme_common_c::t8_element_get_subelement_id (const - t8_element * elem) +t8_default_scheme_common_c::t8_element_get_subelement_id (const t8_element * elem) const { SC_ABORT ("This function is not implemented for the given scheme.\n"); } diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx index 6cc75c71c5..07055d70d0 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx @@ -142,7 +142,7 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { * \return the subelement id of elem (0 if elem is no subelement) */ virtual int - t8_element_get_subelement_id (const t8_element * elem); + t8_element_get_subelement_id (const t8_element * elem) const; /** This function refines a parent element into subelements. * Depending on the subelement type, the number of subelements From 0f7ff6c9ce93ff93ca1135a25587b041bd6f9be9 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 7 May 2024 12:12:35 +0200 Subject: [PATCH 08/55] small adjustments (like additional MPI functions and const keyword) --- .../t8_transition_conformal_hex.cxx | 6 +- .../t8_transition_conformal_hex_cxx.cxx | 133 ++++++++++++++---- .../t8_transition_conformal_hex_cxx.hxx | 92 ++++++++++-- .../t8_transition_conformal_quad.cxx | 11 +- .../t8_transition_conformal_quad_cxx.cxx | 123 +++++++++++++--- .../t8_transition_conformal_quad_cxx.hxx | 95 +++++++++++-- .../t8_transition/t8_transition_cxx.hxx | 2 +- 7 files changed, 378 insertions(+), 84 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx index 10caf35d4a..b67f463731 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -//#include +#include #include #include #include @@ -28,7 +28,7 @@ #include #include #include -#include "t8_transition_conformal_hex_cxx.hxx" +#include /* We want to export the whole implementation to be callable from "C" */ T8_EXTERN_C_BEGIN (); @@ -42,7 +42,7 @@ t8_scheme_new_transition_hex_cxx (void) t8_refcount_init (&s->rc); s->eclass_schemes[T8_ECLASS_VERTEX] = NULL; - s->eclass_schemes[T8_ECLASS_LINE] = NULL; /* Standard T8_ECLASS_LINE is used by the quad scheme */ + s->eclass_schemes[T8_ECLASS_LINE] = NULL; s->eclass_schemes[T8_ECLASS_QUAD] = new t8_default_scheme_quad_c (); s->eclass_schemes[T8_ECLASS_HEX] = new t8_subelement_scheme_hex_c (); s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 4668301959..4c4f706b6d 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1068,7 +1068,7 @@ t8_subelement_scheme_hex_c::t8_element_ancestor_id (const t8_element_t *elem, } int -t8_subelement_scheme_hex_c::t8_element_is_family (t8_element_t **fam) const +t8_subelement_scheme_hex_c::t8_element_is_family (t8_element_t *const *fam) const { /* Note that this test is very rudimentary, especially when there subelements are in fam */ t8_hex_with_subelements **phex_w_sub_family = @@ -1219,8 +1219,7 @@ t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t void t8_subelement_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, - t8_element_t *elem2, - int level) const + t8_element_t *elem2) const { const t8_hex_with_subelements *phex_w_sub_elem1 = (const t8_hex_with_subelements *) elem1; @@ -1237,7 +1236,7 @@ t8_subelement_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); - T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); + T8_ASSERT (0 <= t8_element_level (elem1) && t8_element_level (elem1) <= P8EST_OLD_QMAXLEVEL); p8est_quadrant_successor ((p8est_quadrant_t *) elem1, (p8est_quadrant_t *) elem2); } @@ -2017,13 +2016,7 @@ t8_subelement_scheme_hex_c::t8_element_refines_irregular () const } void -t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t - *elem, - const double - *ref_coords, - const void - *user_data, - double *out_coords) +t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) const { SC_ABORT ("This function is not implemented for the given scheme.\n"); @@ -2672,8 +2665,7 @@ t8_subelement_scheme_hex_c::t8_element_get_transition_type (const } int -t8_subelement_scheme_hex_c::t8_element_get_subelement_id (const - t8_element * elem) +t8_subelement_scheme_hex_c::t8_element_get_subelement_id (const t8_element * elem) const { T8_ASSERT (t8_element_is_valid (elem)); @@ -2728,7 +2720,10 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell /* Below are the cases in which the neighbor is no sibling. * The idea is to fill a location array with the desired properties of the real neighbor. * Togehter with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ - + /* get the location of elem */ + int + location_elem[3] = { }; /* {face, is_split, number of subelement at face} */ + t8_element_get_location_of_subelement (elem, location_elem); //Case 2: The element is a subelement and we are looking for a face neighbor at face 4. if (t8_element_is_subelement(elem)) { @@ -2748,10 +2743,6 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell * We are searching for the subelement id of the real neighbor neigh. * Note that both transition cells can have different levels. */ - /* get the location of elem */ - int - location_elem[3] = { }; /* {face, is_split, number of subelement at face} */ - t8_element_get_location_of_subelement (elem, location_elem); /* Initialize the location array of the real neighbor. */ int @@ -2984,14 +2975,13 @@ t8_subelement_scheme_hex_c::t8_element_new (int length, t8_element_t **elem) con for (elem_count = 0; elem_count < length; elem_count++) { t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem[elem_count]; - t8_element_init (1, elem[elem_count], 0); + t8_element_init (1, elem[elem_count]); T8_QUAD_SET_TDIM ((p8est_quadrant_t *) & phex_w_sub->p8q, 3); } } void -t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem, - int new_called) const +t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem) const { t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; @@ -3005,11 +2995,11 @@ t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem, #ifdef T8_ENABLE_DEBUG /* In debugging mode we iterate over all length many elements and * set their hex to the level 0 hex with ID 0. */ - if (!new_called) { - p8est_quadrant_t *hex = &phex_w_sub[elem_count].p8q; - p8est_quadrant_set_morton (hex, 0, 0); - T8_QUAD_SET_TDIM (hex, 3); - T8_ASSERT (p8est_quadrant_is_extended (hex)); + p8est_quadrant_t *hex = &phex_w_sub[elem_count].p8q; + for (int i = 0; i < length; i++) { + p8est_quadrant_set_morton (hex + i, 0, 0); + T8_QUAD_SET_TDIM (hex + i, 3); + T8_ASSERT (p8est_quadrant_is_extended (hex + i)); } #endif } @@ -3027,6 +3017,27 @@ t8_subelement_scheme_hex_c::t8_element_transition_scheme_is_conformal (void) return T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL; } +int +t8_subelement_scheme_hex_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const{ + + if(t8_element_get_subelement_id((const t8_element * ) elem1) == t8_element_get_subelement_id((const t8_element * ) elem2)){ + return 1; + } +else{ + return 0; +} +} + +void +t8_subelement_scheme_hex_c::t8_element_root (t8_element_t *elem) const{ + SC_ABORT_NOT_REACHED(); + } + + +// void +// t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem) const{ +// SC_ABORT_NOT_REACHED(); +// } #ifdef T8_ENABLE_DEBUG void t8_subelement_scheme_hex_c::t8_element_debug_print (const t8_element_t *elem) const @@ -3068,6 +3079,7 @@ t8_subelement_scheme_hex_c::t8_element_is_valid (const t8_element_t * elem) cons && t8_element_subelement_values_are_valid (elem)); } + /* *INDENT-OFF* */ /* indent bug, indent adds a second "const" modifier */ int @@ -3086,8 +3098,77 @@ t8_subelement_scheme_hex_c::t8_element_subelement_values_are_valid (const ((phex_w_sub->subelement_id >= 0 && phex_w_sub->subelement_id <= T8_SUB_HEX_MAX_SUBELEMENT_ID))); } + +void +t8_subelement_scheme_hex_c::t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const{ + SC_ABORT_NOT_REACHED(); +} #endif +/* each hex is packed as x,y,z coordinates and the level */ +void +t8_subelement_scheme_hex_c::t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, + void *send_buffer, const int buffer_size, int *position, + sc_MPI_Comm comm) const +{ + SC_ABORT_NOT_REACHED(); + // int mpiret; + // p8est_quadrant_t **quads = (p8est_quadrant_t **) elements; + // for (unsigned int ielem = 0; ielem < count; ielem++) { + // mpiret = sc_MPI_Pack (&(quads[ielem]->x), 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Pack (&quads[ielem]->y, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Pack (&quads[ielem]->z, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Pack (&quads[ielem]->level, 1, sc_MPI_INT8_T, send_buffer, buffer_size, position, comm); + // SC_CHECK_MPI (mpiret); + // } +} + +/* each hex is packed as x,y,z coordinates and the level */ +void +t8_subelement_scheme_hex_c::t8_element_MPI_Pack_size (const unsigned int count, sc_MPI_Comm comm, int *pack_size) const +{ + SC_ABORT_NOT_REACHED(); + // int singlesize = 0; + // int datasize = 0; + // int mpiret; + + // /* x,y,z */ + // mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &datasize); + // SC_CHECK_MPI (mpiret); + // singlesize += 3 * datasize; + + // /* level */ + // mpiret = sc_MPI_Pack_size (1, sc_MPI_INT8_T, comm, &datasize); + // SC_CHECK_MPI (mpiret); + // singlesize += datasize; + + // *pack_size = count * singlesize; +} + +/* each hex is packed as x,y,z coordinates and the level */ +void +t8_subelement_scheme_hex_c::t8_element_MPI_Unpack (void *recvbuf, const int buffer_size, int *position, + t8_element_t **elements, const unsigned int count, + sc_MPI_Comm comm) const +{ + SC_ABORT_NOT_REACHED(); + // int mpiret; + // p8est_quadrant_t **quads = (p8est_quadrant_t **) elements; + // for (unsigned int ielem = 0; ielem < count; ielem++) { + // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->x), 1, sc_MPI_INT, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->y), 1, sc_MPI_INT, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->z), 1, sc_MPI_INT, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->level), 1, sc_MPI_INT8_T, comm); + // SC_CHECK_MPI (mpiret); + // } +} + /* Constructor */ t8_subelement_scheme_hex_c::t8_subelement_scheme_hex_c (void) { diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 06aec744c3..e977959548 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -36,8 +36,8 @@ #include #include -#include "t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.hxx" -#include "t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx" +#include +#include #include @@ -141,9 +141,9 @@ public: */ virtual void t8_element_new (int length, t8_element_t **elem) const; - /** Initialize an array of allocated elements. */ - virtual void t8_element_init (int length, t8_element_t *elem, - int called_new) const; + // /** Initialize an array of allocated elements. */ + // virtual void t8_element_init (int length, t8_element_t *elem, + // int called_new) const; /** Return the maximum level allowed for this element class. */ virtual int t8_element_maxlevel (void) const; @@ -253,7 +253,7 @@ public: int level) const; /** Return nonzero if collection of elements is a family */ - virtual int t8_element_is_family (t8_element_t **fam) const; + virtual int t8_element_is_family (t8_element_t *const *fam) const; /** Construct the nearest common ancestor of two elements in the same tree. */ virtual void t8_element_nca (const t8_element_t *elem1, @@ -373,8 +373,7 @@ public: int level) const; /** Compute s as a successor of t*/ - virtual void t8_element_successor (const t8_element_t *t, - t8_element_t *s, int level) const; + virtual void t8_element_successor (const t8_element_t *t, t8_element_t *s) const; /** Get the integer coordinates of the anchor node of an element */ virtual void t8_element_anchor (const t8_element_t *elem, @@ -398,10 +397,8 @@ public: * \param [in] user_data User data. * \param [out] out_coords The coordinates of the point in the reference space of the tree. */ - virtual void t8_element_reference_coords (const t8_element_t *elem, - const double *ref_coords, - const void *user_data, - double *out_coords) + virtual void t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, + double *out_coords) const; /** Construct a transition cell of type type */ @@ -423,7 +420,7 @@ public: t8_element * elem); /** Get the subelement id of elem */ - virtual int t8_element_get_subelement_id (const t8_element * elem); + virtual int t8_element_get_subelement_id (const t8_element * elem) const; /** Get the subelement id of the neighbor subelement of elem at face elem_face * that is a sibling of the subelement neigh. @@ -537,6 +534,65 @@ protected: void t8_element_reset_subelement_values (t8_element_t *elem) const; + /** Check if two elements are equal. + * \param [in] ts Implementation of a class scheme. + * \param [in] elem1 The first element. + * \param [in] elem2 The second element. + * \return 1 if the elements are equal, 0 if they are not equal + */ + virtual int + t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const; + + /** Fills an element with the root element. + * \param [in,out] elem The element to be filled with root. + */ + void + t8_element_root (t8_element_t *elem) const; + + /** Initialize an array of allocated hexahedra/subelements. + * \param [in] length The number of hex to be initialized. + * \param [in,out] elems On input an array of \b length many allocated + * elements. + * \param [in] called_new True if the elements in \a elem were created by a call + * to \ref t8_element_new. False if no element in \a elem + * was created in this way. The case that only some elements + * were created by \ref t8_element_new should never occur. + * \note In debugging mode, an element that was passed to \ref t8_element_init + * must pass \ref t8_element_is_valid. + * \note If an element was created by \ref t8_element_new then \ref t8_element_init + * may not be called for it. Thus, \ref t8_element_new should initialize an element + * in the same way as a call to \ref t8_element_init would. + * Thus, if \a called_new is true this function should usually do nothing. + * \see t8_element_new + * \see t8_element_is_valid + */ + virtual void + t8_element_init (int length, t8_element_t *elem) const; + + virtual void + t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, void *send_buffer, int buffer_size, + int *position, sc_MPI_Comm comm) const; + + /** Determine an upper bound for the size of the packed message of \b count elements + * \param [in] count Number of elements to pack + * \param [in] comm MPI Communicator + * \param [out] pack_size upper bound on the message size + */ + virtual void + t8_element_MPI_Pack_size (const unsigned int count, sc_MPI_Comm comm, int *pack_size) const; + + /** Unpack multiple elements from contiguous memory that was received via MPI. + * \param [in] recvbuf Buffer from which to unpack the elements + * \param [in] buffer_size size of the buffer (in order to check that we don't access out of range) + * \param [in, out] position the position of the first byte that is not already packed + * \param [in] elements Array of initialised elements that is to be filled from the message + * \param [in] count Number of elements to unpack + * \param [in] comm MPI Communicator + */ + virtual void + t8_element_MPI_Unpack (void *recvbuf, const int buffer_size, int *position, t8_element_t **elements, + const unsigned int count, sc_MPI_Comm comm) const; + #ifdef T8_ENABLE_DEBUG /** Query whether an elements subelement values are valid * \param [in] source A element @@ -545,6 +601,16 @@ protected: int t8_element_subelement_values_are_valid (const t8_element_t *elem) const; + + /** + * Print a given element. For a example for a triangle print the coordinates + * and the level of the triangle. This function is only available in the + * debugging configuration. + * + * \param [in] elem The element to print + */ + virtual void + t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const; #endif }; diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx index 5838ab9c68..3b1c8f1985 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx @@ -22,10 +22,12 @@ #include #include +#include + #include #include -#include -#include "t8_transition_conformal_quad_cxx.hxx" + +#include /* We want to export the whole implementation to be callable from "C" */ T8_EXTERN_C_BEGIN (); @@ -42,7 +44,7 @@ t8_scheme_new_transition_quad_cxx (void) s->eclass_schemes[T8_ECLASS_LINE] = new t8_default_scheme_line_c (); /* Standard T8_ECLASS_LINE is used by the quad scheme */ s->eclass_schemes[T8_ECLASS_QUAD] = new t8_subelement_scheme_quad_c (); s->eclass_schemes[T8_ECLASS_HEX] = NULL; - s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); /* can be used for hybrid meshes - not conformal as long as no conformal transition tri class exists */ + s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); /* can be used for hybrid meshes - not conformal as long as no conformal transition tri class exists */ s->eclass_schemes[T8_ECLASS_TET] = NULL; s->eclass_schemes[T8_ECLASS_PRISM] = NULL; s->eclass_schemes[T8_ECLASS_PYRAMID] = NULL; @@ -50,4 +52,7 @@ t8_scheme_new_transition_quad_cxx (void) return s; } + + + T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index 4a4bd796d3..c35da4d0cf 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -555,7 +555,7 @@ t8_subelement_scheme_quad_c::t8_element_ancestor_id (const t8_element_t *elem, } int -t8_subelement_scheme_quad_c::t8_element_is_family (t8_element_t **fam) const +t8_subelement_scheme_quad_c::t8_element_is_family (t8_element_t *const *fam) const { /* Note that this test is very rudimentary, especially when there subelements are in fam */ t8_quad_with_subelements **pquad_w_sub_family = @@ -693,8 +693,7 @@ t8_subelement_scheme_quad_c::t8_element_last_descendant (const t8_element_t void t8_subelement_scheme_quad_c::t8_element_successor (const t8_element_t *elem1, - t8_element_t *elem2, - int level) const + t8_element_t *elem2) const { const t8_quad_with_subelements *pquad_w_sub_elem1 = (const t8_quad_with_subelements *) elem1; @@ -711,12 +710,12 @@ t8_subelement_scheme_quad_c::t8_element_successor (const t8_element_t *elem1, T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); - T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + T8_ASSERT (0 <= t8_element_level (elem1) && t8_element_level (elem1) <= P4EST_QMAXLEVEL); - id = p4est_quadrant_linear_id (q, level); - T8_ASSERT (id + 1 < ((t8_linearidx_t) 1) << P4EST_DIM * level); + id = p4est_quadrant_linear_id (q, t8_element_level (elem1)); + T8_ASSERT (id + 1 < ((t8_linearidx_t) 1) << P4EST_DIM * t8_element_level (elem1)); t8_element_reset_subelement_values (elem2); - p4est_quadrant_set_morton (r, level, id + 1); + p4est_quadrant_set_morton (r, t8_element_level (elem1), id + 1); t8_element_copy_surround (q, r); } @@ -1506,13 +1505,8 @@ t8_subelement_scheme_quad_c::t8_element_refines_irregular () const } void -t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t - *elem, - const double - *ref_coords, - const void - *user_data, - double *out_coords) +t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, + double *out_coords) const { SC_ABORT ("This function is not implemented for the given scheme.\n"); @@ -1941,8 +1935,7 @@ t8_subelement_scheme_quad_c::t8_element_get_transition_type (const } int -t8_subelement_scheme_quad_c::t8_element_get_subelement_id (const - t8_element * elem) +t8_subelement_scheme_quad_c::t8_element_get_subelement_id (const t8_element * elem) const { T8_ASSERT (t8_element_is_valid (elem)); @@ -2338,15 +2331,14 @@ t8_subelement_scheme_quad_c::t8_element_new (int length, t8_element_t **elem) co for (elem_count = 0; elem_count < length; elem_count++) { t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem[elem_count]; - t8_element_init (1, elem[elem_count], 0); + t8_element_init (1, elem[elem_count]); /* set dimension of quad to 2 */ T8_QUAD_SET_TDIM ((p4est_quadrant_t *) & pquad_w_sub->p4q, 2); } } void -t8_subelement_scheme_quad_c::t8_element_init (int length, t8_element_t *elem, - int new_called) const +t8_subelement_scheme_quad_c::t8_element_init (int length, t8_element_t *elem) const { t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; @@ -2360,11 +2352,12 @@ t8_subelement_scheme_quad_c::t8_element_init (int length, t8_element_t *elem, #ifdef T8_ENABLE_DEBUG /* In debugging mode we iterate over all length many elements and * set their quad to the level 0 quad with ID 0. */ - if (!new_called) { p4est_quadrant_t *quad = &pquad_w_sub[elem_count].p4q; - p4est_quadrant_set_morton (quad, 0, 0); - T8_QUAD_SET_TDIM (quad, 2); - T8_ASSERT (p4est_quadrant_is_extended (quad)); + /* Set all values to 0 */ + for (int i = 0; i < length; i++) { + p4est_quadrant_set_morton (quad + i, 0, 0); + T8_QUAD_SET_TDIM (quad + i, 2); + T8_ASSERT (p4est_quadrant_is_extended (quad + i)); } #endif } @@ -2382,6 +2375,85 @@ t8_subelement_scheme_quad_c::t8_element_transition_scheme_is_conformal (void) return T8_QUAD_TRANSITION_SCHEME_IS_CONFORMAL; } +int +t8_subelement_scheme_quad_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const{ + + if(t8_element_get_subelement_id((const t8_element_t * ) elem1) == t8_element_get_subelement_id((const t8_element_t *) elem2)){ + return 1; + } +else{ + return 0; +} +} + +void +t8_subelement_scheme_quad_c::t8_element_root (t8_element_t *elem) const { + SC_ABORT_NOT_REACHED(); + } + + + +void +t8_subelement_scheme_quad_c::t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, + void *send_buffer, const int buffer_size, int *position, + sc_MPI_Comm comm) const +{ + SC_ABORT_NOT_REACHED(); + + // int mpiret; + // p4est_quadrant_t **quads = (p4est_quadrant_t **) elements; + // for (unsigned int ielem = 0; ielem < count; ielem++) { + // mpiret = sc_MPI_Pack (&(quads[ielem]->x), 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Pack (&quads[ielem]->y, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Pack (&quads[ielem]->level, 1, sc_MPI_INT8_T, send_buffer, buffer_size, position, comm); + // SC_CHECK_MPI (mpiret); + // } +} + +/* each quad is packed as x,y coordinates and the level */ +void +t8_subelement_scheme_quad_c::t8_element_MPI_Pack_size (const unsigned int count, sc_MPI_Comm comm, int *pack_size) const +{ + SC_ABORT_NOT_REACHED(); + // int singlesize = 0; + // int datasize = 0; + // int mpiret; + + // /* x,y */ + // mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &datasize); + // SC_CHECK_MPI (mpiret); + // singlesize += 2 * datasize; + + // /* level */ + // mpiret = sc_MPI_Pack_size (1, sc_MPI_INT8_T, comm, &datasize); + // SC_CHECK_MPI (mpiret); + // singlesize += datasize; + + // *pack_size = count * singlesize; +} + +/* each quad is packed as x,y coordinates and the level */ +void +t8_subelement_scheme_quad_c::t8_element_MPI_Unpack (void *recvbuf, const int buffer_size, int *position, + t8_element_t **elements, const unsigned int count, + sc_MPI_Comm comm) const +{ + SC_ABORT_NOT_REACHED(); + // int mpiret; + // p4est_quadrant_t **quads = (p4est_quadrant_t **) elements; + // for (unsigned int ielem = 0; ielem < count; ielem++) { + // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->x), 1, sc_MPI_INT, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->y), 1, sc_MPI_INT, comm); + // SC_CHECK_MPI (mpiret); + // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->level), 1, sc_MPI_INT8_T, comm); + // SC_CHECK_MPI (mpiret); + // } +} + + #ifdef T8_ENABLE_DEBUG void t8_subelement_scheme_quad_c::t8_element_debug_print (const t8_element_t *elem) const @@ -2441,6 +2513,11 @@ t8_subelement_scheme_quad_c::t8_element_subelement_values_are_valid (const pquad_w_sub->subelement_id <= T8_SUB_QUAD_MAX_SUBELEMENT_ID) || pquad_w_sub->subelement_id == 0); } + +void +t8_subelement_scheme_quad_c::t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const{ + SC_ABORT_NOT_REACHED(); +} #endif /* Constructor */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index f8c1b8b29a..77fa7c432b 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -38,8 +38,9 @@ #include -#include "t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.hxx" -#include "t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx" +#include +#include +#include /** The structure holding a quadrilateral element in the default scheme. * We make this definition public for interoperability of element classes. @@ -120,7 +121,7 @@ typedef t8_quad_with_subelements t8_pquad_t; t8_eclass_scheme_t *t8_subelement_scheme_new_quad (void); #endif -struct t8_subelement_scheme_quad_c:public t8_default_scheme_common_c +struct t8_subelement_scheme_quad_c: public t8_default_scheme_common_c { public: /** The virtual table for a particular implementation of an element class. */ @@ -135,9 +136,6 @@ public: */ virtual void t8_element_new (int length, t8_element_t **elem) const; - /** Initialize an array of allocated elements. */ - virtual void t8_element_init (int length, t8_element_t *elem, - int called_new) const; /** Return the maximum level allowed for this element class. */ virtual int t8_element_maxlevel (void) const; @@ -247,7 +245,7 @@ public: int level) const; /** Return nonzero if collection of elements is a family */ - virtual int t8_element_is_family (t8_element_t **fam) const; + virtual int t8_element_is_family (t8_element_t *const *fam) const; /** Construct the nearest common ancestor of two elements in the same tree. */ virtual void t8_element_nca (const t8_element_t *elem1, @@ -368,7 +366,7 @@ public: /** Compute s as a successor of t*/ virtual void t8_element_successor (const t8_element_t *t, - t8_element_t *s, int level) const; + t8_element_t *s) const; /** Get the integer coordinates of the anchor node of an element */ virtual void t8_element_anchor (const t8_element_t *elem, @@ -392,10 +390,8 @@ public: * \param [in] user_data User data. * \param [out] out_coords The coordinates of the point in the reference space of the tree. */ - virtual void t8_element_reference_coords (const t8_element_t *elem, - const double *ref_coords, - const void *user_data, - double *out_coords) + virtual void t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, + double *out_coords) const; /** Construct a transition cell of type type */ @@ -417,7 +413,7 @@ public: t8_element * elem); /** Get the subelement id of elem */ - virtual int t8_element_get_subelement_id (const t8_element * elem); + virtual int t8_element_get_subelement_id (const t8_element * elem) const; /** Get the subelement id of the neighbor subelement of elem at face elem_face * that is a sibling of the subelement neigh. @@ -464,8 +460,42 @@ public: */ virtual void t8_element_vertex_reference_coords (const t8_element_t *t, int vertex, - double coords[]) - const; + double coords[]) const; + + /** Check if two elements are equal. + * \param [in] ts Implementation of a class scheme. + * \param [in] elem1 The first element. + * \param [in] elem2 The second element. + * \return 1 if the elements are equal, 0 if they are not equal + */ + virtual int + t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const; + + /** Fills an element with the root element. + * \param [in,out] elem The element to be filled with root. + */ + void + t8_element_root (t8_element_t *elem) const; + + /** Initialize an array of allocated quads/subelements. + * \param [in] length The number of hex to be initialized. + * \param [in,out] elems On input an array of \b length many allocated + * elements. + * \param [in] called_new True if the elements in \a elem were created by a call + * to \ref t8_element_new. False if no element in \a elem + * was created in this way. The case that only some elements + * were created by \ref t8_element_new should never occur. + * \note In debugging mode, an element that was passed to \ref t8_element_init + * must pass \ref t8_element_is_valid. + * \note If an element was created by \ref t8_element_new then \ref t8_element_init + * may not be called for it. Thus, \ref t8_element_new should initialize an element + * in the same way as a call to \ref t8_element_init would. + * Thus, if \a called_new is true this function should usually do nothing. + * \see t8_element_new + * \see t8_element_is_valid + */ + virtual void + t8_element_init (int length, t8_element_t *elem) const; #ifdef T8_ENABLE_DEBUG /** TODO: this should be the new element_print_element funciton */ @@ -473,6 +503,17 @@ public: /** Query whether an element is valid */ virtual int t8_element_is_valid (const t8_element_t *t) const; + + /** + * Print a given element. For a example for a triangle print the coordinates + * and the level of the triangle. This function is only available in the + * debugging configuration. + * + * \param [in] elem The element to print + */ + virtual void + t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const; + #endif protected: @@ -531,6 +572,30 @@ protected: void t8_element_reset_subelement_values (t8_element_t *elem) const; + virtual void + t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, void *send_buffer, int buffer_size, + int *position, sc_MPI_Comm comm) const; + + /** Determine an upper bound for the size of the packed message of \b count elements + * \param [in] count Number of elements to pack + * \param [in] comm MPI Communicator + * \param [out] pack_size upper bound on the message size + */ + virtual void + t8_element_MPI_Pack_size (const unsigned int count, sc_MPI_Comm comm, int *pack_size) const; + + /** Unpack multiple elements from contiguous memory that was received via MPI. + * \param [in] recvbuf Buffer from which to unpack the elements + * \param [in] buffer_size size of the buffer (in order to check that we don't access out of range) + * \param [in, out] position the position of the first byte that is not already packed + * \param [in] elements Array of initialised elements that is to be filled from the message + * \param [in] count Number of elements to unpack + * \param [in] comm MPI Communicator + */ + virtual void + t8_element_MPI_Unpack (void *recvbuf, const int buffer_size, int *position, t8_element_t **elements, + const unsigned int count, sc_MPI_Comm comm) const; + #ifdef T8_ENABLE_DEBUG /** Query whether an elements subelement values are valid * \param [in] source A element diff --git a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx index 72973f9361..2fb433ede3 100644 --- a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx @@ -35,7 +35,7 @@ enum T8_TRANSITION_REFINE_IDENTIFIER { T8_TRANSITION_CONFORMAL_ZERO_REFINE_FUNCTION = 0, T8_TRANSITION_CONFORMAL_QUAD_REFINE_FUNCTION, - T8_TRANSITION_CONFORMAL_HEX_REFINE_FUNCTION, + T8_TRANSITION_CONFORMAL_HEX_REFINE_FUNCTION }; T8_EXTERN_C_BEGIN (); From 9209aef04c409fdd8f43d7ee2b16daf5d941d5d3 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 7 May 2024 12:27:35 +0200 Subject: [PATCH 09/55] Fixed typos --- .../transition/t8_transition_basic_hex.cxx | 10 +- .../transition/t8_transition_global_hex.cxx | 2 +- src/t8_forest/t8_forest_adapt.cxx | 4 +- src/t8_forest/t8_forest_transition.cxx | 8 +- src/t8_forest/t8_forest_transition.h | 2 +- .../t8_transition_conformal_hex_cxx.cxx | 148 +++++------------- .../t8_transition/t8_transition_cxx.hxx | 2 +- 7 files changed, 57 insertions(+), 119 deletions(-) diff --git a/example/transition/t8_transition_basic_hex.cxx b/example/transition/t8_transition_basic_hex.cxx index f673ee5285..00d299b342 100644 --- a/example/transition/t8_transition_basic_hex.cxx +++ b/example/transition/t8_transition_basic_hex.cxx @@ -27,7 +27,7 @@ * * The geometry (coarse mesh) is again a cube, this time modelled with * 6 tetrahedra, 6 prisms and 4 cubes. - * We refine an element if its midpoint is whithin a sphere of given radius + * We refine an element if its midpoint is within a sphere of given radius * around the point (0.5, 0.5, 1) and we coarsen outside of a given radius. * We will use non-recursive refinement, that means that the refinement level * of any element will change by at most +-1. @@ -122,7 +122,7 @@ t8_test_hex_local (t8_element_t *hex_element, class_scheme->t8_element_shape (children[child_id]); num_vertices = t8_eclass_num_vertices[shape]; - t8_debugf ("Num verticies %i \n", num_vertices); + t8_debugf ("Num vertices %i \n", num_vertices); T8_ASSERT (num_vertices == class_scheme->t8_element_num_corners (children[child_id])); @@ -149,7 +149,7 @@ t8_test_hex_local (t8_element_t *hex_element, T8_FREE (children); t8_debugf - ("~~~~~~~~~~ The t8_test_hex_local function finshed successful ~~~~~~~~~~\n"); + ("~~~~~~~~~~ The t8_test_hex_local function finished successful ~~~~~~~~~~\n"); } @@ -176,7 +176,7 @@ t8_transition_local (t8_eclass_t eclass) class_scheme->t8_element_set_linear_id (hex_element, 0, 0); T8_ASSERT (class_scheme->t8_element_is_valid (hex_element)); - /* First, validate some element funcitons for this hex element */ + /* First, validate some element functions for this hex element */ t8_test_hex_local (hex_element, class_scheme); /* Make checks for all transition types */ @@ -256,7 +256,7 @@ t8_transition_local (t8_eclass_t eclass) t8_scheme_cxx_unref (&ts); t8_debugf - ("~~~~~~~~~~ The t8_transition_local function finshed successful ~~~~~~~~~~\n"); + ("~~~~~~~~~~ The t8_transition_local function finished successful ~~~~~~~~~~\n"); } /* end of t8_transition_local */ diff --git a/example/transition/t8_transition_global_hex.cxx b/example/transition/t8_transition_global_hex.cxx index 6125b7c38c..046b9ea8a2 100644 --- a/example/transition/t8_transition_global_hex.cxx +++ b/example/transition/t8_transition_global_hex.cxx @@ -22,7 +22,7 @@ /* Description: * This is the example file for refinement with transitioning. In this testcase, we are able to - * (i) refine a mesh according to some refinement criterion and use transiton cells to make the mesh conformal + * (i) refine a mesh according to some refinement criterion and use transition cells to make the mesh conformal * (ii) use multiple adaptation steps in which the refinement criterion changes (e.g. the geometry) * (iii) decide, whether we want to check the LFN function for each mesh * (iv) decide, whether we want to get statistics printed out, regarding # of elements in the meshes and runtime infos of the several functions or other debugging information diff --git a/src/t8_forest/t8_forest_adapt.cxx b/src/t8_forest/t8_forest_adapt.cxx index d8b3b1312e..bcbe5701c9 100644 --- a/src/t8_forest/t8_forest_adapt.cxx +++ b/src/t8_forest/t8_forest_adapt.cxx @@ -554,7 +554,7 @@ t8_forest_adapt (t8_forest_t forest) * 0 if the element should remain as is * -1 if we passed a family and it should get coarsened * -2 if the element should be removed. - * >1 if the element should be refined into a transtion cell + * >1 if the element should be refined into a transition cell */ refine = forest->set_adapt_fn (forest, forest->set_from, ltree_id, el_considered, tscheme, is_family, num_elements_to_adapt_callback, elements_from); @@ -605,7 +605,7 @@ t8_forest_adapt (t8_forest_t forest) else if (refine > 1) { /* refinement into transition cell */ - /* determing the number of subelements of the given type for memory allocation */ + /* determine the number of subelements of the given type for memory allocation */ num_subelements = tscheme->t8_element_get_number_of_subelements (refine - 1); diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx index 3c41a4b497..3ae008a79d 100644 --- a/src/t8_forest/t8_forest_transition.cxx +++ b/src/t8_forest/t8_forest_transition.cxx @@ -66,7 +66,7 @@ t8_forest_transition_conformal_quad (t8_forest_t forest, num_faces = ts->t8_element_num_faces (element); /* We use a binary encoding (depending on the face enumeration), to determine which subelement type to use. - * Every face has a flag parameter, wich is set to 1, if there is a neighbor with a higher level + * Every face has a flag parameter, which is set to 1, if there is a neighbor with a higher level * and to 0, if the level of the neighbor is at most the level of the element. * * f0 1 @@ -108,7 +108,7 @@ t8_forest_transition_conformal_quad (t8_forest_t forest, if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, face_neighbor[0], neigh_scheme)) { - /* Compute transition type as the decimal represenation of the binary concatenation */ + /* Compute transition type as the decimal representation of the binary concatenation */ transition_type += 1 << ((num_faces - 1) - iface); } } @@ -155,7 +155,7 @@ t8_forest_transition_conformal_hex (t8_forest_t forest, /* TODO: Update this comment to HEX. */ /* We use a binary encoding (depending on the face enumeration), to determine which subelement type to use. - * Every face has a flag parameter, wich is set to 1, if there is a neighbor with a higher level + * Every face has a flag parameter, which is set to 1, if there is a neighbor with a higher level * and to 0, if the level of the neighbor is at most the level of the element. * * f0 1 @@ -199,7 +199,7 @@ t8_forest_transition_conformal_hex (t8_forest_t forest, if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, face_neighbor[0], neigh_scheme)) { - /* Compute transition type as the decimal represenation of the binary concatenation */ + /* Compute transition type as the decimal representation of the binary concatenation */ transition_type += 1 << ((num_faces - 1) - iface); } } diff --git a/src/t8_forest/t8_forest_transition.h b/src/t8_forest/t8_forest_transition.h index 8c8a2b4713..023c113ec1 100644 --- a/src/t8_forest/t8_forest_transition.h +++ b/src/t8_forest/t8_forest_transition.h @@ -37,7 +37,7 @@ T8_EXTERN_C_BEGIN (); /* In this function, use a binary encoding (depending on the face enumeration), to determine which subelement type to use. - * Every face has a flag parameter, wich is set to 1, if there is a neighbour with a higher level + * Every face has a flag parameter, which is set to 1, if there is a neighbour with a higher level * and to 0, if the level of the neighbour is at most the level of the element. * * f0 1 diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 4c4f706b6d..39c87aafb6 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -77,7 +77,7 @@ const int subelement_face_dual[6][5] = { * location[0] = 5 -> parents dual face = 4 */ const int subelement_location_to_parent_dual_face[6] = { 1, 0, 3, 2, 5, 4 }; -/* Connectivity of a subelements location within a transition cell (only if the subelements are not splitted) +/* Connectivity of a subelements location within a transition cell (only if the subelements are not split) * --> gets subelement_duals */ const int subelement_face_to_dual_subelement[6][5] = { @@ -307,8 +307,6 @@ t8_subelement_scheme_hex_c::t8_element_num_siblings (const t8_element_t * //no hanging nodes if (phex_w_sub->transition_type == 0){ - //eigentlich normale funktion t8_element_num_siblings - //könnte auch 2hoch dim returnen return P8EST_CHILDREN; } @@ -320,7 +318,6 @@ t8_subelement_scheme_hex_c::t8_element_num_siblings (const t8_element_t * // binary shift << 1 Left-shift, d.h. *2¹ // Right shift >> 1 Right-shift, d.h. *2⁻¹ - // & (bitwise AND operator, num_hanging_faces wird nur erhöht, wenn mind. ein bit von transition_type != 0 ist. ) num_hanging_faces += (phex_w_sub->transition_type & (1 << iface)) >> iface; } @@ -342,7 +339,6 @@ t8_subelement_scheme_hex_c::t8_element_num_face_children (const t8_element_t } -//Wenn elements transition cell, dann immer alle seiten bis auf die Grundseite (f4) int t8_subelement_scheme_hex_c::t8_element_neighbor_is_sibling (const t8_element_t @@ -375,7 +371,7 @@ t8_subelement_scheme_hex_c::t8_element_get_num_sibling_neighbors_at_face (const T8_ASSERT (face == 0 || face == 1 || face == 2 || face == 3); int location[3] = { }; - //( location[0] = face_number of transition cell, location[1] = if splitted or not ( 1 = splitted ), location[2] = sub_id + //( location[0] = face_number of transition cell, location[1] = if split or not ( 1 = split ), location[2] = sub_id t8_element_get_location_of_subelement (elem, location); int split = location[1]; int hex_face = location[0]; @@ -504,11 +500,11 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h //iterator variable int iter; - //Get informations about the location of the subelement. + //Get information about the location of the subelement. int num_siblings = t8_element_num_siblings (elem); int location[3] = { }; - //( location[0] = face_number of transition cell, location[1] = if splitted or not ( 1 = splitted ), location[2] = sub_id + // location[0] = face_number of transition cell, location[1] = if split or not ( 1 = split ), location[2] = sub_id t8_element_get_location_of_subelement (elem, location); //Create a temporary variable to store the possible subelement_id of the neighbor @@ -521,25 +517,23 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h int hlp; /* There are 4 cases that can happen: - * 1. The subelement itself is not splitted, and its face neighbor is also not splitted. - * 2. The subelement itself is not splitted, but its face neighbor is splitted. (Two face neighbors) - * 3. The subelement itself is splitted, but its face neighbor is not splitted. - * 4. The subelement itself is splitted, and its face neighbor is also splitted. + * 1. The subelement itself is not split, and its face neighbor is also not split. + * 2. The subelement itself is not split, but its face neighbor is split. (Two face neighbors) + * 3. The subelement itself is split, but its face neighbor is not split. + * 4. The subelement itself is split, and its face neighbor is also split. */ neigh_face[0] = subelement_face_dual[location[0]][face]; - //First check if (the own) face is splitted. - if(location[1] == 0){ //Not splitted + //First check if (the own) face is split. + if(location[1] == 0){ //Not split //get hex_face_number of the face_neighbored subelement // neigh_hex_face is only correct, if the neighbor lies not at the same hex face. - neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; - // t8_productionf("das ist neigh hex face (not splitted) : %i\n", neigh_hex_face); - - /*Check if the dual subelement is splitted. If it's splitted,the element has two neighbors + neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; + /*Check if the dual subelement is split. If it's split,the element has two neighbors * as siblings (case 2). Then we always take the left, front or down (in this order) subelement (the subelement with the lower sub - * element ID). If the transition type is = 1 at the hex_face, it's splitted.*/ + * element ID). If the transition type is = 1 at the hex_face, it's split.*/ //-----------------------------CASE 1-------------------------------------------------------- @@ -551,7 +545,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h int i = (int) pow(2,5 - neigh_hex_face); - if((transition_type & i) == 0){ //neighbor not splitted + if((transition_type & i) == 0){ //neighbor not split for(iter = 0 ; iter <= neigh_hex_face ; iter++){ @@ -571,7 +565,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h } //-------------------------CASE 2-------------------------------------- - else { //neighbor is splitted. We have to return 2 subelements. + else { //neighbor is split. We have to return 2 subelements. amount_subelements = 0; int subelement_id_tmp2 = 0; // In here we store the second subelement ID in case 2 if elem has two neighbors /* For case 2 we need a second face neighbor */ @@ -627,7 +621,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h subelement_id_tmp = amount_subelements - 2; subelement_id_tmp2 = amount_subelements - 1; } - } //for hex_face 4 ist the "down" sub-ids + } //for hex_face 4 its the "down" sub-ids if (location[0] == 4){ subelement_id_tmp = amount_subelements - 4; subelement_id_tmp2 = amount_subelements - 3; @@ -649,7 +643,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h //-------------------------CASE 3-------------------------------------- else{ - //The own face is splitted + //The own face is split //get hex_face_number of the face_neighbored subelement //Condition that the neighbor lies not on the same hex face: hlp = 0; @@ -707,10 +701,10 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; if( (hlp == 0) && ((transition_type & (int) pow(2,5 - neigh_hex_face)) == 0)){ - if((transition_type & (int) pow(2,5 - neigh_hex_face)) == 0){ //neighbor not splitted + if((transition_type & (int) pow(2,5 - neigh_hex_face)) == 0){ //neighbor not split - //it's not possible, that the neighbor lies on the same hex face here, because the own face is splitted here and if the neighbor would lie on the same face - //its face would obviously be splitted too. + //it's not possible, that the neighbor lies on the same hex face here, because the own face is split here and if the neighbor would lie on the same face + //its face would obviously be split too. neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; //make rightshift until only the bits for the faces before our neighbors face are left. transition_type_tmp = transition_type >> (5 - neigh_hex_face); @@ -1211,10 +1205,6 @@ t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t * hex element of the given subelement. Since the last descendant is not meant to be * a subelement, we reset the corresponding subelement values. */ t8_element_reset_subelement_values (desc); - - //t8_global_productionf("das ist sub id nach zurück setzten %i\n", phex_w_sub_desc->subelement_id); - - // SC_ABORT_NOT_REACHED(); } void @@ -1775,14 +1765,10 @@ t8_subelement_scheme_hex_c::t8_element_face_neighbor_inside (const const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; p8est_quadrant_t *n = &phex_w_sub_neigh->p8q; - // t8_debugf(" n: Koordinate x: %i, y %i, z %i, q Koordinaten: x %i, y %i, z %i \n", n->x, n->y, n->z, q->x, q->y, q->z); - // t8_debugf(" ist elem subelement? %i\n",t8_element_is_subelement (elem)); - // /* In case of a subelement one should construct the face neighbor of the face-corresponding child quadrant // * of the subelements parent quadrant. Therefore we might want to adjust the level and adapt the // * anchor node. */ if (t8_element_is_subelement (elem)) { /* if elem is a subelement */ - // t8_debugf(" Subelement: %i\n",t8_element_is_subelement (elem)); T8_ASSERT (0 <= face && face < T8_HEX_SUBELEMENT_FACES); int location[3] = { }; t8_element_get_location_of_subelement (elem, location); @@ -1818,7 +1804,6 @@ int location[3] = { }; int split = location[1]; int subelement_type = location[2]; - // t8_debugf(" Das ist location array location[0] = %i, location[2] = %i, location[2]=%i\n", location[0], location[1], location[2]); /* we need to take into account whether the subelement is split or not */ if (split) { /* split */ /* increase the level by one */ @@ -1906,11 +1891,6 @@ int location[3] = { }; } *neigh_face = subelement_location_to_parent_dual_face[location[0]]; - // t8_debugf(" Location array von mir: location[0] = %i, location[1]= %i, location[2]= %i \n", location[0], location[1], location[2]); - // t8_debugf(" n: Koordinate x: %i, y %i, z %i, q Koordinaten: x %i, y %i, z %i \n", n->x, n->y, n->z, q->x, q->y, q->z); - // t8_debugf(" Nachbar face %i\n", *neigh_face); - // t8_debugf(" Level von Nachbar %i\n", n->level); - // t8_debugf(" Level von mir %i\n", q->level); } @@ -1919,8 +1899,6 @@ int location[3] = { }; /* Compute the face neighbor */ p8est_quadrant_face_neighbor (q, face, n); - // t8_debugf(" n: Koordinate x: %i, y %i, z %i, q Koordinaten: x %i, y %i, z %i \n", n->x, n->y, n->z, q->x, q->y, q->z); - // t8_debugf("face %i\n", face); /* Compute the face of q that coincides with face. * face neigh_face face neigh_face * 0 1 4 5 @@ -1928,54 +1906,15 @@ int location[3] = { }; * 2 3 * 3 2 */ - //t8_element_reset_subelement_values (neigh); + T8_ASSERT (neigh_face != NULL); *neigh_face = p8est_face_dual[face]; - // int sub_id = t8_element_get_subelement_id(neigh); - // t8_debugf( "neigh face: %i\n", *neigh_face); - /* return true if neigh is inside the root */ - // T8_ASSERT(p8est_quadrant_is_inside_root (n)); - - - //return p8est_quadrant_is_inside_root (n); - - // t8_debugf(" n: Koordinate x: %i, y %i, z %i, q Koordinaten: x %i, y %i, z %i \n", n->x, n->y, n->z, q->x, q->y, q->z); - // t8_debugf(" Nachbar face %i\n", *neigh_face); - // t8_debugf(" Level von Nachbar %i\n", n->level); - // t8_debugf(" Level von mir %i\n", q->level); - // } t8_element_reset_subelement_values (neigh); - //t8_element_reset_subelement_values (neigh); - - // T8_QUAD_SET_TDIM (n, 2); - - /* In the following we set the dual faces of our element at the given face. */ - // if (t8_element_is_subelement (elem)) { - // if (face == 4) { - // /* return dual face with respect to neighboring hex element */ - // int location[3] = { }; - // t8_element_get_location_of_subelement (elem, location); - // *neigh_face = subelement_location_to_parent_dual_face[location[0]]; - // } - // else { - // T8_ASSERT (face != 4); - // int location[3] = { }; - // t8_element_get_location_of_subelement (elem, location); - // /* return dual face with resprect to neighboring sibling subelement (note that the constructed neigh is NOT a subelement but the parent hex) */ - // /* Compute the face number as seen from q. - // * 0 -> 2 2 -> 0 - // */ - // *neigh_face = subelement_face_dual[location[0]][face]; - // } - // } - - if ( p8est_quadrant_is_inside_root(n) == 0){ - // t8_debugf("aus function: is inside root: %i\n", p8est_quadrant_is_inside_root (n)); } @@ -2125,7 +2064,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const break; case 0: - if(split == 0){ //not splitted + if(split == 0){ //not split //for face numbers 0,2 and 4 nothing happens if(face_number == 1){ coords[0] += len; @@ -2137,7 +2076,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const coords[2] += len; } } -/* ----------- face 0 + 1 (splitted) --------------------*/ +/* ----------- face 0 + 1 (split) --------------------*/ else{ if((face_number == 0) || (face_number == 1)){ if((sub_face_id & 1)!= 0){ // up @@ -2151,7 +2090,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const coords[0] += len; } } -/* ----------- face 2 + 3 (splitted) --------------------*/ +/* ----------- face 2 + 3 (split) --------------------*/ if((face_number == 2) || (face_number == 3)){ if((sub_face_id & 1) != 0){ // up coords[2] += (len / 2); @@ -2163,7 +2102,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const coords[1] += len; } } -/* ----------- face 4 + 5 (splitted) --------------------*/ +/* ----------- face 4 + 5 (split) --------------------*/ if((face_number == 4) || (face_number == 5)){ if((sub_face_id & 2) != 0){ // back coords[1] += len / 2; @@ -2191,7 +2130,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const } } -/* ----------- face 0 + 1 (splitted) --------------------*/ +/* ----------- face 0 + 1 (split) --------------------*/ else{ if((face_number == 0) || (face_number == 1)){ if((sub_face_id & 1) != 0){ // up @@ -2209,7 +2148,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const coords[0] += len; } } -/* ----------- face 2 + 3 (splitted) --------------------*/ +/* ----------- face 2 + 3 (split) --------------------*/ if((face_number == 2) || (face_number == 3)){ if((sub_face_id & 1) != 0){ // up coords[2] += len / 2; @@ -2225,7 +2164,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const } } -/* ----------- face 4 + 5 (splitted) --------------------*/ +/* ----------- face 4 + 5 (split) --------------------*/ if((face_number == 4) || (face_number == 5)){ if((sub_face_id & 2) != 0){ // back coords[1] += (len / 2); @@ -2254,7 +2193,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const coords[1] += len; } } -/* ----------- face 0 + 1 (splitted) --------------------*/ +/* ----------- face 0 + 1 (split) --------------------*/ else{ if((face_number == 0) || (face_number == 1)){ if((sub_face_id & 2) != 0){ // back @@ -2271,7 +2210,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const } } -/* ----------- face 2 + 3 (splitted) --------------------*/ +/* ----------- face 2 + 3 (split) --------------------*/ if((face_number == 2) || (face_number == 3)){ if((sub_face_id & 1) != 0){ // up coords[2] += len; @@ -2286,7 +2225,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const coords[1] += len; } } -/* ----------- face 4 + 5 (splitted) --------------------*/ +/* ----------- face 4 + 5 (split) --------------------*/ if((face_number == 4) || (face_number == 5)){ if((sub_face_id & 2) != 0){ // back @@ -2317,7 +2256,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const coords[0] += len; } } - /* ----------- face 0 + 1 (splitted) --------------------*/ + /* ----------- face 0 + 1 (split) --------------------*/ else{ if((face_number == 0) || (face_number == 1)){ if((sub_face_id & 2) != 0){ // back @@ -2336,7 +2275,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const coords[0] += len; } } -/* ----------- face 2 + 3 (splitted) --------------------*/ +/* ----------- face 2 + 3 (split) --------------------*/ if((face_number == 2) || (face_number == 3)){ if((sub_face_id & 1) != 0){ // up coords[2] += len; @@ -2355,7 +2294,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const } } -/* ----------- face 4 + 5 (splitted) --------------------*/ +/* ----------- face 4 + 5 (split) --------------------*/ if((face_number == 4) || (face_number == 5)){ if((sub_face_id & 2) != 0){ // back @@ -2487,7 +2426,7 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const * ii) whether this face is split in half (values: {0,1}). * iii) if the subelement is the first or second subelement at the face (values: {0,1}). * - * These informations are then saved in the location array which will be used by the element_vertex function, + * These information are then saved in the location array which will be used by the element_vertex function, * to automatically determine the vertex coordinates of the given subelement. * * The location array for the above example would be {1,1,1} (upper face, split = true, second subelement at the upper face). */ @@ -2501,7 +2440,7 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const /* We need an array with 6 elements to store all subelement types of the hex scheme from 1 to 63 ({0, 0, 0, 0, 0, 1} to {1, 1, 1, 1, 1, 1}) */ for (iface = 0; iface < P8EST_FACES; iface++) { binary_array[(P8EST_FACES - 1) - iface] = (type & (1 << iface)) >> iface; - } /* we now got a binary represenation of the transition type, bitwise stored in an array */ + } /* we now got a binary representation of the transition type, bitwise stored in an array */ int binary_array_temp[P8EST_FACES] = { }; @@ -2548,7 +2487,6 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const } } -//t8_productionf("Das ist cum neigh_array[face_number %i]= %i \n", face_number,cum_neigh_array[iface + 1]); /* make sure that a face_number has been found */ T8_ASSERT (face_number >= 0); @@ -2719,7 +2657,7 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell /* Below are the cases in which the neighbor is no sibling. * The idea is to fill a location array with the desired properties of the real neighbor. - * Togehter with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ + * Together with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ /* get the location of elem */ int location_elem[3] = { }; /* {face, is_split, number of subelement at face} */ @@ -2753,16 +2691,16 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; /* the pseudo_neigh transition cell has a lower level than the elem transition cell, so the second entry - of the location array has to be 1 (= splitted) */ + of the location array has to be 1 (= split) */ location_neigh[1] = 1; /* split */ /* First, check left/right face of transition cell */ if ((location_elem[0] == 0) || (location_elem[0] == 1)) { - //If the y-coordinates differ, we can derivate that the neighbor lies in the back. + //If the y-coordinates differ, we can deviate that the neighbor lies in the back. //Thus, we need to increment the subelement_type by 2^1 if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back*/ } - //Analogously: if the z-coordinates differ, we can derivate that the neighbor lies up. + //Analogously: if the z-coordinates differ, we can deviate that the neighbor lies up. //Thus, we need to increment the subelement_type by 2^0 if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ @@ -2787,7 +2725,7 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell } } } - /* the pseudo_neigh transition cell has not a lower level than the elem transition cell, so it's face is not splitted */ + /* the pseudo_neigh transition cell has not a lower level than the elem transition cell, so it's face is not split */ else { location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; location_neigh[1] = 0; /* not split */ @@ -2857,7 +2795,7 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell } /* the pseudo_neigh transition cell has the same level as elem * Note that the level of the transition cell can not be higher as the level of elem in this case, - * since elem would then be a subelement in a transtion cell. */ + * since elem would then be a subelement in a transition cell. */ if (phex_w_sub_pseudo_neigh->p8q.level == phex_w_sub_elem->p8q.level) { location_neigh[1] = 0; /* not split */ location_neigh[2] = 0; /* default value */ @@ -2988,7 +2926,7 @@ t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem) con int elem_count; for (elem_count = 0; elem_count < length; elem_count++) { - /* initalize subelement parameters */ + /* initialize subelement parameters */ phex_w_sub[elem_count].transition_type = 0; phex_w_sub[elem_count].subelement_id = 0; diff --git a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx index 2fb433ede3..27bd257485 100644 --- a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx @@ -30,7 +30,7 @@ #include -/* This is the unique identifier for the transition fucntion. */ +/* This is the unique identifier for the transition function. */ enum T8_TRANSITION_REFINE_IDENTIFIER { T8_TRANSITION_CONFORMAL_ZERO_REFINE_FUNCTION = 0, From 1cc4970e5f98f30039c67c3e93f003e574e2c9b2 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 7 May 2024 12:28:03 +0200 Subject: [PATCH 10/55] Fixed typos --- .../t8_transition_conformal_hex_cxx.hxx | 21 +++++++++---------- .../t8_transition_conformal_quad_cxx.cxx | 14 ++++++------- .../t8_transition_conformal_quad_cxx.hxx | 16 +++++++------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index e977959548..23754373a3 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -79,10 +79,9 @@ typedef t8_hex_with_subelements t8_phex_sub_t; /** define some subelement related constants */ #define T8_SUB_HEX_MAX_TRANSITION_TYPE 63 -//Transition mit hängenden Kanten (nur Pyramiden) also höchstens vier Parymiden pro Seite. Ein Würfel hat sechs Seiten also maximal -// 6*4 = 24 subelement id's +//A hexahedron has six faces that results in 6*4 = 24 possible subelement id's #define T8_SUB_HEX_MAX_SUBELEMENT_ID 24 -//Pyramide hat 5 Seiten +// A pyramid has 5 faces #define T8_HEX_SUBELEMENT_FACES 5 #define T8_HEX_TRANSITION_IS_IMPLEMENTED 1 @@ -110,7 +109,7 @@ typedef t8_hex_with_subelements t8_phex_sub_t; do { T8_ASSERT ((dim) == 2 || (dim) == 3); \ (quad)->pad8 = (int8_t) (dim); } while (0) -/** Set the direction of the third demension. */ +/** Set the direction of the third dimension. */ #define T8_QUAD_SET_TNORMAL(quad,normal) \ do { T8_ASSERT ((normal) >= 0 && (normal) < 3); \ (quad)->pad16 = (int16_t) (normal); } while (0) @@ -158,8 +157,8 @@ public: virtual void t8_element_copy (const t8_element_t *source, t8_element_t *dest) const; -/** Compare to elements. returns negativ if elem1 < elem2, zero if elem1 equals elem2 - * and positiv if elem1 > elem2. +/** Compare to elements. returns negative if elem1 < elem2, zero if elem1 equals elem2 + * and positive if elem1 > elem2. * If elem2 is a copy of elem1 then the elements are equal. * If both elements are sibling subelements, return 0 if they are identical (same sub_id) and 1 otherwise. */ @@ -411,7 +410,7 @@ public: transition_type) const; -/** Test wheter a given element is a subelement or not */ +/** Test whether a given element is a subelement or not */ virtual int t8_element_is_subelement (const t8_element * elem) const; @@ -471,7 +470,7 @@ public: const; #ifdef T8_ENABLE_DEBUG -/** TODO: this should be the new element_print_element funciton */ +/** TODO: this should be the new element_print_element function */ virtual void t8_element_debug_print (const t8_element_t *elem) const; /** Query whether an element is valid */ @@ -486,7 +485,7 @@ protected: * subelement. * Note that subelements can have another number of vertices compared to the used * eclass scheme. For example, subelements that remove hanging nodes from the HEX scheme - * are triangles with 3 instead of 4 verticies. + * are triangles with 3 instead of 4 vertices. */ void t8_element_vertex_coords_of_subelement (const t8_element_t *t, @@ -506,7 +505,7 @@ protected: * sub_face_id: if there is a hanging node at the face, it is important to know if the given * subelement is the first or the second subelement at this face * (value 0 if it is the first and 1 if it is the second) - * The information in the location can be used to automatically determine the verticies of any subelement. + * The information in the location can be used to automatically determine the vertices of any subelement. * Since this function is only used to determine the vertices of subelements, it can be declared as a private/protected function. */ void t8_element_get_location_of_subelement (const @@ -529,7 +528,7 @@ protected: const; /** This function resets the subelement values of an element to the default value -1. - * \param [in,out] elem A valid element, whose subelement values have been resetted. + * \param [in,out] elem A valid element, whose subelement values have been reset. */ void t8_element_reset_subelement_values (t8_element_t *elem) const; diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index c35da4d0cf..3f3b34a3d8 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -787,7 +787,7 @@ t8_subelement_scheme_quad_c::t8_element_children_at_face (const t8_element_t * * x - - x - - x This picture shows a refined quadrant * | | | with child_ids and the label for the faces. - * | 2 | 3 | For examle for face 2 (bottom face) we see + * | 2 | 3 | For example for face 2 (bottom face) we see * 0 x - - x - - x 1 first_child = 0 and second_child = 1. * | | | * | 0 | 1 | @@ -1618,7 +1618,7 @@ t8_subelement_scheme_quad_c::t8_element_vertex_coords_of_subelement (const coords[1] = q1->y; /* using the location data to determine vertex coordinates */ - if (vertex == 0) { /* vertex 0 (the first vertex allways equals the center of the element) */ + if (vertex == 0) { /* vertex 0 (the first vertex always equals the center of the element) */ coords[0] += len / 2; coords[1] += len / 2; } /* end of vertex == 0 */ @@ -1794,7 +1794,7 @@ t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const * ii) whether this face is split in half (values: {0,1}). * iii) if the subelement is the first or second subelement at the face (values: {0,1}). * - * These informations are then saved in the location array which will be used by the element_vertex function, + * These information are then saved in the location array which will be used by the element_vertex function, * to automatically determine the vertex coordinates of the given subelement. * * The location array for the above example would be {1,1,1} (upper face, split = true, second subelement at the upper face). */ @@ -1807,7 +1807,7 @@ t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const for (iface = 0; iface < P4EST_FACES; iface++) { /* need an array with 4 elements to store all subelement types of the quad scheme from 1 to 15 ({0,0,0,1} to {1,1,1,1}) */ binary_array[(P4EST_FACES - 1) - iface] = (type & (1 << iface)) >> iface; - } /* we now got a binary represenation of the transition type, bitwise stored in an array */ + } /* we now got a binary representation of the transition type, bitwise stored in an array */ /* 2) rearrange the binary representation to be in clockwise order */ int binary_array_temp[P4EST_FACES] = { }; @@ -2015,7 +2015,7 @@ t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell } /* Below are the cases in which the neighbor can not be identified as simple as above. * The idea is to fill a location array with the desired properties of the real neighbor. - * Togehter with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ + * Together with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ if (pquad_w_sub_elem->transition_type != 0 && elem_face == 1) { /* In this case, we have the following situation: @@ -2202,7 +2202,7 @@ t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell } /* the pseudo_neigh tranaition cell has the same level as elem * Note that the level of the trnasition cell can not be higher as the level of elem in this case, - * since elem would then be a subelement in a transtion cell. */ + * since elem would then be a subelement in a transition cell. */ if (pquad_w_sub_pseudo_neigh->p4q.level == pquad_w_sub_elem->p4q.level) { if (elem_face == 0) { /* left face */ location_neigh[0] = 2; /* face */ @@ -2345,7 +2345,7 @@ t8_subelement_scheme_quad_c::t8_element_init (int length, t8_element_t *elem) co int elem_count; for (elem_count = 0; elem_count < length; elem_count++) { - /* initalize subelement parameters */ + /* initialize subelement parameters */ pquad_w_sub[elem_count].transition_type = 0; pquad_w_sub[elem_count].subelement_id = 0; diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index 77fa7c432b..c81a0edb40 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -107,7 +107,7 @@ typedef t8_quad_with_subelements t8_pquad_t; do { T8_ASSERT ((dim) == 2 || (dim) == 3); \ (quad)->pad8 = (int8_t) (dim); } while (0) -/** Set the direction of the third demension. */ +/** Set the direction of the third dimension. */ #define T8_QUAD_SET_TNORMAL(quad,normal) \ do { T8_ASSERT ((normal) >= 0 && (normal) < 3); \ (quad)->pad16 = (int16_t) (normal); } while (0) @@ -150,8 +150,8 @@ public: virtual void t8_element_copy (const t8_element_t *source, t8_element_t *dest) const; -/** Compare to elements. returns negativ if elem1 < elem2, zero if elem1 equals elem2 - * and positiv if elem1 > elem2. +/** Compare to elements. returns negative eif elem1 < elem2, zero if elem1 equals elem2 + * and positive if elem1 > elem2. * If elem2 is a copy of elem1 then the elements are equal. * If both elements are sibling subelements, return 0 if they are identical (same sub_id) and 1 otherwise. */ @@ -404,7 +404,7 @@ public: transition_type) const; -/** Test wheter a given element is a subelement or not */ +/** Test whether a given element is a subelement or not */ virtual int t8_element_is_subelement (const t8_element * elem) const; @@ -498,7 +498,7 @@ public: t8_element_init (int length, t8_element_t *elem) const; #ifdef T8_ENABLE_DEBUG -/** TODO: this should be the new element_print_element funciton */ +/** TODO: this should be the new element_print_element function */ virtual void t8_element_debug_print (const t8_element_t *elem) const; /** Query whether an element is valid */ @@ -524,7 +524,7 @@ protected: * subelement. * Note that subelements can have another number of vertices compared to the used * eclass scheme. For example, subelements that remove hanging nodes from the quad scheme - * are triangles with 3 instead of 4 verticies. + * are triangles with 3 instead of 4 vertices. */ void t8_element_vertex_coords_of_subelement (const t8_element_t *t, @@ -544,7 +544,7 @@ protected: * sub_face_id: if there is a hanging node at the face, it is important to know if the given * subelement is the first or the second subelement at this face * (value 0 if it is the first and 1 if it is the second) - * The information in the location can be used to automatically determine the verticies of any subelement. + * The information in the location can be used to automatically determine the vertices of any subelement. * Since this function is only used to determine the vertices of subelements, it can be declared as a private/protected function. */ void t8_element_get_location_of_subelement (const @@ -567,7 +567,7 @@ protected: const; /** This function resets the subelement values of an element to the default value -1. - * \param [in,out] elem A valid element, whose subelement values have been resetted. + * \param [in,out] elem A valid element, whose subelement values have been reset. */ void t8_element_reset_subelement_values (t8_element_t *elem) const; From 49625bd89d367ea4bad2983187fc65bcd98f45ae Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 7 May 2024 14:29:14 +0200 Subject: [PATCH 11/55] Corrected warnings --- .../t8_transition_conformal_hex_cxx.cxx | 42 +++++-------------- .../t8_transition_conformal_hex_cxx.hxx | 9 +--- 2 files changed, 13 insertions(+), 38 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 39c87aafb6..98d222dfe3 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -364,8 +364,6 @@ t8_subelement_scheme_hex_c::t8_element_get_num_sibling_neighbors_at_face (const const t8_hex_with_subelements *hex_w_sub = (const t8_hex_with_subelements *) elem; - - const t8_element_t *elem2 = (const t8_element *) elem; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_subelement (elem)); T8_ASSERT (face == 0 || face == 1 || face == 2 || face == 3); @@ -501,8 +499,6 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h //iterator variable int iter; //Get information about the location of the subelement. - int - num_siblings = t8_element_num_siblings (elem); int location[3] = { }; // location[0] = face_number of transition cell, location[1] = if split or not ( 1 = split ), location[2] = sub_id t8_element_get_location_of_subelement (elem, location); @@ -512,7 +508,6 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h int transition_type_tmp = 0; int amount_subelements = 0; int transition_type = t8_element_get_transition_type(elem); - int subelement_id = t8_element_get_subelement_id(elem); int neigh_hex_face; int hlp; @@ -826,7 +821,7 @@ phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; neigh_face[0] = subelement_location_to_parent_dual_face[face]; phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; -if( hlp = 0 ){ //if the neighbor lies not on the same hex face as elem +if(hlp == 0){ //if the neighbor lies not on the same hex face as elem //get hex_face_number of the face_neighbored subelement neigh_face[0] = subelement_face_dual[location[0]][face]; @@ -934,7 +929,7 @@ if( hlp = 0 ){ //if the neighbor lies not on the same hex face as elem subelement_id_tmp = amount_subelements - 1; } } - if(location[2] & 1 == 0){//down + if((location[2] & 1) == 0){//down if(location[0] == 2){ // we are at hex_face 2 subelement_id_tmp = amount_subelements - 4; } @@ -955,15 +950,7 @@ if( hlp = 0 ){ //if the neighbor lies not on the same hex face as elem //same for face = 2 if(face == 3 || face == 2){ //We have to distinguish if the element is in the front or back. - if((location[2] & 4) == 1){//left - if(location[0] == 2){ // we are at hex_face 2 - subelement_id_tmp = amount_subelements - 4; - } - if(location[0] == 3){ - subelement_id_tmp = amount_subelements - 2; - } - } - else{//right + if((location[2] & 4) == 0){//right if(location[0] == 2){ // we are at hex_face 2 subelement_id_tmp = amount_subelements - 3; } @@ -971,6 +958,14 @@ if( hlp = 0 ){ //if the neighbor lies not on the same hex face as elem subelement_id_tmp = amount_subelements - 1; } } + else{//left + if(location[0] == 2){ // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 4; + } + if(location[0] == 3){ + subelement_id_tmp = amount_subelements - 2; + } + } } @@ -1211,16 +1206,6 @@ void t8_subelement_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2) const { - const t8_hex_with_subelements *phex_w_sub_elem1 = - (const t8_hex_with_subelements *) elem1; - t8_hex_with_subelements *phex_w_sub_elem2 = - (t8_hex_with_subelements *) elem2; - - const p8est_quadrant_t *q = &phex_w_sub_elem1->p8q; - p8est_quadrant_t *r = &phex_w_sub_elem2->p8q; - - t8_linearidx_t id; - /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem1)); @@ -2442,11 +2427,6 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const binary_array[(P8EST_FACES - 1) - iface] = (type & (1 << iface)) >> iface; } /* we now got a binary representation of the transition type, bitwise stored in an array */ - int binary_array_temp[P8EST_FACES] = { }; - - for (iface = 0; iface < P8EST_FACES; iface++) { /* copying the binary array */ - binary_array_temp[iface] = binary_array[iface]; - } /* 3) use the rearranged binary representation, and the sub_id to determine the location of the subelement and store these information in an array */ /* 3.1) location[0] -> the face_number, the subelement is adjacent to */ /* 3.2) location[1] -> if the face is split or not */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 23754373a3..f025eb58fe 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -88,7 +88,7 @@ typedef t8_hex_with_subelements t8_phex_sub_t; #define T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL 1 /** Return the toplevel dimension. */ -//#define T8_QUAD_GET_TDIM(quad) ((int) (quad)->pad8) +#define T8_QUAD_GET_TDIM(quad) ((int) (quad)->pad8) /** Return the direction of the third dimension. * This is only valid to call if the toplevel dimension is three. @@ -119,12 +119,11 @@ typedef t8_hex_with_subelements t8_phex_sub_t; do { (quad)->p.user_long = (long) (coord); } while (0) #if 0 -/** Provide an implementation for the HEXrilateral element class with subelements. */ +/** Provide an implementation for the hexahedral element class with subelements. */ t8_eclass_scheme_t *t8_subelement_scheme_new_hex (void); #endif -// Die Klasse t8_subelement_scheme_HEX_c erbt von der Klasse t8_default_scheme_common_c struct t8_subelement_scheme_hex_c:public t8_default_scheme_common_c { public: @@ -140,10 +139,6 @@ public: */ virtual void t8_element_new (int length, t8_element_t **elem) const; - // /** Initialize an array of allocated elements. */ - // virtual void t8_element_init (int length, t8_element_t *elem, - // int called_new) const; - /** Return the maximum level allowed for this element class. */ virtual int t8_element_maxlevel (void) const; From 17fb727cc1d467701615883c7d387c0ee33df170 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Mon, 13 May 2024 13:16:17 +0200 Subject: [PATCH 12/55] Added gtest folder schemes_transition, gtest plus small corrections --- src/t8_forest/t8_forest.c | 5 +- .../t8_transition_conformal_hex_cxx.cxx | 101 ++++++++++-------- .../t8_transition_conformal_hex_cxx.hxx | 2 +- test/Makefile.am | 11 ++ .../t8_gtest_child_parent_face.cxx | 83 ++++++++++++++ .../t8_gtest_dfs_base.hxx | 93 ++++++++++++++++ 6 files changed, 248 insertions(+), 47 deletions(-) create mode 100644 test/t8_schemes_transition/t8_gtest_child_parent_face.cxx create mode 100644 test/t8_schemes_transition/t8_gtest_dfs_base.hxx diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index e1d98b0040..196b19f717 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -290,7 +290,7 @@ t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, /* set the forests subelement flag, which is for example used by the LFN routine */ forest->set_subelements = 1; - forest->is_transitioned; + forest->is_transitioned = 1; } void @@ -542,9 +542,12 @@ t8_forest_commit (t8_forest_t forest) /* populate a new forest with tree and quadrant objects */ if (t8_forest_refines_irregular (forest) && forest->set_level > 0) { /* On root level we will also use the normal algorithm */ + t8_forest_populate_irregular (forest); } else { + t8_global_productionf("-----------regular-------------\n"); + t8_forest_populate (forest); } forest->global_num_trees = t8_cmesh_get_num_trees (forest->cmesh); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 98d222dfe3..ea66a7c578 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -157,8 +157,7 @@ t8_subelement_scheme_hex_c::t8_element_copy (const t8_element_t *source, *r = *q; t8_element_copy_subelement_values (source, dest); - //t8_element_copy(q,r); - // t8_element_copy_surround (q, r); + } int @@ -473,7 +472,9 @@ t8_subelement_scheme_hex_c::t8_element_child (const t8_element_t *elem, r->y = childid & 0x02 ? (q->y | shift) : q->y; r->z = childid & 0x04 ? (q->z | shift) : q->z; r->level = q->level + 1; - T8_ASSERT (p8est_quadrant_is_parent (q, r)); + if (q != r) { + T8_ASSERT (p8est_quadrant_is_parent (q, r)); + } } void @@ -2948,7 +2949,9 @@ else{ void t8_subelement_scheme_hex_c::t8_element_root (t8_element_t *elem) const{ - SC_ABORT_NOT_REACHED(); + p8est_quadrant_t *hex = (p8est_quadrant_t *) elem; + p8est_quadrant_set_morton (hex, 0, 0); + T8_ASSERT (p8est_quadrant_is_extended (hex)); } @@ -3023,47 +3026,50 @@ t8_subelement_scheme_hex_c::t8_element_to_string (const t8_element_t *elem, char } #endif -/* each hex is packed as x,y,z coordinates and the level */ +/* each hex is packed as x,y,z coordinates, the subelement ID, transition type and the level */ void t8_subelement_scheme_hex_c::t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, void *send_buffer, const int buffer_size, int *position, sc_MPI_Comm comm) const { - SC_ABORT_NOT_REACHED(); - // int mpiret; - // p8est_quadrant_t **quads = (p8est_quadrant_t **) elements; - // for (unsigned int ielem = 0; ielem < count; ielem++) { - // mpiret = sc_MPI_Pack (&(quads[ielem]->x), 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); - // SC_CHECK_MPI (mpiret); - // mpiret = sc_MPI_Pack (&quads[ielem]->y, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); - // SC_CHECK_MPI (mpiret); - // mpiret = sc_MPI_Pack (&quads[ielem]->z, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); - // SC_CHECK_MPI (mpiret); - // mpiret = sc_MPI_Pack (&quads[ielem]->level, 1, sc_MPI_INT8_T, send_buffer, buffer_size, position, comm); - // SC_CHECK_MPI (mpiret); - // } + int mpiret; + p8est_quadrant_t **quads = (p8est_quadrant_t **) elements; + t8_hex_with_subelements **quads_with_sub = (t8_hex_with_subelements **) elements; + for (unsigned int ielem = 0; ielem < count; ielem++) { + mpiret = sc_MPI_Pack (&(quads[ielem]->x), 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Pack (&(quads[ielem]->y), 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Pack (&(quads[ielem]->z), 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Pack (&quads_with_sub[ielem]->subelement_id, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Pack (&quads_with_sub[ielem]->transition_type, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Pack (&(quads[ielem]->level), 1, sc_MPI_INT8_T, send_buffer, buffer_size, position, comm); + SC_CHECK_MPI (mpiret); + } } -/* each hex is packed as x,y,z coordinates and the level */ +/* each hex is packed as x,y,z coordinates, the subelement ID, transition type and the level */ void t8_subelement_scheme_hex_c::t8_element_MPI_Pack_size (const unsigned int count, sc_MPI_Comm comm, int *pack_size) const { - SC_ABORT_NOT_REACHED(); - // int singlesize = 0; - // int datasize = 0; - // int mpiret; + int singlesize = 0; + int datasize = 0; + int mpiret; - // /* x,y,z */ - // mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &datasize); - // SC_CHECK_MPI (mpiret); - // singlesize += 3 * datasize; + /* x,y,z, subelement ID and transition type */ + mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &datasize); + SC_CHECK_MPI (mpiret); + singlesize += 5 * datasize; - // /* level */ - // mpiret = sc_MPI_Pack_size (1, sc_MPI_INT8_T, comm, &datasize); - // SC_CHECK_MPI (mpiret); - // singlesize += datasize; + /* level */ + mpiret = sc_MPI_Pack_size (1, sc_MPI_INT8_T, comm, &datasize); + SC_CHECK_MPI (mpiret); + singlesize += datasize; - // *pack_size = count * singlesize; + *pack_size = count * singlesize; } /* each hex is packed as x,y,z coordinates and the level */ @@ -3072,19 +3078,24 @@ t8_subelement_scheme_hex_c::t8_element_MPI_Unpack (void *recvbuf, const int buff t8_element_t **elements, const unsigned int count, sc_MPI_Comm comm) const { - SC_ABORT_NOT_REACHED(); - // int mpiret; - // p8est_quadrant_t **quads = (p8est_quadrant_t **) elements; - // for (unsigned int ielem = 0; ielem < count; ielem++) { - // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->x), 1, sc_MPI_INT, comm); - // SC_CHECK_MPI (mpiret); - // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->y), 1, sc_MPI_INT, comm); - // SC_CHECK_MPI (mpiret); - // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->z), 1, sc_MPI_INT, comm); - // SC_CHECK_MPI (mpiret); - // mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->level), 1, sc_MPI_INT8_T, comm); - // SC_CHECK_MPI (mpiret); - // } + int mpiret; + p8est_quadrant_t **quads = (p8est_quadrant_t **) elements; + t8_hex_with_subelements **quads_with_sub = (t8_hex_with_subelements **) elements; + + for (unsigned int ielem = 0; ielem < count; ielem++) { + mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->x), 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->y), 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->z), 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads_with_sub[ielem]->subelement_id), 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads_with_sub[ielem]->transition_type), 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->level), 1, sc_MPI_INT8_T, comm); + SC_CHECK_MPI (mpiret); + } } /* Constructor */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index f025eb58fe..8e4f06ca9c 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -66,7 +66,7 @@ typedef struct { - /* p4est quadrant */ + /* p8est quadrant */ p8est_quadrant_t p8q; /* stores transition cell information (default for non-subelements is 0 and for subelements it is != 0 - is therefore used as a is_subelement check) */ int transition_type; diff --git a/test/Makefile.am b/test/Makefile.am index eb7fbd33ee..913a8db4b7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -11,6 +11,7 @@ t8code_googletest_internal_headers = \ thirdparty/googletest-mpi/gtest/gtest.h \ test/t8_gtest_macros.hxx \ test/t8_schemes/t8_gtest_dfs_base.hxx \ + test/t8_schemes_transition/t8_gtest_dfs_base.hxx \ test/t8_cmesh_generator/t8_cmesh_example_sets.hxx \ test/t8_cmesh_generator/t8_gtest_cmesh_cartestian_product.hxx \ test/t8_cmesh_generator/t8_gtest_cmesh_sum_of_sets.hxx \ @@ -87,6 +88,7 @@ t8code_googletest_programs = \ test/t8_schemes/t8_gtest_default \ test/t8_schemes/t8_gtest_pack_unpack \ test/t8_schemes/t8_gtest_child_parent_face \ + test/t8_schemes_transition/t8_gtest_child_parent_face \ test/t8_cmesh_generator/t8_gtest_cmesh_generator_test test_t8_IO_t8_gtest_vtk_reader_SOURCES = \ @@ -329,6 +331,10 @@ test_t8_schemes_t8_gtest_child_parent_face_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_child_parent_face.cxx +test_t8_schemes_transition_t8_gtest_child_parent_face_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_child_parent_face.cxx + test_t8_cmesh_generator_t8_gtest_cmesh_generator_test_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_cmesh_generator/t8_gtest_cmesh_generator_test.cxx @@ -585,6 +591,10 @@ test_t8_schemes_t8_gtest_child_parent_face_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_child_parent_face_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_child_parent_face_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_child_parent_face_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_child_parent_face_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_child_parent_face_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_cmesh_generator_t8_gtest_cmesh_generator_test_LDADD = $(t8_gtest_target_ld_add) test_t8_cmesh_generator_t8_gtest_cmesh_generator_test_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_cmesh_generator_t8_gtest_cmesh_generator_test_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -655,6 +665,7 @@ test_t8_cmesh_t8_gtest_cmesh_tree_vertices_negative_volume_CPPFLAGS += $(t8_gtes test_t8_schemes_t8_gtest_default_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_pack_unpack_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_child_parent_face_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_child_parent_face_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_generator_t8_gtest_cmesh_generator_test_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_t8_gtest_cmesh_copy_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) diff --git a/test/t8_schemes_transition/t8_gtest_child_parent_face.cxx b/test/t8_schemes_transition/t8_gtest_child_parent_face.cxx new file mode 100644 index 0000000000..9377612694 --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_child_parent_face.cxx @@ -0,0 +1,83 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2023 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include "t8_gtest_dfs_base.hxx" +#include + +class class_child_parent_face: public TestDFS { + virtual void + check_element () + { + const int num_faces = ts->t8_element_num_faces (element); + for (int iface = 0; iface < num_faces; iface++) { + /* Iterate over all faces and determine the facechildren*/ + const int num_face_children = ts->t8_element_num_face_children (element, iface); + t8_element_t **children; + children = T8_ALLOC (t8_element_t *, num_face_children); + ts->t8_element_new (num_face_children, children); + + ts->t8_element_children_at_face (element, iface, children, num_face_children, NULL); + + for (int ifacechild = 0; ifacechild < num_face_children; ifacechild++) { + /* Iterate over those children and determine the childface corresponding to the parentface */ + int childface = ts->t8_element_face_child_face (element, iface, ifacechild); + ASSERT_NE (childface, -1); + /* Determine the parentface corresponding to the childface */ + int parentface = ts->t8_element_face_parent_face (children[ifacechild], childface); + /* Check, that this is equal to the face that we started with */ + EXPECT_EQ (iface, parentface); + } + ts->t8_element_destroy (num_face_children, children); + T8_FREE (children); + } + } + + protected: + void + SetUp () override + { + /* Setup DFS test */ + dfs_test_setup (); + } + void + TearDown () override + { + /* Destroy DFS test */ + dfs_test_teardown (); + } +}; + +TEST_P (class_child_parent_face, t8_recursive_dfs_child_parent_face) +{ +#ifdef T8_ENABLE_LESS_TESTS + const int maxlvl = 4; +#else + const int maxlvl = 6; +#endif + check_recursive_dfs_to_max_lvl (maxlvl); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_child_parent_face, class_child_parent_face, testing::Values (T8_ECLASS_HEX), print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_dfs_base.hxx b/test/t8_schemes_transition/t8_gtest_dfs_base.hxx new file mode 100644 index 0000000000..b136ed3e48 --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_dfs_base.hxx @@ -0,0 +1,93 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2023 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef T8_GTEST_SCHEME_HELPER_H +#define T8_GTEST_SCHEME_HELPER_H + +#include +#include +#include +#include + +class TestDFS: public testing::TestWithParam { + public: + /** recursive tests check something for all descendants of a starting element (currently only root) upto maxlevel +*/ + virtual void + check_element () {}; + + /** recursive depth first search to iterate over all descendants of elem up to max_dfs_recursion_level */ + void + check_recursive_dfs_to_max_lvl (const int max_dfs_recursion_level) + { + int level = ts->t8_element_level (element); + ASSERT_LE (level, max_dfs_recursion_level); + ASSERT_LT (max_dfs_recursion_level, ts->t8_element_maxlevel ()); + + /** call the implementation of the specific test*/ + check_element (); + + if (ts->t8_element_level (element) < max_dfs_recursion_level) { + /* iterate over all children */ + const int num_children = ts->t8_element_num_children (element); + for (int ichild = 0; ichild < num_children; ichild++) { + ts->t8_element_child (element, ichild, element); + check_recursive_dfs_to_max_lvl (max_dfs_recursion_level); + ts->t8_element_parent (element, element); + } + } + } + + void + dfs_test_setup () + { + scheme = t8_scheme_new_transition_hex_cxx (); + eclass = GetParam (); + ts = scheme->eclass_schemes[eclass]; + ts->t8_element_new (1, &element); + ts->t8_element_root (element); + } + void + dfs_test_teardown () + { + ts->t8_element_destroy (1, &element); + t8_scheme_cxx_unref (&scheme); + } + + void + SetUp () override + { + dfs_test_setup (); + } + void + TearDown () override + { + dfs_test_teardown (); + } + + t8_scheme_cxx *scheme; + t8_eclass_t eclass; + t8_eclass_scheme_c *ts; + t8_element_t *element; +}; + +#endif /*T8_GTEST_SCHEME_HELPER_H*/ From ac5a3e96f66c438257f4f4c41d60331f449a1bb3 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 14 May 2024 12:28:56 +0200 Subject: [PATCH 13/55] Added descendant and equal test + correction in t8_element_equal function --- .../t8_transition_conformal_hex_cxx.cxx | 24 +-- test/Makefile.am | 21 +++ .../t8_gtest_descendant.cxx | 162 ++++++++++++++++++ test/t8_schemes_transition/t8_gtest_equal.cxx | 89 ++++++++++ 4 files changed, 279 insertions(+), 17 deletions(-) create mode 100644 test/t8_schemes_transition/t8_gtest_descendant.cxx create mode 100644 test/t8_schemes_transition/t8_gtest_equal.cxx diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index ea66a7c578..d25dadf77c 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -449,18 +449,9 @@ t8_subelement_scheme_hex_c::t8_element_child (const t8_element_t *elem, { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements *phex_w_sub_child = - (t8_hex_with_subelements *) child; - - const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - p8est_quadrant_t *r = &phex_w_sub_child->p8q; - + const p8est_quadrant_t *q = (const p8est_quadrant_t *) elem; const p4est_qcoord_t shift = P8EST_QUADRANT_LEN (q->level + 1); - - /* it should not be possible to construct a child of a subelement */ - T8_ASSERT (!t8_element_is_subelement (elem)); + p8est_quadrant_t *r = (p8est_quadrant_t *) child; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (child)); @@ -475,6 +466,8 @@ t8_subelement_scheme_hex_c::t8_element_child (const t8_element_t *elem, if (q != r) { T8_ASSERT (p8est_quadrant_is_parent (q, r)); } + t8_element_reset_subelement_values (child); + } void @@ -2938,13 +2931,10 @@ t8_subelement_scheme_hex_c::t8_element_transition_scheme_is_conformal (void) int t8_subelement_scheme_hex_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const{ - - if(t8_element_get_subelement_id((const t8_element * ) elem1) == t8_element_get_subelement_id((const t8_element * ) elem2)){ - return 1; - } -else{ - return 0; +if (t8_element_get_subelement_id((const t8_element * ) elem1) != 0 ){ + t8_productionf("--------------------------------\n sub ID %i \n ------------------\n", t8_element_get_subelement_id((const t8_element * ) elem1)); } + return (p8est_quadrant_is_equal ((const p8est_quadrant_t *) elem1, (const p8est_quadrant_t *) elem2)) && (t8_element_get_subelement_id((const t8_element * ) elem1) == t8_element_get_subelement_id((const t8_element * ) elem2)); } void diff --git a/test/Makefile.am b/test/Makefile.am index 913a8db4b7..715c0bd878 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -48,8 +48,10 @@ t8code_googletest_programs = \ test/t8_schemes/t8_gtest_element_ref_coords \ test/t8_geometry/t8_gtest_geometry_handling \ test/t8_schemes/t8_gtest_descendant \ + test/t8_schemes_transition/t8_gtest_descendant \ test/t8_schemes/t8_gtest_find_parent \ test/t8_schemes/t8_gtest_equal \ + test/t8_schemes_transition/t8_gtest_equal \ test/t8_schemes/t8_gtest_root \ test/t8_cmesh/t8_gtest_cmesh_face_is_boundary \ test/t8_cmesh/t8_gtest_cmesh_partition \ @@ -70,6 +72,7 @@ t8code_googletest_programs = \ test/t8_forest/t8_gtest_find_owner \ test/t8_forest/t8_gtest_forest_face_normal \ test/t8_schemes/t8_gtest_face_descendant \ + test/t8_schemes_transition/t8_gtest_face_descendant \ test/t8_geometry/t8_gtest_point_inside \ test/t8_forest/t8_gtest_user_data \ test/t8_forest/t8_gtest_transform \ @@ -183,6 +186,10 @@ test_t8_schemes_t8_gtest_descendant_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_descendant.cxx +test_t8_schemes_transition_t8_gtest_descendant_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_descendant.cxx + test_t8_schemes_t8_gtest_find_parent_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_find_parent.cxx @@ -191,6 +198,10 @@ test_t8_schemes_t8_gtest_equal_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_equal.cxx +test_t8_schemes_transition_t8_gtest_equal_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_equal.cxx + test_t8_schemes_t8_gtest_root_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_root.cxx @@ -439,6 +450,10 @@ test_t8_schemes_t8_gtest_descendant_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_descendant_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_descendant_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_descendant_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_descendant_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_descendant_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_schemes_t8_gtest_find_parent_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_find_parent_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_find_parent_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -447,6 +462,10 @@ test_t8_schemes_t8_gtest_equal_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_equal_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_equal_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_equal_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_equal_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_equal_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_schemes_t8_gtest_root_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_root_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_root_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -627,8 +646,10 @@ test_t8_schemes_t8_gtest_element_count_leaves_CPPFLAGS += $(t8_gtest_target_mpi_ test_t8_schemes_t8_gtest_element_ref_coords_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_geometry_t8_gtest_geometry_handling_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_descendant_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_descendant_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_find_parent_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_equal_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_equal_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_root_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_t8_gtest_cmesh_face_is_boundary_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_t8_gtest_cmesh_partition_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) diff --git a/test/t8_schemes_transition/t8_gtest_descendant.cxx b/test/t8_schemes_transition/t8_gtest_descendant.cxx new file mode 100644 index 0000000000..9373cca49a --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_descendant.cxx @@ -0,0 +1,162 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element types in parallel. + + Copyright (C) 2010 The University of Texas System + Written by Carsten Burstedde, Lucas C. Wilcox, and Tobin Isaac + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + + +/* This program tests the descendant function of an element. */ + +class class_schemes_descendant: public testing::TestWithParam { + protected: + void + SetUp () override + { + eclass = GetParam (); + + scheme = t8_scheme_new_transition_hex_cxx (); + ts = scheme->eclass_schemes[eclass]; + ts->t8_element_new (1, &elem); + ts->t8_element_new (1, &desc); + ts->t8_element_new (1, &test); + ts->t8_element_root (elem); + } + void + TearDown () override + { + ts->t8_element_destroy (1, &elem); + ts->t8_element_destroy (1, &desc); + ts->t8_element_destroy (1, &test); + t8_scheme_cxx_unref (&scheme); + } +#ifdef T8_ENABLE_DEBUG + const int maxlvl = 3; +#else + const int maxlvl = 4; +#endif + + t8_scheme_cxx *scheme; + t8_eclass_scheme_c *ts; + t8_eclass_t eclass; + t8_element_t *elem; + t8_element_t *desc; + t8_element_t *test; +}; + +/* Test recursively if the first and last descendant of an element is + * computed correctly. Only the descendant of elem->level + 1 is tested. + */ +static void +t8_recursive_descendant (t8_element_t *elem, t8_element_t *desc, t8_element_t *test, t8_eclass_scheme_c *ts, int maxlvl) +{ + const int num_children = ts->t8_element_num_children (elem); + const int level = ts->t8_element_level (elem); + for (int ichild = 0; ichild < num_children; ichild++) { + ts->t8_element_child (elem, ichild, desc); + /* first child == first descendant. */ + if (ichild == 0) { + ts->t8_element_first_descendant (elem, test, level + 1); + EXPECT_ELEM_EQ (ts, desc, test); + } + /* last child == last descendant. */ + else if (ichild == num_children - 1) { + ts->t8_element_last_descendant (elem, test, level + 1); + EXPECT_ELEM_EQ (ts, desc, test); + } + else if (level > maxlvl) { + t8_recursive_descendant (desc, elem, test, ts, maxlvl); + ts->t8_element_parent (desc, elem); + } + } +} + +/* Test, if the first descendant of an element is computed correctly over a range + * of levels. + */ +static void +t8_deep_first_descendant (t8_element_t *elem, t8_element_t *desc, t8_element_t *test, t8_eclass_scheme_c *ts, int level) +{ + const int elem_level = ts->t8_element_level (elem); + ts->t8_element_copy (elem, test); + + for (int ilevel = elem_level; ilevel < level; ilevel++) { + ts->t8_element_child (test, 0, desc); + ts->t8_element_copy (desc, test); + } + ts->t8_element_first_descendant (elem, test, level); + EXPECT_ELEM_EQ (ts, desc, test); +} + +/* Test, if the last descendant of an element is computed correctly over a range + * of levels. + */ +static void +t8_deep_last_descendant (t8_element_t *elem, t8_element_t *desc, t8_element_t *test, t8_eclass_scheme_c *ts, int level) +{ + ts->t8_element_copy (elem, test); + + /* Compute the correct element. */ + for (int ilevel = ts->t8_element_level (elem); ilevel < level; ilevel++) { + const int num_children = ts->t8_element_num_children (test); + ts->t8_element_child (test, num_children - 1, desc); + ts->t8_element_copy (desc, test); + } + /* Check for equality. */ + ts->t8_element_last_descendant (elem, test, level); + EXPECT_ELEM_EQ (ts, desc, test); +} + +/* Test if the first and last descendant of an element are computed correctly. + * The level between the element and the descendant is larger or equal to one. + */ +static void +t8_large_step_descendant (t8_element_t *elem, t8_element_t *desc, t8_element_t *test, t8_eclass_scheme_c *ts, + int maxlvl) +{ + for (int ilevel = ts->t8_element_level (elem); ilevel < maxlvl; ilevel++) { + + const int num_children = ts->t8_element_num_children (elem); + /* Use these functions to perform the actual test. */ + t8_deep_first_descendant (elem, desc, test, ts, maxlvl); + t8_deep_last_descendant (elem, desc, test, ts, maxlvl); + for (int jchild = 0; jchild < num_children; jchild++) { + ts->t8_element_child (elem, jchild, desc); + t8_large_step_descendant (desc, elem, test, ts, maxlvl); + ts->t8_element_parent (desc, elem); + } + } +} + +TEST_P (class_schemes_descendant, test_recursive_descendant) +{ + t8_recursive_descendant (elem, desc, test, ts, maxlvl); + t8_deep_first_descendant (elem, desc, test, ts, ts->t8_element_maxlevel ()); + t8_deep_last_descendant (elem, desc, test, ts, ts->t8_element_maxlevel ()); + t8_large_step_descendant (elem, desc, test, ts, maxlvl); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_descendant, class_schemes_descendant, testing::Values (T8_ECLASS_HEX), print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_equal.cxx b/test/t8_schemes_transition/t8_gtest_equal.cxx new file mode 100644 index 0000000000..75cb16c085 --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_equal.cxx @@ -0,0 +1,89 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include "t8_gtest_dfs_base.hxx" +#include + + +class class_test_equal: public TestDFS { + virtual void + check_element () + { + const int num_children = ts->t8_element_num_children (element); + for (int ichild1 = 0; ichild1 < num_children; ichild1++) { + ts->t8_element_child (element, ichild1, child1); + /* the child must be different than its parent */ + EXPECT_FALSE (ts->t8_element_equal (element, child1)); + for (int ichild2 = 0; ichild2 < num_children; ichild2++) { + ts->t8_element_child (element, ichild2, child2); + /* the child must be different than its parent */ + EXPECT_FALSE (ts->t8_element_equal (element, child2)); + const int equal = ts->t8_element_equal (child1, child2); + /* The children must be equal if and only if their indices are equal. */ + EXPECT_EQ (equal, ichild1 == ichild2); + /* t8_element_equal should compute the same as t8_element_compare, + * when we only check if compare has 0 as result. */ + const int compare_equal = !ts->t8_element_compare (child1, child2); + EXPECT_EQ (equal, compare_equal); + } + } + } + + protected: + void + SetUp () override + { + dfs_test_setup (); + /* Get element and initialize it */ + ts->t8_element_new (1, &child1); + ts->t8_element_new (1, &child2); + } + void + TearDown () override + { + /* Destroy element */ + ts->t8_element_destroy (1, &child1); + ts->t8_element_destroy (1, &child2); + + /* Destroy DFS test */ + dfs_test_teardown (); + } + t8_element_t *child1; + t8_element_t *child2; +}; + +TEST_P (class_test_equal, test_equal_dfs) +{ +#ifdef T8_ENABLE_LESS_TESTS + const int maxlvl = 3; +#else + const int maxlvl = 5; +#endif + check_recursive_dfs_to_max_lvl (maxlvl); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_test_all_imps, class_test_equal, testing::Values (T8_ECLASS_HEX), print_eclass); From 1a16a9230e99a8fb7e066994163405a52416e333 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 14 May 2024 13:50:50 +0200 Subject: [PATCH 14/55] Added test face_descendant + correction in scheme --- .../t8_transition_conformal_hex_cxx.cxx | 57 ++++---- test/Makefile.am | 9 ++ .../t8_gtest_face_descendant.cxx | 124 ++++++++++++++++++ 3 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 test/t8_schemes_transition/t8_gtest_face_descendant.cxx diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index d25dadf77c..3b09d78f3c 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1496,8 +1496,6 @@ t8_subelement_scheme_hex_c::t8_element_tree_face (const t8_element_t *elem, /* For hex the face and the tree face number are the same. */ return face; } - - // SC_ABORT_NOT_REACHED(); } /** Construct the first descendant of an element that touches a given face. */ @@ -1511,30 +1509,23 @@ t8_subelement_scheme_hex_c::t8_element_first_descendant_face (const int level) const { - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements *phex_w_sub_first_desc = - (t8_hex_with_subelements *) first_desc; - - const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - p8est_quadrant_t *desc = &phex_w_sub_first_desc->p8q; - - int first_face_corner; - /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); + + const p8est_quadrant_t *q = (const p8est_quadrant_t *) elem; + p8est_quadrant_t *desc = (p8est_quadrant_t *) first_desc; + int first_face_corner; + T8_ASSERT (0 <= face && face < P8EST_FACES); - T8_ASSERT (0 <= level && level <= P8EST_QMAXLEVEL); + T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); /* Get the first corner of q that belongs to face */ first_face_corner = p8est_face_corners[face][0]; - /* Construce the descendant in that corner */ + /* Construct the descendant of q in this corner */ p8est_quadrant_corner_descendant (q, desc, first_face_corner, level); - t8_element_reset_subelement_values (first_desc); - - } + /** Construct the last descendant of an element that touches a given face. */ void t8_subelement_scheme_hex_c::t8_element_last_descendant_face (const @@ -1544,29 +1535,21 @@ t8_subelement_scheme_hex_c::t8_element_last_descendant_face (const *last_desc, int level) const { - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements *phex_w_sub_last_desc = - (t8_hex_with_subelements *) last_desc; - - const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - p8est_quadrant_t *desc = &phex_w_sub_last_desc->p8q; - - int last_face_corner; - /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); T8_ASSERT (!t8_element_is_subelement (last_desc)); + + const p8est_quadrant_t *q = (const p8est_quadrant_t *) elem; + p8est_quadrant_t *desc = (p8est_quadrant_t *) last_desc; + int last_face_corner; + T8_ASSERT (0 <= face && face < P8EST_FACES); - T8_ASSERT (0 <= level && level <= P8EST_QMAXLEVEL); + T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); /* Get the last corner of q that belongs to face */ - last_face_corner = p8est_face_corners[face][1]; - /* Construce the descendant in that corner */ + last_face_corner = p8est_face_corners[face][3]; + /* Construct the descendant of q in this corner */ p8est_quadrant_corner_descendant (q, desc, last_face_corner, level); - t8_element_reset_subelement_values (last_desc); - - } void @@ -3012,7 +2995,13 @@ t8_subelement_scheme_hex_c::t8_element_subelement_values_are_valid (const void t8_subelement_scheme_hex_c::t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const{ - SC_ABORT_NOT_REACHED(); + T8_ASSERT (!t8_element_is_subelement(elem)); + T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (debug_string != NULL); + t8_hex_with_subelements *hex_with_sub = (t8_hex_with_subelements *) elem; + const p8est_quadrant_t *hex = &hex_with_sub->p8q; + + snprintf (debug_string, string_size, "x: %i, y: %i, z: %i, level: %i", hex->x, hex->y, hex->z, hex->level); } #endif diff --git a/test/Makefile.am b/test/Makefile.am index 715c0bd878..f0ade41106 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -274,6 +274,10 @@ test_t8_schemes_t8_gtest_face_descendant_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_face_descendant.cxx +test_t8_schemes_transition_t8_gtest_face_descendant_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_face_descendant.cxx + test_t8_geometry_t8_gtest_point_inside_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_geometry/t8_gtest_point_inside.cxx @@ -538,6 +542,10 @@ test_t8_schemes_t8_gtest_face_descendant_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_face_descendant_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_face_descendant_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_face_descendant_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_face_descendant_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_face_descendant_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_geometry_t8_gtest_point_inside_LDADD = $(t8_gtest_target_ld_add) test_t8_geometry_t8_gtest_point_inside_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_geometry_t8_gtest_point_inside_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -668,6 +676,7 @@ test_t8_forest_t8_gtest_half_neighbors_CPPFLAGS += $(t8_gtest_target_mpi_cpp_fla test_t8_forest_t8_gtest_find_owner_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_forest_t8_gtest_forest_face_normal_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_face_descendant_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_face_descendant_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_geometry_t8_gtest_point_inside_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_forest_t8_gtest_user_data_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_forest_t8_gtest_transform_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) diff --git a/test/t8_schemes_transition/t8_gtest_face_descendant.cxx b/test/t8_schemes_transition/t8_gtest_face_descendant.cxx new file mode 100644 index 0000000000..9190be3b78 --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_face_descendant.cxx @@ -0,0 +1,124 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element types in parallel. + + Copyright (C) 2010 The University of Texas System + Written by Carsten Burstedde, Lucas C. Wilcox, and Tobin Isaac + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include "t8_gtest_dfs_base.hxx" +#include + +/* compute the first/last descendant by iteratively taking the first/last child at each level*/ +static void +t8_test_manual_first_last_face_descendant (const t8_eclass_scheme_c *ts, const t8_element_t *element, const int iface, + const int desc_level, const int last, t8_element_t *face_desc) +{ + const int num_children_at_face = ts->t8_element_num_face_children (element, iface); + + int *child_indices = T8_ALLOC (int, num_children_at_face); + t8_element_t **children = T8_ALLOC (t8_element_t *, num_children_at_face); + ts->t8_element_new (num_children_at_face, children); + + ts->t8_element_copy (element, face_desc); + const int level = ts->t8_element_level (element); + for (int ilevel = level; ilevel < desc_level; ilevel++) { + EXPECT_EQ (ts->t8_element_num_face_children (element, iface), num_children_at_face); + /* Compute child_id of the test_child_id-th child. */ + ts->t8_element_children_at_face (face_desc, iface, children, num_children_at_face, child_indices); + + /* chose correct face_id dependent on if we want first or last face desc.*/ + const int face_child_id = last ? num_children_at_face - 1 : 0; + + const int child_id = child_indices[face_child_id]; + + ts->t8_element_child (face_desc, child_id, face_desc); + } + ts->t8_element_destroy (num_children_at_face, children); + T8_FREE (children); + T8_FREE (child_indices); +} + +class class_descendant: public TestDFS { + virtual void + check_element () + { + /* Check the linear first and last descendants of an element along all faces. + * For the test the descendants are computed manually by t8_test_manual_first_last_face_descendant and + * by the scheme implementation t8_element_first_descendant for the first descendants over the levels. + */ + + const int level = ts->t8_element_level (element); + const int num_faces = ts->t8_element_num_faces (element); + + /* Testing the linear first descendant. */ + for (int ilevel = level + 1; ilevel < max_test_lvl; ilevel++) { + for (int jface = 0; jface < num_faces; jface++) { + + t8_test_manual_first_last_face_descendant (ts, element, jface, ilevel, 0, manual_face_desc); + ts->t8_element_first_descendant_face (element, jface, scheme_face_desc, ilevel); + /* Compare the manually computed child with the result of t8_element_first_descendant_face. */ + EXPECT_ELEM_EQ (ts, scheme_face_desc, manual_face_desc); + + t8_test_manual_first_last_face_descendant (ts, element, jface, ilevel, 1, manual_face_desc); + ts->t8_element_last_descendant_face (element, jface, scheme_face_desc, ilevel); + /* Compare the manually computed child with the result of t8_element_last_descendant_face. */ + EXPECT_ELEM_EQ (ts, scheme_face_desc, manual_face_desc); + } + } + } + + protected: + void + SetUp () override + { + dfs_test_setup (); + max_test_lvl = ts->t8_element_maxlevel (); + ts->t8_element_new (1, &manual_face_desc); + ts->t8_element_new (1, &scheme_face_desc); + } + void + TearDown () override + { + ts->t8_element_destroy (1, &manual_face_desc); + ts->t8_element_destroy (1, &scheme_face_desc); + dfs_test_teardown (); + } + int max_test_lvl; + t8_element_t *manual_face_desc; + t8_element_t *scheme_face_desc; +}; + +TEST_P (class_descendant, t8_check_face_desc) +{ + +#ifdef T8_ENABLE_LESS_TESTS + const int maxlvl = 3; +#else + const int maxlvl = 5; +#endif + + check_recursive_dfs_to_max_lvl (maxlvl); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_element_face_descendant, class_descendant, testing::Values (T8_ECLASS_HEX), print_eclass); From faeddb1ce075166fb6115173cd445fd8e5c426a8 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 14 May 2024 15:07:18 +0200 Subject: [PATCH 15/55] Added more test for t8_schemes_transition --- .../t8_transition_conformal_hex_cxx.cxx | 13 +- .../t8_gtest_face_neigh.cxx | 210 ++++++++++++ .../t8_gtest_find_parent.cxx | 78 +++++ test/t8_schemes_transition/t8_gtest_nca.cxx | 314 ++++++++++++++++++ .../t8_gtest_pack_unpack.cxx | 140 ++++++++ test/t8_schemes_transition/t8_gtest_root.cxx | 72 ++++ .../t8_gtest_successor.cxx | 159 +++++++++ 7 files changed, 978 insertions(+), 8 deletions(-) create mode 100644 test/t8_schemes_transition/t8_gtest_face_neigh.cxx create mode 100644 test/t8_schemes_transition/t8_gtest_find_parent.cxx create mode 100644 test/t8_schemes_transition/t8_gtest_nca.cxx create mode 100644 test/t8_schemes_transition/t8_gtest_pack_unpack.cxx create mode 100644 test/t8_schemes_transition/t8_gtest_root.cxx create mode 100644 test/t8_schemes_transition/t8_gtest_successor.cxx diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 3b09d78f3c..43afaece64 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1228,18 +1228,15 @@ t8_subelement_scheme_hex_c::t8_element_nca (const t8_element_t *elem1, T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); -#if 0 - /* TODO: This assertions throws an error since it expects a 3D hex. - * this does not make sense. investigate. */ - T8_ASSERT (t8_element_surround_matches (q1, q2)); -#endif +// #if 0 +// /* TODO: This assertions throws an error since it expects a 3D hex. +// * this does not make sense. investigate. */ +// T8_ASSERT (t8_element_surround_matches (q1, q2)); +// #endif /* In case of subelements, we use the parent quadrant and construct nca of the parent quadrant */ t8_element_reset_subelement_values (nca); p8est_nearest_common_ancestor (q1, q2, r); - // t8_element_copy_surround (q1, r); - - // SC_ABORT_NOT_REACHED(); } //Nummerierung der Seiten(der Pyramiden) wie in Davids Masterarbeit diff --git a/test/t8_schemes_transition/t8_gtest_face_neigh.cxx b/test/t8_schemes_transition/t8_gtest_face_neigh.cxx new file mode 100644 index 0000000000..7c178ffa06 --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_face_neigh.cxx @@ -0,0 +1,210 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + + +#include + +/* *INDENT-OFF* */ +class face_neigh: public testing::TestWithParam { + protected: + void + SetUp () override + { + eclass = GetParam (); + scheme = t8_scheme_new_transition_hex_cxx (); + + ts = scheme->eclass_schemes[eclass]; + ts->t8_element_new (1, &element); + ts->t8_element_new (1, &child); + ts->t8_element_new (1, &neigh); + ts->t8_element_root (element); + } + + void + TearDown () override + { + ts->t8_element_destroy (1, &element); + ts->t8_element_destroy (1, &child); + ts->t8_element_destroy (1, &neigh); + t8_scheme_cxx_unref (&scheme); + } + t8_element_t *element; + t8_element_t *child; + t8_element_t *neigh; + t8_scheme_cxx *scheme; + t8_eclass_scheme_c *ts; + t8_eclass_t eclass; + +#ifdef T8_ENABLE_LESS_TESTS + const int maxlvl = 3; +#else + const int maxlvl = 4; +#endif +}; +/* *INDENT-ON* */ + +void +t8_test_face_neighbor_inside (int num_faces, t8_element_t *element, t8_element_t *child, t8_element_t *neigh, + t8_eclass_scheme_c *ts) +{ + int face_num; + int check; + + for (int iface = 0; iface < num_faces; iface++) { + /* Compute the neighbors neighbor along a given face and check, if the result is the + * original element. */ + ts->t8_element_face_neighbor_inside (child, neigh, iface, &face_num); + ts->t8_element_face_neighbor_inside (neigh, element, face_num, &check); + + EXPECT_TRUE (ts->t8_element_equal (child, element)) << "Got a false neighbor."; + EXPECT_ELEM_EQ (ts, child, element); + } +} + +int +t8_test_get_middle_child (t8_eclass_t eclass, int ilevel, t8_element_t *element, t8_element_t *child, + t8_eclass_scheme_c *ts) +{ + /* Get the child number of the child in the middle of the element, depending of the shape of the element. */ + switch (eclass) { + case T8_ECLASS_VERTEX: + return 0; + case T8_ECLASS_LINE: + return 0; + case T8_ECLASS_QUAD: + /* There are no inner children in level one refinement. The test starts with level two, because this is the first level, inner children exists. + The third child of level one child 0 is one of four middle children in level two. */ + ts->t8_element_child (element, 0, child); + ts->t8_element_copy (child, element); + return 3; + case T8_ECLASS_TRIANGLE: + return 3; + case T8_ECLASS_HEX: + /* There are no inner children in level one refinement. The test starts with level two, because this is the first level, inner children existing. + The third child of level one child 4 is one of eight middle children in level two. */ + ts->t8_element_child (element, 4, child); + ts->t8_element_copy (child, element); + return 3; + case T8_ECLASS_TET: + return 3; + case T8_ECLASS_PRISM: + /* There are no inner children in level one refinement. The test starts with level two, because this is the first level, inner children existing. + The last child of level one child 4 is one of eight middle children in level two. */ + ts->t8_element_child (element, 4, child); + ts->t8_element_copy (child, element); + return 7; + case T8_ECLASS_PYRAMID: { + t8_dpyramid_t *pyramid = (t8_dpyramid_t *) element; + /* middle_child_id of Pyramid Type 6. */ + if (pyramid->pyramid.type == T8_DPYRAMID_FIRST_TYPE) { + return 8; + } + /* middle_child_id of Pyramid Type 7. */ + else { + return 3; + } + } + default: + return 0; + } +} + +/* Compute all children along all faces. Compute their neighbors along the face, + * check, if the children have root contact, and if the neighbors are outside of the + * root. */ +TEST_P (face_neigh, check_not_inside_root) +{ + /* Are the neighbors of the element really outside?. */ + + const int num_faces = ts->t8_element_num_faces (element); + + for (int iface = 0; iface < num_faces; iface++) { + + const int num_children = ts->t8_element_num_face_children (element, iface); + int *child_indices = T8_ALLOC (int, num_children); + t8_element_t **children = T8_ALLOC (t8_element_t *, num_children); + ts->t8_element_new (num_children, children); + ts->t8_element_children_at_face (element, iface, children, num_children, child_indices); + + for (int jchild = 0; jchild < num_children; jchild++) { + + const int child_id = child_indices[jchild]; + const int face_contact = ts->t8_element_face_child_face (element, iface, jchild); + + ts->t8_element_child (element, child_id, child); + int face_num; + int inside = ts->t8_element_face_neighbor_inside (child, neigh, face_contact, &face_num); + + ASSERT_EQ (inside, 0) << "Element is not outside."; + + inside = ts->t8_element_tree_face (child, face_contact); + ASSERT_EQ (inside, iface) << "Wrong face."; + } + ts->t8_element_destroy (num_children, children); + T8_FREE (children); + T8_FREE (child_indices); + } +} + +void +t8_recursive_check_diff (t8_element_t *element, t8_element_t *child, t8_element_t *neigh, t8_eclass_scheme_c *ts, + int maxlvl, int level) +{ + + T8_ASSERT (level <= maxlvl && maxlvl <= ts->t8_element_maxlevel () - 1); + if (level == maxlvl) { + return; + } + + /* Compute the neighbors neighbor along a given face and check, if the result is the + * original element. */ + int num_faces = ts->t8_element_num_faces (element); + + t8_test_face_neighbor_inside (num_faces, child, element, neigh, ts); + + int num_children = ts->t8_element_num_children (child); + for (int ichild = 0; ichild < num_children; ichild++) { + ts->t8_element_child (element, ichild, child); + t8_recursive_check_diff (child, element, neigh, ts, maxlvl, level + 1); + ts->t8_element_parent (child, element); + } +} + +/* Recursively check, if all neighbors are computed correct up to a given level. */ +TEST_P (face_neigh, recursive_check_diff) +{ + int level = 1; + int middle_child_id = t8_test_get_middle_child (eclass, level, element, child, ts); + ts->t8_element_child (element, middle_child_id, child); + + t8_recursive_check_diff (child, element, neigh, ts, maxlvl, level); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_face_neigh, face_neigh, testing::Values(T8_ECLASS_HEX), print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_find_parent.cxx b/test/t8_schemes_transition/t8_gtest_find_parent.cxx new file mode 100644 index 0000000000..8ee9a34a3b --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_find_parent.cxx @@ -0,0 +1,78 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +class class_find_parent: public TestDFS { + virtual void + check_element () + { + const int num_children = ts->t8_element_num_children (element); + for (int ichild = 0; ichild < num_children; ichild++) { + ts->t8_element_child (element, ichild, child); + /* Compute parent of child */ + ts->t8_element_parent (child, test_parent); + /* Check that it is equal to the original element */ + EXPECT_ELEM_EQ (ts, element, test_parent); + } + } + + protected: + void + SetUp () override + { + dfs_test_setup (); + /* Get element and initialize it */ + ts->t8_element_new (1, &child); + ts->t8_element_new (1, &test_parent); + } + void + TearDown () override + { + /* Destroy element */ + ts->t8_element_destroy (1, &child); + ts->t8_element_destroy (1, &test_parent); + + /* Destroy DFS test */ + dfs_test_teardown (); + } + t8_element_t *child; + t8_element_t *test_parent; +}; + +TEST_P (class_find_parent, t8_compute_child_find_parent) +{ +#ifdef T8_ENABLE_LESS_TESTS + const int maxlvl = 4; +#else + const int maxlvl = 6; +#endif + check_recursive_dfs_to_max_lvl (maxlvl); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_find_parent, class_find_parent, testing::Values (T8_ECLASS_HEX), print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_nca.cxx b/test/t8_schemes_transition/t8_gtest_nca.cxx new file mode 100644 index 0000000000..a06c0e3397 --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_nca.cxx @@ -0,0 +1,314 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2015 the developers + +t8code is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +t8code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/** \file t8_gtest_nca.cxx +* Provide tests to check the functionality of the nearest-common-ancestor function +* for every element. +*/ + +#include +#include +#include +#include +#include +#include + + +class nca: public testing::TestWithParam { + protected: + void + SetUp () override + { + eclass = GetParam (); + scheme = t8_scheme_new_transition_hex_cxx (); + ts = scheme->eclass_schemes[eclass]; + ts->t8_element_new (1, &correct_nca); + ts->t8_element_new (1, &desc_a); + ts->t8_element_new (1, &desc_b); + ts->t8_element_new (1, &check); + ts->t8_element_set_linear_id (correct_nca, 0, 0); + } + void + TearDown () override + { + ts->t8_element_destroy (1, &correct_nca); + ts->t8_element_destroy (1, &desc_a); + ts->t8_element_destroy (1, &desc_b); + ts->t8_element_destroy (1, &check); + t8_scheme_cxx_unref (&scheme); + } + /* correct_nca -> the nearest common ancestor that we check for + * desc_a -> a descendant of correct_nca + * desc_b -> another descendant of correct_nca, different from desc_a + * check -> the computed nca of desc_a and desc_b, should be equal to correct_nca + */ + t8_element_t *correct_nca, *desc_a, *desc_b, *check; + t8_scheme_cxx *scheme; + t8_eclass_scheme_c *ts; + t8_eclass_t eclass; +}; + +/** + * Test the nca for the children of the root-element + * + */ +TEST_P (nca, nca_check_shallow) +{ + int i, j; + const int num_children = ts->t8_element_num_children (correct_nca); + /* Iterate over all combinations of two children from correct_nca */ + for (i = 0; i < num_children - 1; i++) { + ts->t8_element_child (correct_nca, i, desc_a); + for (j = i + 1; j < num_children; j++) { + ts->t8_element_child (correct_nca, j, desc_b); + /*Compute the nca */ + ts->t8_element_nca (desc_a, desc_b, check); + /*expect equality */ + EXPECT_ELEM_EQ (ts, check, correct_nca); + } + } +} + +/** + * Check the nca for elements on the maximal level. + * We iteratively compute an element that is the correct nca up to level 10. + * The first and the last descendant of this element at the maximal level are + * computed and used as an input for t8_element_nca. + */ +TEST_P (nca, nca_check_deep) +{ + const int max_lvl = 10; + const int elem_max_level = ts->t8_element_maxlevel (); + /* num_children is not a const here, cause this can change for pyramids */ + int num_children; + /* iterate over levels and children */ + int lvl, check_lvl_a, check_lvl_b, child_id; + t8_element_t *tmp; + + ts->t8_element_new (1, &tmp); + ts->t8_element_copy (correct_nca, tmp); + for (lvl = 1; lvl <= max_lvl; lvl++) { + num_children = ts->t8_element_num_children (tmp); + for (child_id = 0; child_id < num_children; child_id++) { + ts->t8_element_child (tmp, child_id, correct_nca); + /* Compute first and last descendant at every level up to elem_max_lvl. + * They have the correct_nca as the nca */ + for (check_lvl_a = lvl + 1; check_lvl_a < elem_max_level; check_lvl_a++) { + ts->t8_element_first_descendant (correct_nca, desc_a, check_lvl_a); + for (check_lvl_b = lvl + 1; check_lvl_b < elem_max_level; check_lvl_b++) { + ts->t8_element_last_descendant (correct_nca, desc_b, check_lvl_b); + /* Compute the nca of desc_a and desc_b */ + ts->t8_element_nca (desc_a, desc_b, check); + if (eclass == T8_ECLASS_VERTEX) { + /* first- last-descendant logic does not hold for vertices. */ + EXPECT_EQ (ts->t8_element_level (check), + SC_MIN (ts->t8_element_level (desc_a), ts->t8_element_level (desc_b))); + } + else { + /* Expect equality of correct_nca and check for every other class */ + EXPECT_ELEM_EQ (ts, correct_nca, check); + } + } + } + } + /* Determine next element */ + if (num_children != 1) { + ts->t8_element_copy (tmp, correct_nca); + /* Continue in the middle */ + ts->t8_element_child (correct_nca, num_children / 2, tmp); + } + else { + ts->t8_element_copy (correct_nca, tmp); + } + } + ts->t8_element_destroy (1, &tmp); +} + +/** + * Recursively check the computation of the nca of all possible combination of descendants of the + * \a correct_nca that have \a correct_nca as the nca. + * + * \param[in] correct_nca The correct nearest common ancestor + * \param[in] desc_a Storage for the computation of a descendant of \correct_nca + * \param[in] desc_b Storage for the computation of a descendant of \correct_nca + * \param[in] check Storage for the computation of the nca of \a desc_a and \a desc_b + * \param[in] parent_a An initialized element, descendant of \a correct_nca, not a descendant or ancestor of \a parent_b. \a desc_a will be a child of it + * \param[in] parent_b An initialized element, descendant of \a correct_nca, not a descendant or ancestor of \a parent_a. \a desc_b will be a child of it + * \param[in] max_lvl The maximal depth of the recursion + * \param[in] ts the scheme to use + */ +static void +t8_recursive_nca_check (t8_element_t *check_nca, t8_element_t *desc_a, t8_element_t *desc_b, t8_element_t *check, + t8_element_t *parent_a, t8_element_t *parent_b, const int max_lvl, t8_eclass_scheme_c *ts) +{ + T8_ASSERT (max_lvl <= ts->t8_element_maxlevel () - 1); + /* compute the level of the parents */ + int level_a = ts->t8_element_level (parent_a); + int level_b = ts->t8_element_level (parent_b); + int num_children_a, num_children_b; + int i, j; + /* If one parent has reached the maximal level, the test returns */ + if (level_a == max_lvl || level_b == max_lvl) { + return; + } + num_children_a = ts->t8_element_num_children (parent_a); + num_children_b = ts->t8_element_num_children (parent_b); + + /* Iterate over all children of parent_a */ + for (i = 0; i < num_children_a; i++) { + ts->t8_element_child (parent_a, i, desc_a); + /* Iterate over all children of parent_b */ + for (j = 0; j < num_children_b; j++) { + ts->t8_element_child (parent_b, j, desc_b); + ts->t8_element_nca (desc_a, desc_b, check); + + if (!ts->t8_element_equal (check_nca, check)) { + level_a = ts->t8_element_level (desc_a); + level_b = ts->t8_element_level (desc_b); + + int level_c = ts->t8_element_level (check_nca); + int level_nca = ts->t8_element_level (check); + /* Output the linear id of the descendants where the computation fails. + * This makes debugging a lot easier, as one can reconstruct the descendants + * via t8_element_set_linear_id and can directly test them instead of waiting + * until the recursion reaches the faulty computation. */ + t8_debugf ("id of desc_a: %li, level: %i\n", ts->t8_element_get_linear_id (desc_a, level_a), level_a); + t8_debugf ("id of desc_b: %li, level: %i\n", ts->t8_element_get_linear_id (desc_b, level_b), level_b); + + for (int k = SC_MAX (level_a, level_b); k >= 0; k--) { + t8_debugf ("id of desc_a: %li, level: %i\n", ts->t8_element_get_linear_id (desc_a, k), k); + t8_debugf ("id of desc_b: %li, level: %i\n", ts->t8_element_get_linear_id (desc_b, k), k); + } + + t8_debugf ("id of the correct nca: %li, level: %i\n", ts->t8_element_get_linear_id (check_nca, level_c), + level_c); + + t8_debugf ("id of the computed nca: %li, level: %i\n", ts->t8_element_get_linear_id (check, level_nca), + level_nca); + + SC_ABORT ("Computed nca is not the correct nca!\n"); + } + /* parent_a stays fixed, b-part goes one level deeper into the recursion */ + t8_recursive_nca_check (check_nca, desc_a, parent_b, check, parent_a, desc_b, max_lvl, ts); + /* We reused parent_b, hence we have to recompute the correct parent */ + ts->t8_element_parent (desc_b, parent_b); + } + /* We reused parent_a, hence we have to recompute the correct parent */ + ts->t8_element_parent (desc_a, parent_a); + } +} + +/* Recursively check the computation of the nca. recursion_depth defines up to which + * level we compute descendants of correct_nca that should have correct_nca as the + * output of t8_element_nca.*/ +TEST_P (nca, recursive_check) +{ +#ifdef T8_ENABLE_LESS_TESTS + const int recursion_depth = 3; +#else + /* User lower recursion depth for pyramids, it takes to much time otherwise */ + const int recursion_depth = 4; +#endif + t8_element_t *parent_a, *parent_b; + int num_children; + num_children = ts->t8_element_num_children (correct_nca); + int i, j; + if (num_children > 1) { + ts->t8_element_new (1, &parent_a); + ts->t8_element_new (1, &parent_b); + ts->t8_element_child (correct_nca, 0, parent_a); + ts->t8_element_child (correct_nca, 1, parent_b); + for (i = 0; i < num_children - 1; i++) { + ts->t8_element_child (correct_nca, i, parent_a); + for (j = i + 1; j < num_children; j++) { + ts->t8_element_child (correct_nca, j, parent_b); + t8_recursive_nca_check (correct_nca, desc_a, desc_b, check, parent_a, parent_b, recursion_depth, ts); + } + } + } + else { + GTEST_SKIP (); + } + ts->t8_element_destroy (1, &parent_a); + ts->t8_element_destroy (1, &parent_b); +} + +/* Test the nca recursively for elements in the middle of the uniform refinement tree + * up to the maximal level. + * Be careful when increasing the recursion_depth, as it increases the number of test-cases exponentially. */ +TEST_P (nca, recursive_check_higher_level) +{ + + const int recursion_depth = 3; + const int max_lvl = ts->t8_element_maxlevel (); + t8_element_t *parent_a; + t8_element_t *parent_b; + t8_element_t *correct_nca_high_level; + int num_children; + int i, k, l; + t8_gloidx_t leaves_on_level; + EXPECT_TRUE (max_lvl - recursion_depth >= 0); + + ts->t8_element_new (1, &parent_a); + ts->t8_element_new (1, &parent_b); + ts->t8_element_new (1, &correct_nca_high_level); + + /* Test on different levels around the middle of the refinement tree */ + for (i = recursion_depth; i < max_lvl; i++) { + leaves_on_level = ts->t8_element_count_leaves (correct_nca, i - recursion_depth); + /* middle = leaves/2 */ + ts->t8_element_set_linear_id (correct_nca_high_level, i - recursion_depth, leaves_on_level / 2); + + /* Initialization for recursive_nca_check */ + num_children = ts->t8_element_num_children (correct_nca_high_level); + if (num_children > 1) { + /* Compute children on to different branches in the tree an test them. + * This ensures, that the nca of all their descendants has to be correct_nca_high_level*/ + for (k = 0; k < num_children; k++) { + ts->t8_element_child (correct_nca_high_level, k, parent_a); + for (l = 0; l < num_children; l++) { + ts->t8_element_child (correct_nca_high_level, l, parent_b); + if (k != l) { + t8_recursive_nca_check (correct_nca_high_level, desc_a, desc_b, check, parent_a, parent_b, i, ts); + } + else { + ts->t8_element_nca (parent_a, parent_b, check); + EXPECT_ELEM_EQ (ts, parent_a, check); + EXPECT_ELEM_EQ (ts, parent_b, check); + } + } + } + } + else { + ts->t8_element_destroy (1, &parent_a); + ts->t8_element_destroy (1, &parent_b); + ts->t8_element_destroy (1, &correct_nca_high_level); + GTEST_SKIP (); + } + } + /* Clean-up */ + ts->t8_element_destroy (1, &parent_a); + ts->t8_element_destroy (1, &parent_b); + ts->t8_element_destroy (1, &correct_nca_high_level); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_nca, nca, testing::Values (T8_ECLASS_HEX), print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_pack_unpack.cxx b/test/t8_schemes_transition/t8_gtest_pack_unpack.cxx new file mode 100644 index 0000000000..ff8e1e406f --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_pack_unpack.cxx @@ -0,0 +1,140 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2024 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + + +/** Use DFS to check for all elements, if packing them, sending them to ourself and unpacking them results in the same element + * Here, each element is sent individually. + */ +class class_test_pack: public TestDFS { + virtual void + + /* pack the element and its children, send to ourself, unpack and check if it is the same element */ + check_element () + { + size_t count = 1; + int position = 0; + + /* Compute pack size and allocate send buffer */ + int pack_size; + int num_children = ts->t8_element_num_children (element); + ts->t8_element_MPI_Pack_size (count, comm, &pack_size); + pack_size *= (num_children + 1); + char *sendbuf = T8_ALLOC (char, pack_size); + + /* pack data */ + ts->t8_element_MPI_Pack (&element, count, sendbuf, pack_size, &position, comm); + t8_element_t **children = T8_ALLOC (t8_element_t *, num_children); + ts->t8_element_new (num_children, children); + ts->t8_element_children (element, num_children, children); + ts->t8_element_MPI_Pack (children, num_children, sendbuf, pack_size, &position, comm); + + int recvBufferSize = pack_size; + char *recvbuf = T8_ALLOC (char, recvBufferSize); +#if T8_ENABLE_MPI + /* Send data */ + sc_MPI_Request request; + mpiret = sc_MPI_Isend (sendbuf, position, sc_MPI_PACKED, rank, T8_MPI_TEST_ELEMENT_PACK_TAG, comm, &request); + SC_CHECK_MPI (mpiret); + + /* Probe size and allocate */ + sc_MPI_Status status; + sc_MPI_Probe (rank, T8_MPI_TEST_ELEMENT_PACK_TAG, comm, &status); + + /* receive data */ + mpiret + = sc_MPI_Recv (recvbuf, position, sc_MPI_PACKED, rank, T8_MPI_TEST_ELEMENT_PACK_TAG, comm, sc_MPI_STATUS_IGNORE); + SC_CHECK_MPI (mpiret); + + /* Finalize non-blocking send communication */ + mpiret = sc_MPI_Wait (&request, sc_MPI_STATUS_IGNORE); + SC_CHECK_MPI (mpiret); +#else + /* just copy the data, if we did not compile with MPI*/ + mempcpy (recvbuf, sendbuf, pack_size); +#endif + /* Unpack data */ + position = 0; + ts->t8_element_MPI_Unpack (recvbuf, recvBufferSize, &position, &element_compare, count, comm); + t8_element_t **children_compare = T8_ALLOC (t8_element_t *, num_children); + ts->t8_element_new (num_children, children_compare); + ts->t8_element_MPI_Unpack (recvbuf, recvBufferSize, &position, children_compare, num_children, comm); + + /* free buffers */ + T8_FREE (sendbuf); + T8_FREE (recvbuf); + + /* Check that data was sent and received correctly */ + EXPECT_ELEM_EQ (ts, element, element_compare); + for (int ichild = 0; ichild < num_children; ichild++) { + EXPECT_ELEM_EQ (ts, children[ichild], children_compare[ichild]); + } + ts->t8_element_destroy (num_children, children); + ts->t8_element_destroy (num_children, children_compare); + T8_FREE (children); + T8_FREE (children_compare); + } + + protected: + void + SetUp () override + { + dfs_test_setup (); + /* Get element and initialize it */ + ts->t8_element_new (1, &element_compare); + + comm = sc_MPI_COMM_WORLD; + mpiret = sc_MPI_Comm_rank (comm, &rank); + SC_CHECK_MPI (mpiret); + } + void + TearDown () override + { + /* Destroy element */ + ts->t8_element_destroy (1, &element_compare); + + /* Destroy DFS test */ + dfs_test_teardown (); + } + t8_element_t *element_compare; + sc_MPI_Comm comm; + int rank; + int mpiret; +}; + +TEST_P (class_test_pack, test_equal_dfs) +{ +#ifdef T8_ENABLE_LESS_TESTS + const int maxlvl = 4; +#else + const int maxlvl = 6; +#endif + check_recursive_dfs_to_max_lvl (maxlvl); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_test_all_imps, class_test_pack, testing::Values (T8_ECLASS_HEX)); diff --git a/test/t8_schemes_transition/t8_gtest_root.cxx b/test/t8_schemes_transition/t8_gtest_root.cxx new file mode 100644 index 0000000000..7caeeef6be --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_root.cxx @@ -0,0 +1,72 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +t8code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/** \file t8_gtest_root.cxx +*/ + +#include +#include +#include +#include +#include +#include + +class root: public testing::TestWithParam { + protected: + void + SetUp () override + { + eclass = GetParam (); + scheme = t8_scheme_new_transition_hex_cxx (); + ts = scheme->eclass_schemes[eclass]; + ts->t8_element_new (1, &element); + ts->t8_element_root (element); + } + void + TearDown () override + { + ts->t8_element_destroy (1, &element); + t8_scheme_cxx_unref (&scheme); + } + t8_element_t *element; + t8_scheme_cxx *scheme; + t8_eclass_scheme_c *ts; + t8_eclass_t eclass; +}; + +/*Test root*/ + +TEST_P (root, has_level_zero) +{ + EXPECT_EQ (ts->t8_element_level (element), 0); +} + +TEST_P (root, equals_linear_id_0_0) +{ + t8_element_t *root_compare; + ts->t8_element_new (1, &root_compare); + ts->t8_element_set_linear_id (root_compare, 0, 0); + EXPECT_ELEM_EQ (ts, element, root_compare); + ts->t8_element_destroy (1, &root_compare); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_root, root, testing::Values (T8_ECLASS_HEX), print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_successor.cxx b/test/t8_schemes_transition/t8_gtest_successor.cxx new file mode 100644 index 0000000000..fba4a5d928 --- /dev/null +++ b/test/t8_schemes_transition/t8_gtest_successor.cxx @@ -0,0 +1,159 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element types in parallel. + + Copyright (C) 2010 The University of Texas System + Written by Carsten Burstedde, Lucas C. Wilcox, and Tobin Isaac + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +class class_successor: public testing::TestWithParam { + protected: + void + SetUp () override + { + eclass = GetParam (); + + scheme = t8_scheme_new_transition_hex_cxx (); + ts = scheme->eclass_schemes[eclass]; + + ts->t8_element_new (1, &element); + ts->t8_element_new (1, &successor); + ts->t8_element_new (1, &child); + ts->t8_element_new (1, &last); + + ts->t8_element_root (element); + if (eclass == T8_ECLASS_VERTEX) + GTEST_SKIP (); + } + void + TearDown () override + { + ts->t8_element_destroy (1, &element); + ts->t8_element_destroy (1, &successor); + ts->t8_element_destroy (1, &child); + ts->t8_element_destroy (1, &last); + + t8_scheme_cxx_unref (&scheme); + } + t8_eclass_t eclass; + t8_eclass_scheme_c *ts; + t8_scheme_cxx *scheme; + t8_element_t *element; + t8_element_t *successor; + t8_element_t *child; + t8_element_t *last; +}; + +/* Check the computation of the successor recursively. Iterate through the elements + * via DFS. On the given maxlvl-1 the children are computeted iteratively. For + * each child, the successor is checked. + */ +static void +t8_recursive_successor (t8_element_t *element, t8_element_t *successor, t8_element_t *child, t8_element_t *last, + t8_eclass_scheme_c *ts, const int maxlvl) +{ + const int level = ts->t8_element_level (element); + ASSERT_TRUE (ts->t8_element_level (element) <= maxlvl && maxlvl <= ts->t8_element_maxlevel () - 1); + const int num_children = ts->t8_element_num_children (element); + if (level == maxlvl - 1) { + /* Check, if the successor of the last recursion is the first child of + * of this element. + */ + ts->t8_element_child (element, 0, child); + EXPECT_ELEM_EQ (ts, child, successor); + /*Check if the successor in this element is computed correctly */ + for (int ichild = 1; ichild < num_children; ichild++) { + EXPECT_EQ (ts->t8_element_level (child), maxlvl); + ts->t8_element_successor (child, successor); + ts->t8_element_child (element, ichild, child); + EXPECT_ELEM_EQ (ts, child, successor); + } + /*If the iterator is the last element, the test can finish */ + if (ts->t8_element_equal (last, child)) { + return; + } + /*Compute the next successor / "jump" out of the current element */ + else { + EXPECT_EQ (ts->t8_element_level (child), maxlvl); + ts->t8_element_successor (child, successor); + } + } + else { + /*DFS run through the elements */ + for (int ichild = 0; ichild < num_children; ichild++) { + ts->t8_element_child (element, ichild, child); + t8_recursive_successor (child, successor, element, last, ts, maxlvl); + ts->t8_element_parent (child, element); + } + } +} + +/* Check the computation of the successor at the maximum level of the element. + * Given the element of level maxlevel-2 with linear id 0 all children of + * maximum level are computed. The successor runs through all these children. + */ +static void +t8_deep_successor (t8_element_t *element, t8_element_t *successor, t8_element_t *child, t8_eclass_scheme_c *ts) +{ + int maxlvl = ts->t8_element_maxlevel (); + int num_children = ts->t8_element_num_children (element); + + for (int ichild = 0; ichild < num_children; ichild++) { + ts->t8_element_child (element, ichild, child); + /* Go to the children at maximum level. */ + const int num_children_child = ts->t8_element_num_children (child); + for (int jchild = 0; jchild < num_children_child; jchild++) { + ts->t8_element_child (child, jchild, element); + /* Check the computation of the successor. */ + ASSERT_TRUE (ts->t8_element_equal (element, successor)) << "Wrong Successor at Maxlvl.\n"; + /* Compute the next successor. */ + EXPECT_EQ (ts->t8_element_level (successor), maxlvl); + ts->t8_element_successor (successor, successor); + } + ts->t8_element_parent (child, element); + } +} + +TEST_P (class_successor, test_recursive_and_deep_successor) +{ +#ifdef T8_ENABLE_LESS_TESTS + const int maxlvl = 3; +#else + const int maxlvl = 4; +#endif + + /* Test at lower level. */ + for (int ilevel = 1; ilevel <= maxlvl; ilevel++) { + ts->t8_element_set_linear_id (successor, ilevel, 0); + ts->t8_element_last_descendant (element, last, ilevel); + t8_recursive_successor (element, successor, child, last, ts, ilevel); + } + /* Test at Maxlevel. */ + ts->t8_element_set_linear_id (element, ts->t8_element_maxlevel () - 2, 0); + ts->t8_element_set_linear_id (successor, ts->t8_element_maxlevel (), 0); + t8_deep_successor (element, successor, last, ts); +} + +INSTANTIATE_TEST_SUITE_P (t8_gtest_successor, class_successor, testing::Values(T8_ECLASS_HEX), print_eclass); From 95df1df437e03e5c3098b34061bbb418dcf97485 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 21 May 2024 11:42:06 +0200 Subject: [PATCH 16/55] Added t8_forest_commit test for transitioned forest --- test/Makefile.am | 72 +++++++- .../t8_gtest_forest_commit.cxx | 170 ++++++++++++++++++ 2 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 test/t8_forest_transition/t8_gtest_forest_commit.cxx diff --git a/test/Makefile.am b/test/Makefile.am index f0ade41106..65b2b2653e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -30,8 +30,10 @@ t8code_googletest_programs = \ test/t8_geometry/t8_geometry_implementations/t8_gtest_geometry_lagrange \ test/t8_gtest_cmesh_bcast \ test/t8_schemes/t8_gtest_nca \ + test/t8_schemes_transition/t8_gtest_nca \ test/t8_schemes/t8_gtest_pyra_connectivity \ test/t8_schemes/t8_gtest_face_neigh \ + test/t8_schemes_transition/t8_gtest_face_neigh \ test/t8_geometry/t8_geometry_implementations/t8_gtest_geometry_linear \ test/t8_geometry/t8_geometry_implementations/t8_gtest_geometry_cad \ test/t8_gtest_eclass \ @@ -50,9 +52,11 @@ t8code_googletest_programs = \ test/t8_schemes/t8_gtest_descendant \ test/t8_schemes_transition/t8_gtest_descendant \ test/t8_schemes/t8_gtest_find_parent \ + test/t8_schemes_transition/t8_gtest_find_parent \ test/t8_schemes/t8_gtest_equal \ test/t8_schemes_transition/t8_gtest_equal \ test/t8_schemes/t8_gtest_root \ + test/t8_schemes_transition/t8_gtest_root \ test/t8_cmesh/t8_gtest_cmesh_face_is_boundary \ test/t8_cmesh/t8_gtest_cmesh_partition \ test/t8_cmesh/t8_gtest_cmesh_copy \ @@ -63,6 +67,7 @@ t8code_googletest_programs = \ test/t8_cmesh/t8_gtest_cmesh_add_attributes_when_derive \ test/t8_cmesh/t8_gtest_attribute_gloidx_array \ test/t8_schemes/t8_gtest_successor \ + test/t8_schemes_transition/t8_gtest_successor \ test/t8_schemes/t8_gtest_boundary_extrude \ test/t8_forest/t8_gtest_search \ test/t8_gtest_netcdf_linkage \ @@ -80,6 +85,7 @@ t8code_googletest_programs = \ test/t8_forest/t8_gtest_ghost_delete \ test/t8_forest/t8_gtest_ghost_and_owner \ test/t8_forest/t8_gtest_forest_commit \ + test/t8_forest_transition/t8_gtest_forest_commit \ test/t8_forest/t8_gtest_balance \ test/t8_IO/t8_gtest_vtk_reader \ test/t8_forest_incomplete/t8_gtest_permute_hole \ @@ -90,6 +96,7 @@ t8code_googletest_programs = \ test/t8_cmesh/t8_gtest_cmesh_tree_vertices_negative_volume \ test/t8_schemes/t8_gtest_default \ test/t8_schemes/t8_gtest_pack_unpack \ + test/t8_schemes_transition/t8_gtest_pack_unpack \ test/t8_schemes/t8_gtest_child_parent_face \ test/t8_schemes_transition/t8_gtest_child_parent_face \ test/t8_cmesh_generator/t8_gtest_cmesh_generator_test @@ -106,6 +113,10 @@ test_t8_schemes_t8_gtest_nca_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_nca.cxx +test_t8_schemes_transition_t8_gtest_nca_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_nca.cxx + test_t8_schemes_t8_gtest_pyra_connectivity_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_pyra_connectivity.cxx @@ -114,6 +125,10 @@ test_t8_schemes_t8_gtest_face_neigh_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_face_neigh.cxx +test_t8_schemes_transition_t8_gtest_face_neigh_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_face_neigh.cxx + test_t8_geometry_t8_geometry_implementations_t8_gtest_geometry_linear_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_geometry/t8_geometry_implementations/t8_gtest_geometry_linear.cxx @@ -194,6 +209,10 @@ test_t8_schemes_t8_gtest_find_parent_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_find_parent.cxx +test_t8_schemes_transition_t8_gtest_find_parent_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_find_parent.cxx + test_t8_schemes_t8_gtest_equal_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_equal.cxx @@ -206,6 +225,10 @@ test_t8_schemes_t8_gtest_root_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_root.cxx +test_t8_schemes_transition_t8_gtest_root_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_root.cxx + test_t8_cmesh_t8_gtest_cmesh_face_is_boundary_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_cmesh/t8_gtest_cmesh_face_is_boundary.cxx @@ -238,6 +261,10 @@ test_t8_schemes_t8_gtest_successor_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_successor.cxx +test_t8_schemes_transition_t8_gtest_successor_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_successor.cxx + test_t8_schemes_t8_gtest_boundary_extrude_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_schemes/t8_gtest_boundary_extrude.cxx @@ -306,6 +333,10 @@ test_t8_forest_t8_gtest_forest_commit_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_forest/t8_gtest_forest_commit.cxx +test_t8_forest_transition_t8_gtest_forest_commit_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_forest_transition/t8_gtest_forest_commit.cxx + test_t8_forest_t8_gtest_balance_SOURCES = \ test/t8_gtest_main.cxx \ test/t8_forest/t8_gtest_balance.cxx @@ -340,7 +371,11 @@ test_t8_schemes_t8_gtest_default_SOURCES = \ test_t8_schemes_t8_gtest_pack_unpack_SOURCES = \ test/t8_gtest_main.cxx \ - test/t8_schemes/t8_gtest_pack_unpack.cxx + test/t8_schemes/t8_gtest_pack_unpack.cxx + +test_t8_schemes_transition_t8_gtest_pack_unpack_SOURCES = \ + test/t8_gtest_main.cxx \ + test/t8_schemes_transition/t8_gtest_pack_unpack.cxx test_t8_schemes_t8_gtest_child_parent_face_SOURCES = \ test/t8_gtest_main.cxx \ @@ -374,6 +409,10 @@ test_t8_schemes_t8_gtest_nca_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_nca_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_nca_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_nca_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_nca_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_nca_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_schemes_t8_gtest_pyra_connectivity_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_pyra_connectivity_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_pyra_connectivity_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -382,6 +421,10 @@ test_t8_schemes_t8_gtest_face_neigh_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_face_neigh_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_face_neigh_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_face_neigh_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_face_neigh_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_face_neigh_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_geometry_t8_geometry_implementations_t8_gtest_geometry_linear_LDADD = $(t8_gtest_target_ld_add) test_t8_geometry_t8_geometry_implementations_t8_gtest_geometry_linear_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_geometry_t8_geometry_implementations_t8_gtest_geometry_linear_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -462,6 +505,10 @@ test_t8_schemes_t8_gtest_find_parent_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_find_parent_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_find_parent_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_find_parent_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_find_parent_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_find_parent_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_schemes_t8_gtest_equal_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_equal_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_equal_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -474,6 +521,10 @@ test_t8_schemes_t8_gtest_root_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_root_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_root_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_root_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_root_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_root_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_cmesh_t8_gtest_cmesh_face_is_boundary_LDADD = $(t8_gtest_target_ld_add) test_t8_cmesh_t8_gtest_cmesh_face_is_boundary_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_cmesh_t8_gtest_cmesh_face_is_boundary_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -506,6 +557,10 @@ test_t8_schemes_t8_gtest_successor_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_successor_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_successor_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_successor_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_successor_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_successor_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_schemes_t8_gtest_boundary_extrude_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_boundary_extrude_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_boundary_extrude_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -574,6 +629,10 @@ test_t8_forest_t8_gtest_forest_commit_LDADD = $(t8_gtest_target_ld_add) test_t8_forest_t8_gtest_forest_commit_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_forest_t8_gtest_forest_commit_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_forest_transition_t8_gtest_forest_commit_LDADD = $(t8_gtest_target_ld_add) +test_t8_forest_transition_t8_gtest_forest_commit_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_forest_transition_t8_gtest_forest_commit_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_forest_t8_gtest_balance_LDADD = $(t8_gtest_target_ld_add) test_t8_forest_t8_gtest_balance_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_forest_t8_gtest_balance_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -614,6 +673,10 @@ test_t8_schemes_t8_gtest_pack_unpack_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_pack_unpack_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_pack_unpack_CPPFLAGS = $(t8_gtest_target_cpp_flags) +test_t8_schemes_transition_t8_gtest_pack_unpack_LDADD = $(t8_gtest_target_ld_add) +test_t8_schemes_transition_t8_gtest_pack_unpack_LDFLAGS = $(t8_gtest_target_ld_flags) +test_t8_schemes_transition_t8_gtest_pack_unpack_CPPFLAGS = $(t8_gtest_target_cpp_flags) + test_t8_schemes_t8_gtest_child_parent_face_LDADD = $(t8_gtest_target_ld_add) test_t8_schemes_t8_gtest_child_parent_face_LDFLAGS = $(t8_gtest_target_ld_flags) test_t8_schemes_t8_gtest_child_parent_face_CPPFLAGS = $(t8_gtest_target_cpp_flags) @@ -635,8 +698,10 @@ test_t8_cmesh_t8_gtest_cmesh_copy_CPPFLAGS = $(t8_gtest_target_cpp_flags) if !T8_ENABLE_MPI test_t8_gtest_cmesh_bcast_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_nca_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_nca_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_pyra_connectivity_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_face_neigh_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_face_neigh_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_geometry_t8_geometry_implementations_t8_gtest_geometry_linear_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_geometry_t8_geometry_implementations_t8_gtest_geometry_cad_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_gtest_eclass_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) @@ -656,9 +721,11 @@ test_t8_geometry_t8_gtest_geometry_handling_CPPFLAGS += $(t8_gtest_target_mpi_cp test_t8_schemes_t8_gtest_descendant_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_transition_t8_gtest_descendant_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_find_parent_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_find_parent_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_equal_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_transition_t8_gtest_equal_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_root_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_root_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_t8_gtest_cmesh_face_is_boundary_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_t8_gtest_cmesh_partition_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_t8_gtest_cmesh_set_partition_offsets_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) @@ -667,6 +734,7 @@ test_t8_cmesh_t8_gtest_multiple_attributes_CPPFLAGS += $(t8_gtest_target_mpi_cpp test_t8_cmesh_t8_gtest_cmesh_add_attributes_when_derive_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_t8_gtest_attribute_gloidx_array_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_successor_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_successor_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_boundary_extrude_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_forest_t8_gtest_search_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_gtest_netcdf_linkage_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) @@ -684,6 +752,7 @@ test_t8_forest_t8_gtest_ghost_exchange_CPPFLAGS += $(t8_gtest_target_mpi_cpp_fla test_t8_forest_t8_gtest_ghost_delete_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_forest_t8_gtest_ghost_and_owner_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_forest_t8_gtest_forest_commit_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_forest_transition_t8_gtest_forest_commit_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_forest_t8_gtest_balance_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_IO_t8_gtest_vtk_reader_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_forest_incomplete_t8_gtest_permute_hole_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) @@ -694,6 +763,7 @@ test_t8_forest_incomplete_t8_gtest_empty_global_tree_CPPFLAGS += $(t8_gtest_targ test_t8_cmesh_t8_gtest_cmesh_tree_vertices_negative_volume_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_default_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_pack_unpack_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) +test_t8_schemes_transition_t8_gtest_pack_unpack_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_t8_gtest_child_parent_face_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_schemes_transition_t8_gtest_child_parent_face_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) test_t8_cmesh_generator_t8_gtest_cmesh_generator_test_CPPFLAGS += $(t8_gtest_target_mpi_cpp_flags) diff --git a/test/t8_forest_transition/t8_gtest_forest_commit.cxx b/test/t8_forest_transition/t8_gtest_forest_commit.cxx new file mode 100644 index 0000000000..2cd7e1df4b --- /dev/null +++ b/test/t8_forest_transition/t8_gtest_forest_commit.cxx @@ -0,0 +1,170 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/t8_cmesh_generator/t8_cmesh_example_sets.hxx" +#include +#include +#include + +/* In this test, we adapt, balance and partition a uniform forest. + * We do this in two ways: + * 1st All operations are performed in one single call to t8_forest_commit + * 2nd Each intermediate step is performed in a separate commit + * + * After these two forests are created, we check for equality. + */ + + + +/* Adapt a forest such that always the first child of a + * tree is refined and no other elements. This results in a highly + * imbalanced forest. */ +static int +t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, const int is_family, const int num_elements, t8_element_t *elements[]) +{ + T8_ASSERT (!is_family || (is_family && num_elements == ts->t8_element_num_children (elements[0]))); + + int level = ts->t8_element_level (elements[0]); + + /* we set a maximum refinement level as forest user data */ + int maxlevel = *(int *) t8_forest_get_user_data (forest); + if (level >= maxlevel) { + /* Do not refine after the maxlevel */ + return 0; + } + int child_id = ts->t8_element_child_id (elements[0]); + if (child_id == 1) { + return 1; + } + return 0; +} + +/* adapt, balance and partition a given forest in one step */ +static t8_forest_t +t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) +{ + t8_debugf("---------start t8_test_forest_commit_abp ---------------------\n"); + + t8_forest_t forest_ada_bal_par; + + /* Adapt, balance and partition the uniform forest */ + t8_forest_init (&forest_ada_bal_par); + /* Set user data for adapt */ + t8_forest_set_user_data (forest_ada_bal_par, &maxlevel); + t8_forest_set_adapt (forest_ada_bal_par, forest, t8_test_adapt_balance, 1); + t8_forest_set_balance (forest_ada_bal_par, NULL, 0); + t8_forest_set_transition(forest_ada_bal_par, NULL, 0); + t8_forest_set_partition (forest_ada_bal_par, NULL, 0); + t8_forest_commit (forest_ada_bal_par); + + t8_debugf("---------finsish t8_test_forest_commit_abp ---------------------\n"); + return forest_ada_bal_par; +} + +/* adapt, balance and partition a given forest in 3 steps */ +static t8_forest_t +t8_test_forest_commit_abp_3step (t8_forest_t forest, int maxlevel) +{ + t8_forest_t forest_adapt; + t8_forest_t forest_balance; + t8_forest_t forest_partition; + + t8_forest_init (&forest_adapt); + t8_forest_init (&forest_balance); + t8_forest_init (&forest_partition); + + /* adapt the forest */ + t8_forest_set_user_data (forest_adapt, &maxlevel); + t8_forest_set_adapt (forest_adapt, forest, t8_test_adapt_balance, 1); + t8_forest_commit (forest_adapt); + + /* balance the forest */ + t8_forest_set_balance (forest_balance, forest_adapt, 0); + t8_forest_commit (forest_balance); + + /* partrition the forest */ + t8_forest_set_partition (forest_partition, forest_balance, 0); + t8_forest_commit (forest_partition); + + return forest_partition; +} + +TEST (forest_commit, test_forest_commit) +{ + t8_cmesh_t cmesh; + t8_forest_t forest; + t8_forest_t forest_ada_bal_part; + t8_forest_t forest_abp_3part; + + const int level_step = 0; + /* construct a single tree hex cmesh */ + cmesh = t8_cmesh_new_hypercube (T8_ECLASS_HEX, sc_MPI_COMM_WORLD, 0, 0, 0); + /* ref the cmesh since we reuse it */ + t8_cmesh_ref (cmesh); + + t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); + sizeof(t8_hex_with_subelements); + t8_debugf("size of p8est quadrant %li \n",sizeof(p8est_quadrant_t) ); + + t8_debugf("size of t8_hex_with_subelements %li \n",sizeof(t8_hex_with_subelements) ); + t8_scheme_cxx_ref (scheme); + + /* Compute the first level, such that no process is empty */ + // int min_level = t8_forest_min_nonempty_level (cmesh, scheme); + // // /* Use one level with empty processes */ + // min_level = SC_MAX (min_level - 1, 0); + int maxlevel = 2; + for (int level = 0; level <= maxlevel; level++) { + t8_debugf ("Testing forest commit level %i\n", level); + + + /* Create a uniformly refined forest */ + forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); + /* We need to use forest twice, so we ref it */ + // t8_forest_ref (forest); + /* Adapt, balance and partition the forest */ + // forest_ada_bal_part = t8_test_forest_commit_abp (forest, maxlevel); + /* Adapt, balance and partition the forest using three separate steps */ + // forest_abp_3part = t8_test_forest_commit_abp_3step (forest, maxlevel); + + // ASSERT_TRUE (t8_forest_is_equal (forest_abp_3part, forest_ada_bal_part)) << "The forests are not equal"; + t8_forest_unref (&forest); + + // t8_forest_unref (&forest_ada_bal_part); + // t8_forest_unref (&forest_abp_3part); + } + + t8_scheme_cxx_unref (&scheme); + t8_cmesh_unref(&cmesh); + t8_debugf ("Done testing forest commit."); +} + + From 7bc5d0060e2ed17e2b6aab32e9a3d47e4cf54e6a Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 22 May 2024 11:05:00 +0200 Subject: [PATCH 17/55] Added test file for forest commit + corrections in t8_element_new + _init --- src/t8_forest/t8_forest.c | 130 ++++++++++++++---- src/t8_forest/t8_forest_adapt.cxx | 2 +- src/t8_forest/t8_forest_balance.cxx | 2 + src/t8_forest/t8_forest_cxx.cxx | 6 +- src/t8_forest/t8_forest_general.h | 7 + src/t8_forest/t8_forest_partition.cxx | 2 +- .../t8_transition_conformal_hex.cxx | 3 +- .../t8_transition_conformal_hex_cxx.cxx | 92 ++++++------- .../t8_transition_conformal_hex_cxx.hxx | 45 +++--- .../t8_gtest_forest_commit.cxx | 31 +++-- 10 files changed, 210 insertions(+), 110 deletions(-) diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index 196b19f717..ffcefe59c4 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -62,6 +62,7 @@ t8_forest_init (t8_forest_t *pforest) forest->stats_computed = 0; forest->incomplete_trees = -1; forest->set_subelements = 0; + forest->is_transitioned = 0; } int @@ -261,6 +262,7 @@ t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, T8_ASSERT (t8_forest_is_initialized (forest)); if (set_transition_with_balance) { + t8_debugf("-------------set transition with balance -------------\n"); /* balance with repartition */ t8_forest_set_balance (forest, set_from, 0); } @@ -393,19 +395,6 @@ t8_forest_comm_global_num_elements (t8_forest_t forest) forest->global_num_elements = global_num_el; } -void -t8_forest_comm_global_num_subelements (t8_forest_t forest) -{ - int mpiret; - t8_gloidx_t local_num_subel; - t8_gloidx_t global_num_subel; - - local_num_subel = (t8_gloidx_t) forest->local_num_subelements; - mpiret = sc_MPI_Allreduce (&local_num_subel, &global_num_subel, 1, - T8_MPI_GLOIDX, sc_MPI_SUM, forest->mpicomm); - SC_CHECK_MPI (mpiret); - forest->global_num_subelements = global_num_subel; -} /** Adapt callback function to refine every element in the forest. * It is merely used to build a new forest with pyramids. * @@ -458,7 +447,6 @@ t8_forest_refines_irregular (t8_forest_t forest) /* Combine the process-local results via a logic or and distribute the result over all procs (in the communicator).*/ mpiret = sc_MPI_Allreduce (&irregular, &irregular_all_procs, 1, sc_MPI_INT, sc_MPI_LOR, forest->mpicomm); SC_CHECK_MPI (mpiret); - return irregular_all_procs; } @@ -476,11 +464,14 @@ t8_forest_populate_irregular (t8_forest_t forest) t8_forest_t forest_tmp_partition; t8_cmesh_ref (forest->cmesh); t8_scheme_cxx_ref (forest->scheme_cxx); + t8_debugf("scheme adresse anfang populate irregular %p\n", forest->scheme_cxx); /* We start with a level 0 uniform refinement */ t8_forest_init (&forest_zero); t8_forest_set_level (forest_zero, 0); t8_forest_set_cmesh (forest_zero, forest->cmesh, forest->mpicomm); t8_forest_set_scheme (forest_zero, forest->scheme_cxx); + t8_debugf("set level in populate irregular %i\n", forest->set_level); + t8_forest_commit (forest_zero); /* Up to the specified level we refine every element. */ for (int i = 1; i <= forest->set_level; i++) { @@ -492,16 +483,22 @@ t8_forest_populate_irregular (t8_forest_t forest) t8_forest_init (&forest_tmp_partition); t8_forest_set_partition (forest_tmp_partition, forest_tmp, 0); t8_forest_commit (forest_tmp_partition); + t8_debugf("-------------end populate irregular ---------\n"); + forest_zero = forest_tmp_partition; } + /* Copy all elements over to the original forest. */ t8_forest_copy_trees (forest, forest_zero, 1); + t8_forest_unref (&forest_tmp_partition); + t8_debugf("-------------end populate irregular ---------\n"); } void t8_forest_commit (t8_forest_t forest) { + t8_debugf("scheme adresse anfang commit %p\n", forest->scheme_cxx); int mpiret; int partitioned = 0; sc_MPI_Comm comm_dup; @@ -515,6 +512,7 @@ t8_forest_commit (t8_forest_t forest) } if (forest->set_from == NULL) { + t8_global_productionf("-----------set_from == NULL-------------\n"); /* This forest is constructed solely from its cmesh as a uniform * forest */ T8_ASSERT (forest->mpicomm != sc_MPI_COMM_NULL); @@ -522,7 +520,8 @@ t8_forest_commit (t8_forest_t forest) T8_ASSERT (forest->scheme_cxx != NULL); T8_ASSERT (forest->from_method == T8_FOREST_FROM_LAST); T8_ASSERT (forest->incomplete_trees == -1); - + T8_ASSERT (forest->set_subelements == 0); + T8_ASSERT (forest->is_transitioned == 0); /* dup communicator if requested */ if (forest->do_dup) { mpiret = sc_MPI_Comm_dup (forest->mpicomm, &comm_dup); @@ -530,30 +529,35 @@ t8_forest_commit (t8_forest_t forest) forest->mpicomm = comm_dup; } forest->dimension = forest->cmesh->dimension; - /* Set mpirank and mpisize */ mpiret = sc_MPI_Comm_size (forest->mpicomm, &forest->mpisize); SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Comm_rank (forest->mpicomm, &forest->mpirank); SC_CHECK_MPI (mpiret); /* Compute the maximum allowed refinement level */ t8_forest_compute_maxlevel (forest); T8_ASSERT (forest->set_level <= forest->maxlevel); + /* populate a new forest with tree and quadrant objects */ if (t8_forest_refines_irregular (forest) && forest->set_level > 0) { + t8_global_productionf("----------- refines irregular-------------\n"); /* On root level we will also use the normal algorithm */ - t8_forest_populate_irregular (forest); } else { - t8_global_productionf("-----------regular-------------\n"); + t8_global_productionf("-----------refines regular-------------\n"); t8_forest_populate (forest); } forest->global_num_trees = t8_cmesh_get_num_trees (forest->cmesh); forest->incomplete_trees = 0; + forest->is_transitioned = 0; } - else { /* set_from != NULL */ + else { + t8_global_productionf("-----------set_from != NULL-------------\n"); + + /* set_from != NULL */ t8_forest_t forest_from = forest->set_from; /* temporarily store set_from, since we may overwrite it */ T8_ASSERT (forest->mpicomm == sc_MPI_COMM_NULL); @@ -592,6 +596,7 @@ t8_forest_commit (t8_forest_t forest) /* Compute the maximum allowed refinement level */ t8_forest_compute_maxlevel (forest); + t8_debugf("Forest from method anfang commit %i\n", forest->from_method); if (forest->from_method == T8_FOREST_FROM_COPY) { SC_CHECK_ABORT (forest->set_from != NULL, "No forest to copy from was specified."); t8_forest_copy_trees (forest, forest->set_from, 1); @@ -601,11 +606,14 @@ t8_forest_commit (t8_forest_t forest) /* T8_ASSERT (forest->from_method == T8_FOREST_FROM_COPY); */ if (forest->from_method & T8_FOREST_FROM_ADAPT) { SC_CHECK_ABORT (forest->set_adapt_fn != NULL, "No adapt function specified"); + t8_debugf("from method von forest in adapt %i\n",forest->from_method ); + forest->from_method -= T8_FOREST_FROM_ADAPT; if (forest->from_method > 0) { /* The forest should also be partitioned/balanced/transitioned. * We first untransition the forest, then adapt the forest, then balance and then partition and then possibly transition the forest again*/ - if (forest->is_transitioned){ + if (forest->set_from->is_transitioned){ + T8_ASSERT(forest->is_transitioned == 0); t8_forest_untransition(forest); T8_ASSERT (!t8_forest_is_transitioned (forest)); } @@ -635,18 +643,21 @@ t8_forest_commit (t8_forest_t forest) /* This forest should only be adapted */ t8_forest_copy_trees (forest, forest->set_from, 0); /* The input forest for forest_adapt() should always be a non-transitioned forest.*/ - if (forest->is_transitioned){ + if (forest->set_from->is_transitioned){ t8_forest_untransition(forest); T8_ASSERT (!t8_forest_is_transitioned (forest)); } t8_forest_adapt (forest); + forest->is_transitioned = 0; } } if (forest->from_method & T8_FOREST_FROM_PARTITION) { + t8_debugf("from method in partition %i\n",forest->from_method ); partitioned = 1; /* Partition this forest */ forest->from_method -= T8_FOREST_FROM_PARTITION; + // t8_debugf("from method nach partition %i\n",forest->from_method ); if (forest->from_method > 0) { /* The forest should also be balanced after partition */ @@ -679,13 +690,34 @@ t8_forest_commit (t8_forest_t forest) forest->trees = sc_array_new (sizeof (t8_tree_struct_t)); /* partition the forest */ t8_forest_partition (forest); + } } if (forest->from_method & T8_FOREST_FROM_BALANCE) { + t8_debugf("from method in balance %i\n",forest->from_method ); /* balance the forest */ forest->from_method -= T8_FOREST_FROM_BALANCE; - /* This is the last from method that we execute, - * nothing should be left todo */ + if (forest->from_method > 0) { + int flag_rep; + if (forest->set_balance == T8_FOREST_BALANCE_NO_REPART) { + /* balance without repartition */ + flag_rep = 1; + } + else { + /* balance with repartition */ + flag_rep = 0; + } + /* in this case, we will use subelements after balancing */ + t8_forest_t forest_balance; + t8_forest_init (&forest_balance); + /* forest_adapt should not change ownership of forest->set_from */ + t8_forest_set_balance (forest_balance, forest->set_from, flag_rep); + t8_forest_commit (forest_balance); + /* The new forest will be partitioned/balanced from forest_adapt */ + forest->set_from = forest_balance; + } + else{ + /* TOnly execute t8_balance. It is possible to call t8_transition afterwards. */ T8_ASSERT (forest->from_method == 0); /* This forest should only be balanced */ @@ -697,13 +729,17 @@ t8_forest_commit (t8_forest_t forest) /* balance with repartition */ t8_forest_balance (forest, 1); } + + } + forest->is_transitioned = 0; } if (forest->from_method & T8_FOREST_FROM_TRANSITION) { + t8_debugf("from method in transition %i\n",forest->from_method ); forest->from_method -= T8_FOREST_FROM_TRANSITION; /* this is the last from method that we execute, * nothing should be left todo */ T8_ASSERT (forest->from_method == 0); - T8_ASSERT (t8_forest_is_balanced(forest)); + // T8_ASSERT (t8_forest_is_balanced(forest)); /* use subelements */ t8_forest_transition (forest); forest->is_transitioned = 1; @@ -712,12 +748,13 @@ t8_forest_commit (t8_forest_t forest) /* decrease reference count of intermediate input forest, possibly destroying it */ t8_forest_unref (&forest->set_from); } + t8_debugf(" forest_from == forest->set_from\n"); + /* reset forest->set_from */ forest->set_from = forest_from; /* decrease reference count of input forest, possibly destroying it */ t8_forest_unref (&forest->set_from); } /* end set_from != NULL */ - /* Compute the element offset of the trees */ t8_forest_compute_elements_offset (forest); @@ -733,18 +770,26 @@ t8_forest_commit (t8_forest_t forest) "global elements.\n\tTree range is from %lli to %lli.\n", (long) forest->local_num_elements, (long long) forest->global_num_elements, (long long) forest->first_local_tree, (long long) forest->last_local_tree); - +//ist gleich NULL wenn wir nur einen Baum haben if (forest->tree_offsets == NULL) { /* Compute the tree offset array */ t8_forest_partition_create_tree_offsets (forest); + t8_debugf("Scheme nach forest->tree_offsets == NULL \n"); + } + //ist gleich Null wenn wir nur einen Baum haben if (forest->element_offsets == NULL) { /* Compute element offsets */ t8_forest_partition_create_offsets (forest); + + } if (forest->global_first_desc == NULL) { + /* Compute global first desc array */ t8_forest_partition_create_first_desc (forest); + // t8_debugf("Scheme nach global first desc == NULL %p\n", forest->scheme_cxx); + } if (forest->profile != NULL) { @@ -782,6 +827,8 @@ t8_forest_commit (t8_forest_t forest) #ifdef T8_ENABLE_DEBUG t8_forest_partition_test_boundary_element (forest); #endif + t8_debugf("scheme adresse Ende commit %p\n", forest->scheme_cxx); + } t8_locidx_t @@ -800,6 +847,29 @@ t8_forest_get_global_num_elements (const t8_forest_t forest) return forest->global_num_elements; } +t8_gloidx_t +t8_forest_get_global_num_subelements (t8_forest_t forest) +{ + T8_ASSERT (forest->global_num_subelements <= forest->global_num_elements); + T8_ASSERT (t8_forest_is_committed (forest)); + + return forest->global_num_subelements; +} + +void +t8_forest_comm_global_num_subelements (t8_forest_t forest) +{ + int mpiret; + t8_gloidx_t local_num_subel; + t8_gloidx_t global_num_subel; + + local_num_subel = (t8_gloidx_t) forest->local_num_subelements; + mpiret = sc_MPI_Allreduce (&local_num_subel, &global_num_subel, 1, + T8_MPI_GLOIDX, sc_MPI_SUM, forest->mpicomm); + SC_CHECK_MPI (mpiret); + forest->global_num_subelements = global_num_subel; +} + t8_locidx_t t8_forest_get_num_ghosts (const t8_forest_t forest) { @@ -1451,6 +1521,7 @@ t8_forest_profile_get_balance (t8_forest_t forest, int *balance_rounds) void t8_forest_compute_elements_offset (t8_forest_t forest) { + t8_locidx_t itree, num_trees; t8_locidx_t current_offset; t8_tree_t tree; @@ -1459,6 +1530,8 @@ t8_forest_compute_elements_offset (t8_forest_t forest) /* Get the number of local trees */ num_trees = t8_forest_get_num_local_trees (forest); + + current_offset = 0; /* Iterate through all trees, sum up the element counts and set it as * the element_offsets */ @@ -1466,6 +1539,7 @@ t8_forest_compute_elements_offset (t8_forest_t forest) tree = t8_forest_get_tree (forest, itree); tree->elements_offset = current_offset; current_offset += t8_forest_get_tree_element_count (tree); + } /* At the end, we counted all elements */ T8_ASSERT (current_offset == forest->local_num_elements); @@ -1526,6 +1600,7 @@ t8_forest_new_uniform (t8_cmesh_t cmesh, t8_scheme_cxx_t *scheme, const int leve /* Initialize the forest */ t8_forest_init (&forest); + T8_ASSERT(t8_forest_is_initialized(forest)); /* Set the cmesh, scheme and level */ t8_forest_set_cmesh (forest, cmesh, comm); t8_forest_set_scheme (forest, scheme); @@ -1572,6 +1647,9 @@ t8_forest_free_trees (t8_forest_t forest) number_of_trees = forest->trees->elem_count; for (jt = 0; jt < number_of_trees; jt++) { tree = (t8_tree_t) t8_sc_array_index_locidx (forest->trees, jt); + t8_debugf("anzahl element in baum %i \n", t8_forest_get_tree_element_count (tree)); + t8_debugf("anzahl bäume %i \n", number_of_trees); + if (t8_forest_get_tree_element_count (tree) < 1) { /* if local tree is empty */ T8_ASSERT (forest->incomplete_trees); diff --git a/src/t8_forest/t8_forest_adapt.cxx b/src/t8_forest/t8_forest_adapt.cxx index bcbe5701c9..6c2242709a 100644 --- a/src/t8_forest/t8_forest_adapt.cxx +++ b/src/t8_forest/t8_forest_adapt.cxx @@ -744,7 +744,7 @@ t8_forest_adapt (t8_forest_t forest) * even if you do not want this output. It fixes a bug that occurred on JUQUEEN, where the * runtimes were computed to 0. * Only delete the line, if you know what you are doing. */ - t8_global_productionf ("End adadpt %f %f\n", sc_MPI_Wtime (), forest->profile->adapt_runtime); + t8_global_productionf ("End adapt %f %f\n", sc_MPI_Wtime (), forest->profile->adapt_runtime); } } diff --git a/src/t8_forest/t8_forest_balance.cxx b/src/t8_forest/t8_forest_balance.cxx index 3537311b6b..8dcb1f9970 100644 --- a/src/t8_forest/t8_forest_balance.cxx +++ b/src/t8_forest/t8_forest_balance.cxx @@ -180,6 +180,7 @@ t8_forest_balance (t8_forest_t forest, int repartition) T8_ASSERT (forest_from->maxlevel_existing >= 0); /* Initialize the temp forest to be adapted from forest_from */ t8_forest_init (&forest_temp); + t8_debugf("forest temp is transitioned %i und forest from is transitioned %i\n", forest_temp->is_transitioned, forest_from->is_transitioned); /* Update the maximum occurring level */ forest_temp->maxlevel_existing = forest_from->maxlevel_existing; /* Adapt the forest */ @@ -193,6 +194,7 @@ t8_forest_balance (t8_forest_t forest, int repartition) t8_forest_set_profiling (forest_temp, 1); } t8_global_productionf ("Profiling: %i\n", forest->profile != NULL); + /* Adapt the forest */ t8_forest_commit (forest_temp); /* Store the runtimes of adapt and ghost */ diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index 0981dfd492..36db821886 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -183,6 +184,8 @@ t8_forest_compute_maxlevel (t8_forest_t forest) /* If there are trees of this class, compute the maxlevel of the class */ ts = t8_forest_get_eclass_scheme_before_commit (forest, (t8_eclass_t) eclass_it); maxlevel = ts->t8_element_maxlevel (); + + /* Compute the minimum of this level and the stored maxlevel */ if (forest->maxlevel == -1) { forest->maxlevel = maxlevel; @@ -1155,7 +1158,7 @@ t8_forest_populate (t8_forest_t forest) t8_eclass_scheme_c *eclass_scheme; t8_gloidx_t cmesh_first_tree, cmesh_last_tree; int is_empty; - + SC_CHECK_ABORT (forest->set_level <= forest->maxlevel, "Given refinement level exceeds the maximum.\n"); /* TODO: create trees and quadrants according to uniform refinement */ t8_cmesh_uniform_bounds (forest->cmesh, forest->set_level, forest->scheme_cxx, &forest->first_local_tree, @@ -1411,6 +1414,7 @@ t8_forest_copy_trees (t8_forest_t forest, t8_forest_t from, int copy_elements) forest->local_num_elements = from->local_num_elements; forest->global_num_elements = from->global_num_elements; forest->incomplete_trees = from->incomplete_trees; + forest->is_transitioned = from->is_transitioned; } else { forest->local_num_elements = 0; diff --git a/src/t8_forest/t8_forest_general.h b/src/t8_forest/t8_forest_general.h index f2b7c572fa..3bf4b79522 100644 --- a/src/t8_forest/t8_forest_general.h +++ b/src/t8_forest/t8_forest_general.h @@ -386,6 +386,13 @@ t8_forest_comm_global_num_elements (t8_forest_t forest); void t8_forest_comm_global_num_subelements (t8_forest_t forest); +/** Return the number of global subelements in the forest. + * \param [in] forest A forest. + * \return The number of subelements (summed over all processes) in \a forest. + * \a forest must be committed before calling this function. + */ +t8_gloidx_t t8_forest_get_global_num_subelements (t8_forest_t forest); + /** Set a source forest to use subelements during commit, that will remove hanging faces from the adapted mesh. * \param [in, out] forest The forest. diff --git a/src/t8_forest/t8_forest_partition.cxx b/src/t8_forest/t8_forest_partition.cxx index b8ff2cb8a3..52e79d90a4 100644 --- a/src/t8_forest/t8_forest_partition.cxx +++ b/src/t8_forest/t8_forest_partition.cxx @@ -130,7 +130,7 @@ t8_forest_partition_test_desc (t8_forest_t forest) /* This forest is empty, nothing to do */ return; } - + tree = t8_forest_get_tree (forest, 0); ts = t8_forest_get_eclass_scheme (forest, tree->eclass); /* Get the first descendant id of this rank */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx index b67f463731..456cf04142 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -42,7 +43,7 @@ t8_scheme_new_transition_hex_cxx (void) t8_refcount_init (&s->rc); s->eclass_schemes[T8_ECLASS_VERTEX] = NULL; - s->eclass_schemes[T8_ECLASS_LINE] = NULL; + s->eclass_schemes[T8_ECLASS_LINE] = new t8_default_scheme_line_c (); s->eclass_schemes[T8_ECLASS_QUAD] = new t8_default_scheme_quad_c (); s->eclass_schemes[T8_ECLASS_HEX] = new t8_subelement_scheme_hex_c (); s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 43afaece64..0224144c17 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1134,8 +1134,7 @@ t8_linearidx_t T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); - // return p8est_quadrant_linear_id ((p8est_quadrant_t *) q, level); - return p8est_quadrant_linear_id ( q, level); + return p8est_quadrant_linear_id ((p8est_quadrant_t *) q, level); } void @@ -1185,8 +1184,9 @@ t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (desc)); T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); + // p8est_quadrant_last_descendant (q, r, level); + p8est_quadrant_last_descendant ((p8est_quadrant_t *) elem, (p8est_quadrant_t *) desc, level); - p8est_quadrant_last_descendant (q, r, level); /* We allow constructing a last descendant from a subelement. * Keep in mind, that transforming a hex element to a subelement does not change the @@ -2863,12 +2863,11 @@ t8_subelement_scheme_hex_c::t8_element_new (int length, t8_element_t **elem) con /* allocate memory */ t8_default_scheme_common_c::t8_element_new (length, elem); - int elem_count; - for (elem_count = 0; elem_count < length; elem_count++) { + for (int i = 0; i < length; i++) { t8_hex_with_subelements *phex_w_sub = - (t8_hex_with_subelements *) elem[elem_count]; - t8_element_init (1, elem[elem_count]); - T8_QUAD_SET_TDIM ((p8est_quadrant_t *) & phex_w_sub->p8q, 3); + (t8_hex_with_subelements *) elem[i]; + t8_element_init (1, elem[i]); + T8_QUAD_SET_TDIM ( (p8est_quadrant_t *) & phex_w_sub->p8q, 3); } } @@ -2877,22 +2876,18 @@ t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem) con { t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; - int elem_count; - - for (elem_count = 0; elem_count < length; elem_count++) { + for (int i = 0; i < length; i++) { /* initialize subelement parameters */ - phex_w_sub[elem_count].transition_type = 0; - phex_w_sub[elem_count].subelement_id = 0; - + phex_w_sub[i].transition_type = 0; + phex_w_sub[i].subelement_id = 0; #ifdef T8_ENABLE_DEBUG /* In debugging mode we iterate over all length many elements and * set their hex to the level 0 hex with ID 0. */ - p8est_quadrant_t *hex = &phex_w_sub[elem_count].p8q; - for (int i = 0; i < length; i++) { - p8est_quadrant_set_morton (hex + i, 0, 0); - T8_QUAD_SET_TDIM (hex + i, 3); - T8_ASSERT (p8est_quadrant_is_extended (hex + i)); - } + p8est_quadrant_t *hex = &phex_w_sub[i].p8q; + p8est_quadrant_set_morton (hex, 0, 0); + T8_QUAD_SET_TDIM (hex, 3); + T8_ASSERT (p8est_quadrant_is_extended (hex)); + #endif } } @@ -2925,34 +2920,8 @@ t8_subelement_scheme_hex_c::t8_element_root (t8_element_t *elem) const{ } -// void -// t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem) const{ -// SC_ABORT_NOT_REACHED(); -// } #ifdef T8_ENABLE_DEBUG -void -t8_subelement_scheme_hex_c::t8_element_debug_print (const t8_element_t *elem) const -{ - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; - t8_productionf ("\n|------------ t8_element_debug_print: ------------|" - "\n| Transition Type: %i" - "\n| Subelement ID: %i" - "\n| Anchor (Morton): (%i,%i,%i)" - "\n| Anchor (ref coords): (%lf,%lf,%lf)" - "\n| Level: %i" - "\n|-------------------------------------------------|\n", - phex_w_sub->transition_type, phex_w_sub->subelement_id, - phex_w_sub->p8q.x, phex_w_sub->p8q.y,phex_w_sub->p8q.z, - (double) phex_w_sub->p8q.x / (double) P8EST_ROOT_LEN, - (double) phex_w_sub->p8q.y / (double) P8EST_ROOT_LEN, - (double) phex_w_sub->p8q.z / (double) P8EST_ROOT_LEN, - phex_w_sub->p8q.level); - - /* if the element is not valid, abort, but after printing */ - T8_ASSERT (t8_element_is_valid (elem)); -} /* *INDENT-OFF* */ /* indent bug, indent adds a second "const" modifier */ @@ -2986,8 +2955,8 @@ t8_subelement_scheme_hex_c::t8_element_subelement_values_are_valid (const return ((phex_w_sub->transition_type >= 0 && phex_w_sub->transition_type <= T8_SUB_HEX_MAX_TRANSITION_TYPE) && - ((phex_w_sub->subelement_id >= 0 && - phex_w_sub->subelement_id <= T8_SUB_HEX_MAX_SUBELEMENT_ID))); + (phex_w_sub->subelement_id >= 0 && + phex_w_sub->subelement_id <= T8_SUB_HEX_MAX_SUBELEMENT_ID)); } void @@ -3000,6 +2969,33 @@ t8_subelement_scheme_hex_c::t8_element_to_string (const t8_element_t *elem, char snprintf (debug_string, string_size, "x: %i, y: %i, z: %i, level: %i", hex->x, hex->y, hex->z, hex->level); } + +void +t8_subelement_scheme_hex_c::t8_element_debug_print (const t8_element_t *elem) const +{ + const t8_hex_with_subelements *phex_w_sub = + (const t8_hex_with_subelements *) elem; + + t8_productionf ("\n|------------ t8_element_debug_print: ------------|" + "\n| Transition Type: %i" + "\n| Subelement ID: %i" + "\n| Anchor (Morton): (%i,%i,%i)" + "\n| Anchor (ref coords): (%lf,%lf,%lf)" + "\n| Level: %i" + "\n|-------------------------------------------------|\n", + phex_w_sub->transition_type, phex_w_sub->subelement_id, + phex_w_sub->p8q.x, phex_w_sub->p8q.y,phex_w_sub->p8q.z, + (double) phex_w_sub->p8q.x / (double) P8EST_ROOT_LEN, + (double) phex_w_sub->p8q.y / (double) P8EST_ROOT_LEN, + (double) phex_w_sub->p8q.z / (double) P8EST_ROOT_LEN, + phex_w_sub->p8q.level); + + /* if the element is not valid, abort, but after printing */ + T8_ASSERT (t8_element_is_valid (elem)); + +} + + #endif /* each hex is packed as x,y,z coordinates, the subelement ID, transition type and the level */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 8e4f06ca9c..aa86f2a4e4 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -69,9 +69,10 @@ typedef struct /* p8est quadrant */ p8est_quadrant_t p8q; /* stores transition cell information (default for non-subelements is 0 and for subelements it is != 0 - is therefore used as a is_subelement check) */ - int transition_type; + int transition_type; /* stores subelement information (default for non-subelements is 0) */ - int subelement_id; + int subelement_id; + } t8_hex_with_subelements; typedef t8_hex_with_subelements t8_phex_sub_t; @@ -88,35 +89,37 @@ typedef t8_hex_with_subelements t8_phex_sub_t; #define T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL 1 /** Return the toplevel dimension. */ -#define T8_QUAD_GET_TDIM(quad) ((int) (quad)->pad8) +// #define T8_QUAD_GET_TDIM(quad) ((int) (quad)->pad8) /** Return the direction of the third dimension. * This is only valid to call if the toplevel dimension is three. */ -#define T8_QUAD_GET_TNORMAL(quad) \ - ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ - ((int) (quad)->pad16) ) +// #define T8_QUAD_GET_TNORMAL(quad) \ +// ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ +// ((int) (quad)->pad16) ) /** Return the coordinate in the third dimension. * This is only valid to call if the toplevel dimension is three. */ -#define T8_QUAD_GET_TCOORD(quad) \ - ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ - ((int) (quad)->p.user_long) ) +// #define T8_QUAD_GET_TCOORD(quad) \ +// ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ +// ((int) (quad)->p.user_long) ) /** Set the toplevel dimension of a hexahedron. */ -#define T8_QUAD_SET_TDIM(quad,dim) \ - do { T8_ASSERT ((dim) == 2 || (dim) == 3); \ - (quad)->pad8 = (int8_t) (dim); } while (0) +#define T8_QUAD_SET_TDIM(quad, dim) \ + do { \ + T8_ASSERT ((dim) == 2 || (dim) == 3); \ + (quad)->pad8 = (int8_t) (dim); \ + } while (0) -/** Set the direction of the third dimension. */ -#define T8_QUAD_SET_TNORMAL(quad,normal) \ - do { T8_ASSERT ((normal) >= 0 && (normal) < 3); \ - (quad)->pad16 = (int16_t) (normal); } while (0) +// /** Set the direction of the third dimension. */ +// #define T8_QUAD_SET_TNORMAL(quad,normal) \ +// do { T8_ASSERT ((normal) >= 0 && (normal) < 3); \ +// (quad)->pad16 = (int16_t) (normal); } while (0) -/** Set the coordinate in the third dimension. */ -#define T8_QUAD_SET_TCOORD(quad,coord) \ - do { (quad)->p.user_long = (long) (coord); } while (0) +// /** Set the coordinate in the third dimension. */ +// #define T8_QUAD_SET_TCOORD(quad,coord) \ +// do { (quad)->p.user_long = (long) (coord); } while (0) #if 0 /** Provide an implementation for the hexahedral element class with subelements. */ @@ -604,7 +607,9 @@ protected: * \param [in] elem The element to print */ virtual void - t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const; + t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const; + + #endif }; diff --git a/test/t8_forest_transition/t8_gtest_forest_commit.cxx b/test/t8_forest_transition/t8_gtest_forest_commit.cxx index 2cd7e1df4b..2eb222faba 100644 --- a/test/t8_forest_transition/t8_gtest_forest_commit.cxx +++ b/test/t8_forest_transition/t8_gtest_forest_commit.cxx @@ -61,7 +61,7 @@ t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t return 0; } int child_id = ts->t8_element_child_id (elements[0]); - if (child_id == 1) { + if (child_id == 0) { return 1; } return 0; @@ -79,7 +79,7 @@ t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) t8_forest_init (&forest_ada_bal_par); /* Set user data for adapt */ t8_forest_set_user_data (forest_ada_bal_par, &maxlevel); - t8_forest_set_adapt (forest_ada_bal_par, forest, t8_test_adapt_balance, 1); + t8_forest_set_adapt (forest_ada_bal_par, forest, t8_test_adapt_balance, 0); t8_forest_set_balance (forest_ada_bal_par, NULL, 0); t8_forest_set_transition(forest_ada_bal_par, NULL, 0); t8_forest_set_partition (forest_ada_bal_par, NULL, 0); @@ -123,47 +123,54 @@ TEST (forest_commit, test_forest_commit) t8_forest_t forest; t8_forest_t forest_ada_bal_part; t8_forest_t forest_abp_3part; + const char *prefix_transition = "forest_test_transition"; const int level_step = 0; /* construct a single tree hex cmesh */ cmesh = t8_cmesh_new_hypercube (T8_ECLASS_HEX, sc_MPI_COMM_WORLD, 0, 0, 0); - /* ref the cmesh since we reuse it */ - t8_cmesh_ref (cmesh); + t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); - sizeof(t8_hex_with_subelements); - t8_debugf("size of p8est quadrant %li \n",sizeof(p8est_quadrant_t) ); + // sizeof(t8_hex_with_subelements); + // t8_debugf("size of p8est quadrant %li \n",sizeof(p8est_quadrant_t) ); - t8_debugf("size of t8_hex_with_subelements %li \n",sizeof(t8_hex_with_subelements) ); - t8_scheme_cxx_ref (scheme); + // t8_debugf("size of t8_hex_with_subelements %li \n",sizeof(t8_hex_with_subelements) ); + /* Compute the first level, such that no process is empty */ // int min_level = t8_forest_min_nonempty_level (cmesh, scheme); // // /* Use one level with empty processes */ // min_level = SC_MAX (min_level - 1, 0); - int maxlevel = 2; + int maxlevel = 5; + for (int level = 0; level <= maxlevel; level++) { + /* ref the cmesh since we reuse it */ + t8_cmesh_ref (cmesh); t8_debugf ("Testing forest commit level %i\n", level); - /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); /* We need to use forest twice, so we ref it */ // t8_forest_ref (forest); /* Adapt, balance and partition the forest */ // forest_ada_bal_part = t8_test_forest_commit_abp (forest, maxlevel); + // if ( level == maxlevel){ + + // t8_forest_write_vtk (forest_ada_bal_part, prefix_transition); + // } /* Adapt, balance and partition the forest using three separate steps */ // forest_abp_3part = t8_test_forest_commit_abp_3step (forest, maxlevel); // ASSERT_TRUE (t8_forest_is_equal (forest_abp_3part, forest_ada_bal_part)) << "The forests are not equal"; - t8_forest_unref (&forest); + t8_scheme_cxx_ref (scheme); + t8_forest_unref (&forest); // t8_forest_unref (&forest_ada_bal_part); // t8_forest_unref (&forest_abp_3part); } + t8_cmesh_unref(&cmesh); t8_scheme_cxx_unref (&scheme); - t8_cmesh_unref(&cmesh); t8_debugf ("Done testing forest commit."); } From b3b06f3d7d04c2697a059316d1245f68f2d951cc Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 22 May 2024 14:22:14 +0200 Subject: [PATCH 18/55] Completed gtest_forest_commit --- src/t8_forest/t8_forest.c | 18 +----- src/t8_forest/t8_forest_adapt.cxx | 13 ++-- src/t8_forest/t8_forest_balance.cxx | 1 - .../t8_transition_conformal_hex_cxx.cxx | 4 +- .../t8_gtest_forest_commit.cxx | 64 +++++++++++-------- 5 files changed, 48 insertions(+), 52 deletions(-) diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index ffcefe59c4..ac53ee4d55 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -292,7 +292,7 @@ t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, /* set the forests subelement flag, which is for example used by the LFN routine */ forest->set_subelements = 1; - forest->is_transitioned = 1; + // forest->is_transitioned = 1; } void @@ -464,13 +464,11 @@ t8_forest_populate_irregular (t8_forest_t forest) t8_forest_t forest_tmp_partition; t8_cmesh_ref (forest->cmesh); t8_scheme_cxx_ref (forest->scheme_cxx); - t8_debugf("scheme adresse anfang populate irregular %p\n", forest->scheme_cxx); /* We start with a level 0 uniform refinement */ t8_forest_init (&forest_zero); t8_forest_set_level (forest_zero, 0); t8_forest_set_cmesh (forest_zero, forest->cmesh, forest->mpicomm); t8_forest_set_scheme (forest_zero, forest->scheme_cxx); - t8_debugf("set level in populate irregular %i\n", forest->set_level); t8_forest_commit (forest_zero); /* Up to the specified level we refine every element. */ @@ -498,7 +496,6 @@ t8_forest_populate_irregular (t8_forest_t forest) void t8_forest_commit (t8_forest_t forest) { - t8_debugf("scheme adresse anfang commit %p\n", forest->scheme_cxx); int mpiret; int partitioned = 0; sc_MPI_Comm comm_dup; @@ -554,9 +551,7 @@ t8_forest_commit (t8_forest_t forest) forest->incomplete_trees = 0; forest->is_transitioned = 0; } - else { - t8_global_productionf("-----------set_from != NULL-------------\n"); - + else { /* set_from != NULL */ t8_forest_t forest_from = forest->set_from; /* temporarily store set_from, since we may overwrite it */ @@ -748,8 +743,6 @@ t8_forest_commit (t8_forest_t forest) /* decrease reference count of intermediate input forest, possibly destroying it */ t8_forest_unref (&forest->set_from); } - t8_debugf(" forest_from == forest->set_from\n"); - /* reset forest->set_from */ forest->set_from = forest_from; /* decrease reference count of input forest, possibly destroying it */ @@ -766,6 +759,7 @@ t8_forest_commit (t8_forest_t forest) forest->set_for_coarsening = 0; forest->set_from = NULL; forest->committed = 1; + t8_debugf("Forest is transitioned %i \n", forest->is_transitioned); t8_debugf ("Committed forest with %li local elements and %lli " "global elements.\n\tTree range is from %lli to %lli.\n", (long) forest->local_num_elements, (long long) forest->global_num_elements, @@ -774,7 +768,6 @@ t8_forest_commit (t8_forest_t forest) if (forest->tree_offsets == NULL) { /* Compute the tree offset array */ t8_forest_partition_create_tree_offsets (forest); - t8_debugf("Scheme nach forest->tree_offsets == NULL \n"); } //ist gleich Null wenn wir nur einen Baum haben @@ -788,7 +781,6 @@ t8_forest_commit (t8_forest_t forest) /* Compute global first desc array */ t8_forest_partition_create_first_desc (forest); - // t8_debugf("Scheme nach global first desc == NULL %p\n", forest->scheme_cxx); } @@ -827,8 +819,6 @@ t8_forest_commit (t8_forest_t forest) #ifdef T8_ENABLE_DEBUG t8_forest_partition_test_boundary_element (forest); #endif - t8_debugf("scheme adresse Ende commit %p\n", forest->scheme_cxx); - } t8_locidx_t @@ -1647,8 +1637,6 @@ t8_forest_free_trees (t8_forest_t forest) number_of_trees = forest->trees->elem_count; for (jt = 0; jt < number_of_trees; jt++) { tree = (t8_tree_t) t8_sc_array_index_locidx (forest->trees, jt); - t8_debugf("anzahl element in baum %i \n", t8_forest_get_tree_element_count (tree)); - t8_debugf("anzahl bäume %i \n", number_of_trees); if (t8_forest_get_tree_element_count (tree) < 1) { /* if local tree is empty */ diff --git a/src/t8_forest/t8_forest_adapt.cxx b/src/t8_forest/t8_forest_adapt.cxx index 6c2242709a..447e5f6772 100644 --- a/src/t8_forest/t8_forest_adapt.cxx +++ b/src/t8_forest/t8_forest_adapt.cxx @@ -558,12 +558,15 @@ t8_forest_adapt (t8_forest_t forest) */ refine = forest->set_adapt_fn (forest, forest->set_from, ltree_id, el_considered, tscheme, is_family, num_elements_to_adapt_callback, elements_from); + t8_debugf("refine value %i \n", refine ); + /* make adjustments of the refine value in the context of transitioned forests */ - // if (forest->set_from->is_transitioned == 1 || forest->set_subelements == 1) { - if (forest->set_from->is_transitioned == 1){ - t8_forest_adjust_refine_for_transitioned_forests (forest, tscheme, - t8_element_array_index_locidx (telements_from, el_considered), - ltree_id, &refine);} + // if (forest->set_from->is_transitioned == 1 || forest->set_subelements == 1) { + // if (forest->set_from->is_transitioned == 1){ + // t8_debugf("HIER\n"); + // t8_forest_adjust_refine_for_transitioned_forests (forest, tscheme, + // t8_element_array_index_locidx (telements_from, el_considered), + // ltree_id, &refine);} T8_ASSERT (is_family || refine != -1); if (refine == 1 && tscheme->t8_element_level (elements_from[0]) >= forest->maxlevel) { diff --git a/src/t8_forest/t8_forest_balance.cxx b/src/t8_forest/t8_forest_balance.cxx index 8dcb1f9970..0fa2ca2bf0 100644 --- a/src/t8_forest/t8_forest_balance.cxx +++ b/src/t8_forest/t8_forest_balance.cxx @@ -180,7 +180,6 @@ t8_forest_balance (t8_forest_t forest, int repartition) T8_ASSERT (forest_from->maxlevel_existing >= 0); /* Initialize the temp forest to be adapted from forest_from */ t8_forest_init (&forest_temp); - t8_debugf("forest temp is transitioned %i und forest from is transitioned %i\n", forest_temp->is_transitioned, forest_from->is_transitioned); /* Update the maximum occurring level */ forest_temp->maxlevel_existing = forest_from->maxlevel_existing; /* Adapt the forest */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 0224144c17..e468a22df3 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -2906,9 +2906,7 @@ t8_subelement_scheme_hex_c::t8_element_transition_scheme_is_conformal (void) int t8_subelement_scheme_hex_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const{ -if (t8_element_get_subelement_id((const t8_element * ) elem1) != 0 ){ - t8_productionf("--------------------------------\n sub ID %i \n ------------------\n", t8_element_get_subelement_id((const t8_element * ) elem1)); -} + return (p8est_quadrant_is_equal ((const p8est_quadrant_t *) elem1, (const p8est_quadrant_t *) elem2)) && (t8_element_get_subelement_id((const t8_element * ) elem1) == t8_element_get_subelement_id((const t8_element * ) elem2)); } diff --git a/test/t8_forest_transition/t8_gtest_forest_commit.cxx b/test/t8_forest_transition/t8_gtest_forest_commit.cxx index 2eb222faba..c296cfd271 100644 --- a/test/t8_forest_transition/t8_gtest_forest_commit.cxx +++ b/test/t8_forest_transition/t8_gtest_forest_commit.cxx @@ -56,15 +56,19 @@ t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t /* we set a maximum refinement level as forest user data */ int maxlevel = *(int *) t8_forest_get_user_data (forest); - if (level >= maxlevel) { - /* Do not refine after the maxlevel */ - return 0; - } - int child_id = ts->t8_element_child_id (elements[0]); - if (child_id == 0) { + // if (level >= maxlevel) { + // /* Do not refine after the maxlevel */ + // return 0; + // } + // int child_id = ts->t8_element_child_id (elements[0]); + // if (child_id == 1) { + // return 1; + // } + // return 0; + if (lelement_id == 0){ return 1; } - return 0; +return 0; } /* adapt, balance and partition a given forest in one step */ @@ -84,6 +88,8 @@ t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) t8_forest_set_transition(forest_ada_bal_par, NULL, 0); t8_forest_set_partition (forest_ada_bal_par, NULL, 0); t8_forest_commit (forest_ada_bal_par); + // t8_forest_write_vtk (forest_ada_bal_par, "transition_forest"); + t8_debugf("---------finsish t8_test_forest_commit_abp ---------------------\n"); return forest_ada_bal_par; @@ -96,22 +102,28 @@ t8_test_forest_commit_abp_3step (t8_forest_t forest, int maxlevel) t8_forest_t forest_adapt; t8_forest_t forest_balance; t8_forest_t forest_partition; + t8_forest_t forest_transition; t8_forest_init (&forest_adapt); t8_forest_init (&forest_balance); t8_forest_init (&forest_partition); + t8_forest_init (&forest_transition); /* adapt the forest */ t8_forest_set_user_data (forest_adapt, &maxlevel); - t8_forest_set_adapt (forest_adapt, forest, t8_test_adapt_balance, 1); + t8_forest_set_adapt (forest_adapt, forest, t8_test_adapt_balance, 0); t8_forest_commit (forest_adapt); /* balance the forest */ t8_forest_set_balance (forest_balance, forest_adapt, 0); t8_forest_commit (forest_balance); + /* transition the forest */ + t8_forest_set_transition (forest_transition, forest_balance, 0); + t8_forest_commit (forest_transition); + /* partrition the forest */ - t8_forest_set_partition (forest_partition, forest_balance, 0); + t8_forest_set_partition (forest_partition, forest_transition, 0); t8_forest_commit (forest_partition); return forest_partition; @@ -121,8 +133,8 @@ TEST (forest_commit, test_forest_commit) { t8_cmesh_t cmesh; t8_forest_t forest; - t8_forest_t forest_ada_bal_part; - t8_forest_t forest_abp_3part; + t8_forest_t forest_ada_bal_tra_part; + t8_forest_t forest_abtp_3part; const char *prefix_transition = "forest_test_transition"; const int level_step = 0; @@ -141,35 +153,31 @@ TEST (forest_commit, test_forest_commit) // int min_level = t8_forest_min_nonempty_level (cmesh, scheme); // // /* Use one level with empty processes */ // min_level = SC_MAX (min_level - 1, 0); - int maxlevel = 5; + int maxlevel = 2; for (int level = 0; level <= maxlevel; level++) { /* ref the cmesh since we reuse it */ - t8_cmesh_ref (cmesh); + t8_cmesh_ref (cmesh); t8_debugf ("Testing forest commit level %i\n", level); /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); /* We need to use forest twice, so we ref it */ - // t8_forest_ref (forest); - /* Adapt, balance and partition the forest */ - // forest_ada_bal_part = t8_test_forest_commit_abp (forest, maxlevel); - // if ( level == maxlevel){ - - // t8_forest_write_vtk (forest_ada_bal_part, prefix_transition); - // } - /* Adapt, balance and partition the forest using three separate steps */ - // forest_abp_3part = t8_test_forest_commit_abp_3step (forest, maxlevel); + t8_forest_ref (forest); + /* Adapt, balance, transition and partition the forest */ + forest_ada_bal_tra_part = t8_test_forest_commit_abp (forest, maxlevel); - // ASSERT_TRUE (t8_forest_is_equal (forest_abp_3part, forest_ada_bal_part)) << "The forests are not equal"; + /* Adapt, balance, transition and partition the forest using three separate steps */ + forest_abtp_3part = t8_test_forest_commit_abp_3step (forest, maxlevel); + + ASSERT_TRUE (t8_forest_is_equal (forest_abtp_3part, forest_ada_bal_tra_part)) << "The forests are not equal"; t8_scheme_cxx_ref (scheme); - t8_forest_unref (&forest); - // t8_forest_unref (&forest_ada_bal_part); - // t8_forest_unref (&forest_abp_3part); + t8_forest_unref (&forest_ada_bal_tra_part); + t8_forest_unref (&forest_abtp_3part); } - t8_cmesh_unref(&cmesh); - + + t8_cmesh_unref(&cmesh); t8_scheme_cxx_unref (&scheme); t8_debugf ("Done testing forest commit."); } From 2205e8041f40dd5701d7222ded238526521b9e86 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 22 May 2024 14:24:05 +0200 Subject: [PATCH 19/55] Corrected typo --- src/t8_forest/t8_forest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index ac53ee4d55..eb0a1b96b7 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -764,13 +764,13 @@ t8_forest_commit (t8_forest_t forest) "global elements.\n\tTree range is from %lli to %lli.\n", (long) forest->local_num_elements, (long long) forest->global_num_elements, (long long) forest->first_local_tree, (long long) forest->last_local_tree); -//ist gleich NULL wenn wir nur einen Baum haben + if (forest->tree_offsets == NULL) { /* Compute the tree offset array */ t8_forest_partition_create_tree_offsets (forest); } - //ist gleich Null wenn wir nur einen Baum haben + if (forest->element_offsets == NULL) { /* Compute element offsets */ t8_forest_partition_create_offsets (forest); From ba38293bc6e91cb11c309cb305d50326af30c338 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Mon, 27 May 2024 10:45:49 +0200 Subject: [PATCH 20/55] Added vertex function + reference_coords --- example/transition/t8_transition_forest.cxx | 211 ++++++++++++++++++ src/t8_forest/t8_forest.c | 3 - .../t8_transition_conformal_hex_cxx.cxx | 31 ++- .../t8_transition_conformal_hex_cxx.hxx | 15 ++ .../t8_transition_conformal_quad_cxx.cxx | 5 + .../t8_transition_conformal_quad_cxx.hxx | 12 + .../t8_gtest_forest_commit.cxx | 28 +-- 7 files changed, 281 insertions(+), 24 deletions(-) create mode 100644 example/transition/t8_transition_forest.cxx diff --git a/example/transition/t8_transition_forest.cxx b/example/transition/t8_transition_forest.cxx new file mode 100644 index 0000000000..dd9853ec56 --- /dev/null +++ b/example/transition/t8_transition_forest.cxx @@ -0,0 +1,211 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include +#include +#include +#include +#include /* A collection of exemplary cmeshes */ +#include +#include +#include /* geometrical information of the forest */ +#include +#include +#include +#include +#include +#include + +/* In this test, we adapt, balance and partition a uniform forest. + * We do this in two ways: + * 1st All operations are performed in one single call to t8_forest_commit + * 2nd Each intermediate step is performed in a separate commit + * + * After these two forests are created, we check for equality. + */ + + +/* Adapt a forest such that always the first child of a + * tree is refined and no other elements. This results in a highly + * imbalanced forest. */ +static int +t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, const int is_family, const int num_elements, t8_element_t *elements[]) +{ + T8_ASSERT (!is_family || (is_family && num_elements == ts->t8_element_num_children (elements[0]))); + + int level = ts->t8_element_level (elements[0]); + + /* we set a maximum refinement level as forest user data */ + int maxlevel = *(int *) t8_forest_get_user_data (forest); + // if (level >= maxlevel) { + // /* Do not refine after the maxlevel */ + // return 0; + // } + // int child_id = ts->t8_element_child_id (elements[0]); + // if (child_id == 1) { + // return 1; + // } + // return 0; + if (lelement_id == 0){ + return 1; + } +return 0; +} + +/* adapt, balance and partition a given forest in one step */ +static t8_forest_t +t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) +{ + t8_debugf("---------start t8_test_forest_commit_abp ---------------------\n"); + + t8_forest_t forest_ada_bal_par; + + /* Adapt, balance and partition the uniform forest */ + t8_forest_init (&forest_ada_bal_par); + /* Set user data for adapt */ + t8_forest_set_user_data (forest_ada_bal_par, &maxlevel); + t8_forest_set_adapt (forest_ada_bal_par, forest, t8_test_adapt_balance, 0); + t8_forest_set_balance (forest_ada_bal_par, NULL, 0); + t8_forest_set_transition(forest_ada_bal_par, NULL, 0); + t8_forest_set_partition (forest_ada_bal_par, NULL, 0); + t8_forest_commit (forest_ada_bal_par); + + t8_debugf("---------finsish t8_test_forest_commit_abp ---------------------\n"); + return forest_ada_bal_par; +} + +/* adapt, balance and partition a given forest in 3 steps */ +static t8_forest_t +t8_test_forest_commit_abp_3step (t8_forest_t forest, int maxlevel) +{ + t8_debugf("---------start t8_test_forest_commit_abtp_3step ---------------------\n"); + + t8_forest_t forest_adapt; + t8_forest_t forest_balance; + t8_forest_t forest_partition; + t8_forest_t forest_transition; + + t8_forest_init (&forest_adapt); + t8_forest_init (&forest_balance); + t8_forest_init (&forest_partition); + t8_forest_init (&forest_transition); + + /* adapt the forest */ + t8_forest_set_user_data (forest_adapt, &maxlevel); + t8_forest_set_adapt (forest_adapt, forest, t8_test_adapt_balance, 0); + t8_forest_commit (forest_adapt); + + /* balance the forest */ + t8_forest_set_balance (forest_balance, forest_adapt, 0); + t8_forest_commit (forest_balance); + + /* transition the forest */ + t8_forest_set_transition (forest_transition, forest_balance, 0); + t8_forest_commit (forest_transition); + + /* partrition the forest */ + t8_forest_set_partition (forest_partition, forest_transition, 0); + t8_forest_commit (forest_partition); +t8_debugf("---------finsish t8_test_forest_commit_abtp_3step ---------------------\n"); + return forest_partition; +} + +void t8_transition_commit () +{ + t8_cmesh_t cmesh; + t8_forest_t forest; + t8_forest_t forest_ada_bal_tra_part; + t8_forest_t forest_abtp_3part; + + /* construct a single tree hex cmesh */ + cmesh = t8_cmesh_new_hypercube (T8_ECLASS_HEX, sc_MPI_COMM_WORLD, 0, 0, 0); + + + t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); + + int maxlevel = 2; + for (int level = 2; level <= maxlevel; level++) { + /* ref the cmesh since we reuse it */ + t8_cmesh_ref (cmesh); + t8_debugf ("Testing forest commit level %i\n", level); + + /* Create a uniformly refined forest */ + forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); + + /* We need to use forest twice, so we ref it */ + t8_forest_ref (forest); + /* Adapt, balance, transition and partition the forest */ + t8_debugf("ref count forest %i \n", forest->rc.refcount); + + forest_ada_bal_tra_part = t8_test_forest_commit_abp (forest, maxlevel); + t8_forest_write_vtk (forest_ada_bal_tra_part, "transition_forest"); + + t8_debugf("ref count forest %i \n", forest->rc.refcount); + + /* Adapt, balance, transition and partition the forest using three separate steps */ + forest_abtp_3part = t8_test_forest_commit_abp_3step (forest, maxlevel); + + // ASSERT_TRUE (t8_forest_is_equal (forest_abtp_3part, forest_ada_bal_tra_part)) << "The forests are not equal"; + t8_scheme_cxx_ref (scheme); + + t8_debugf("ref count forest ada_bal_tra_part %i \n", forest_ada_bal_tra_part->rc.refcount); + t8_debugf("ref count forest_abtp_3part %i \n", forest_abtp_3part->rc.refcount); + t8_debugf("ref count scheme %i \n", scheme->rc.refcount); + t8_debugf("ref count cmesh %i \n", cmesh->rc.refcount); + t8_forest_unref (&forest_ada_bal_tra_part); + t8_forest_unref (&forest_abtp_3part); + t8_debugf("ref count scheme %i \n", scheme->rc.refcount); + t8_debugf("ref count cmesh %i \n", cmesh->rc.refcount); + + } + t8_cmesh_unref(&cmesh); + t8_debugf("ref count scheme %i \n", scheme->rc.refcount); + t8_scheme_cxx_unref (&scheme); + + + t8_debugf ("Done testing forest commit."); +} + + +int +main (int argc, char **argv) +{ + int mpiret; +/* Initialize MPI. This has to happen before we initialize sc or t8code. */ + mpiret = sc_MPI_Init (&argc, &argv); + + SC_CHECK_MPI (mpiret); + /* Initialize the sc library, has to happen before we initialize t8code. */ + sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_ESSENTIAL); + + t8_init (SC_LP_DEFAULT); + + t8_transition_commit (); + + sc_finalize (); + + mpiret = sc_MPI_Finalize (); + + SC_CHECK_MPI (mpiret); + + return 0; +} \ No newline at end of file diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index eb0a1b96b7..cf1ad2b042 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -509,7 +509,6 @@ t8_forest_commit (t8_forest_t forest) } if (forest->set_from == NULL) { - t8_global_productionf("-----------set_from == NULL-------------\n"); /* This forest is constructed solely from its cmesh as a uniform * forest */ T8_ASSERT (forest->mpicomm != sc_MPI_COMM_NULL); @@ -538,12 +537,10 @@ t8_forest_commit (t8_forest_t forest) /* populate a new forest with tree and quadrant objects */ if (t8_forest_refines_irregular (forest) && forest->set_level > 0) { - t8_global_productionf("----------- refines irregular-------------\n"); /* On root level we will also use the normal algorithm */ t8_forest_populate_irregular (forest); } else { - t8_global_productionf("-----------refines regular-------------\n"); t8_forest_populate (forest); } diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index e468a22df3..fde071f636 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1913,11 +1913,40 @@ t8_subelement_scheme_hex_c::t8_element_refines_irregular () const return 1; } +void + t8_subelement_scheme_hex_c::t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const + { + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} + void t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) const { - SC_ABORT ("This function is not implemented for the given scheme.\n"); + T8_ASSERT (ref_coords != NULL); + T8_ASSERT (t8_element_is_valid (elem)); + + const p8est_quadrant_t *q1 = (const p8est_quadrant_t *) elem; + + /* Get the length of the quadrant */ + const p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); + + for (size_t coord = 0; coord < num_coords; ++coord) { + const size_t offset = 3 * coord; + /* Compute the x, y and z coordinates of the point depending on the + * reference coordinates */ + out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; + out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; + out_coords[offset + 2] = q1->z + ref_coords[offset + 2] * len; + + /* We divide the integer coordinates by the root length of the hex + * to obtain the reference coordinates. */ + out_coords[offset + 0] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; + } + + } void diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index aa86f2a4e4..39c369b350 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -386,6 +386,21 @@ public: int vertex, int coords[]) const; + + /** Compute the integer coordinates of a given element vertex. + * The default scheme implements the Morton type SFCs. In these SFCs the + * elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and + * L the maximum refinement level. + * All element vertices have integer coordinates in this cube. + * \param [in] elem The element. + * \param [in] vertex The id of the vertex whose coordinates shall be computed. + * \param [out] coords An array of at least as many integers as the element's dimension + * whose entries will be filled with the coordinates of \a vertex. + */ + virtual void + t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const; + + /** Convert a point in the reference space of an element to a point in the * reference space of the tree. * diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index 3f3b34a3d8..9bf74f063f 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -1504,6 +1504,11 @@ t8_subelement_scheme_quad_c::t8_element_refines_irregular () const return 1; } +void +t8_subelement_scheme_quad_c::t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const + { + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} void t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index c81a0edb40..c8221e0854 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -381,6 +381,18 @@ public: virtual void t8_element_vertex_coords (const t8_element_t *t, int vertex, int coords[]) const; + /** Compute the integer coordinates of a given element vertex. + * The default scheme implements the Morton type SFCs. In these SFCs the + * elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and + * L the maximum refinement level. + * All element vertices have integer coordinates in this cube. + * \param [in] elem The element. + * \param [in] vertex The id of the vertex whose coordinates shall be computed. + * \param [out] coords An array of at least as many integers as the element's dimension + * whose entries will be filled with the coordinates of \a vertex. + */ + virtual void + t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const; /** Convert a point in the reference space of an element to a point in the * reference space of the tree. diff --git a/test/t8_forest_transition/t8_gtest_forest_commit.cxx b/test/t8_forest_transition/t8_gtest_forest_commit.cxx index c296cfd271..83d73346e6 100644 --- a/test/t8_forest_transition/t8_gtest_forest_commit.cxx +++ b/test/t8_forest_transition/t8_gtest_forest_commit.cxx @@ -88,8 +88,6 @@ t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) t8_forest_set_transition(forest_ada_bal_par, NULL, 0); t8_forest_set_partition (forest_ada_bal_par, NULL, 0); t8_forest_commit (forest_ada_bal_par); - // t8_forest_write_vtk (forest_ada_bal_par, "transition_forest"); - t8_debugf("---------finsish t8_test_forest_commit_abp ---------------------\n"); return forest_ada_bal_par; @@ -135,7 +133,6 @@ TEST (forest_commit, test_forest_commit) t8_forest_t forest; t8_forest_t forest_ada_bal_tra_part; t8_forest_t forest_abtp_3part; - const char *prefix_transition = "forest_test_transition"; const int level_step = 0; /* construct a single tree hex cmesh */ @@ -143,18 +140,8 @@ TEST (forest_commit, test_forest_commit) t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); - // sizeof(t8_hex_with_subelements); - // t8_debugf("size of p8est quadrant %li \n",sizeof(p8est_quadrant_t) ); - - // t8_debugf("size of t8_hex_with_subelements %li \n",sizeof(t8_hex_with_subelements) ); - - - /* Compute the first level, such that no process is empty */ - // int min_level = t8_forest_min_nonempty_level (cmesh, scheme); - // // /* Use one level with empty processes */ - // min_level = SC_MAX (min_level - 1, 0); - int maxlevel = 2; + int maxlevel = -1; for (int level = 0; level <= maxlevel; level++) { /* ref the cmesh since we reuse it */ t8_cmesh_ref (cmesh); @@ -162,6 +149,7 @@ TEST (forest_commit, test_forest_commit) /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); + /* We need to use forest twice, so we ref it */ t8_forest_ref (forest); /* Adapt, balance, transition and partition the forest */ @@ -173,13 +161,13 @@ TEST (forest_commit, test_forest_commit) ASSERT_TRUE (t8_forest_is_equal (forest_abtp_3part, forest_ada_bal_tra_part)) << "The forests are not equal"; t8_scheme_cxx_ref (scheme); + t8_forest_unref (&forest_ada_bal_tra_part); t8_forest_unref (&forest_abtp_3part); - } - - t8_cmesh_unref(&cmesh); - t8_scheme_cxx_unref (&scheme); - t8_debugf ("Done testing forest commit."); -} + } + t8_scheme_cxx_unref (&scheme); + t8_cmesh_unref(&cmesh); + t8_debugf ("Done testing forest commit."); +} \ No newline at end of file From 5ddc71a4c28928d43806084df8039734ddee40ca Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Mon, 27 May 2024 10:47:04 +0200 Subject: [PATCH 21/55] Adjustment in test file t8_forest_transition --- example/transition/t8_transition_forest.cxx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/example/transition/t8_transition_forest.cxx b/example/transition/t8_transition_forest.cxx index dd9853ec56..b5d2b3e15a 100644 --- a/example/transition/t8_transition_forest.cxx +++ b/example/transition/t8_transition_forest.cxx @@ -167,18 +167,12 @@ void t8_transition_commit () // ASSERT_TRUE (t8_forest_is_equal (forest_abtp_3part, forest_ada_bal_tra_part)) << "The forests are not equal"; t8_scheme_cxx_ref (scheme); - t8_debugf("ref count forest ada_bal_tra_part %i \n", forest_ada_bal_tra_part->rc.refcount); - t8_debugf("ref count forest_abtp_3part %i \n", forest_abtp_3part->rc.refcount); - t8_debugf("ref count scheme %i \n", scheme->rc.refcount); - t8_debugf("ref count cmesh %i \n", cmesh->rc.refcount); t8_forest_unref (&forest_ada_bal_tra_part); t8_forest_unref (&forest_abtp_3part); - t8_debugf("ref count scheme %i \n", scheme->rc.refcount); - t8_debugf("ref count cmesh %i \n", cmesh->rc.refcount); + } t8_cmesh_unref(&cmesh); - t8_debugf("ref count scheme %i \n", scheme->rc.refcount); t8_scheme_cxx_unref (&scheme); From 0b9fd5ba482e455e42e4e4d44d876e6b95901daa Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 4 Jun 2024 14:06:17 +0200 Subject: [PATCH 22/55] Added reference_coords function --- .../t8_transition_conformal_hex_cxx.cxx | 220 +++++++++++++++++- 1 file changed, 214 insertions(+), 6 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index fde071f636..baa5bae4d1 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1925,7 +1925,8 @@ t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *ele { T8_ASSERT (ref_coords != NULL); T8_ASSERT (t8_element_is_valid (elem)); - + + if(!t8_element_is_subelement(elem)){ const p8est_quadrant_t *q1 = (const p8est_quadrant_t *) elem; /* Get the length of the quadrant */ @@ -1945,9 +1946,218 @@ t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *ele out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; } - - + + } + else{ + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; + p8est_quadrant_t *q1 = &phex_w_sub->p8q; + p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); + /* get location information of the given subelement */ + int location[3] = { }; + t8_element_get_location_of_subelement (elem, location); + + for (int coord = 0; coord < num_coords; ++coord) { + const size_t offset = coord * 3; + out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; + out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; + out_coords[offset + 2] = q1->z + ref_coords[offset + 2] * len; + + + //Set the apex to the center of the transition cell + if(ref_coords[0] == 1 && ref_coords[1] == 1 && ref_coords[2] == 1){ + out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + out_coords[offset + 2] -= ref_coords[offset + 2] * (len/2); + } + else{ + if(location[0] == 0){ + //face 0 + //Add the x-coordinate to the z-coordinate in order to flip the base side of the pyramid to face f0 + out_coords[offset + 2] += ref_coords[offset + 0] * len; + //set x-coordinate to zero + out_coords[offset + 0] -= ref_coords[offset + 0] * len; + } + if(location[0] == 1){ + //Add one to the z-coordinate if the x-coordinate equals zero + out_coords[offset + 2] += (1 - 1*ref_coords[offset + 0]) * len; + //set x-coordinate to one + out_coords[offset + 0] += (1 - 1*ref_coords[offset + 0]) * len; + } + if(location[0] == 2){ + //Add one to the z-coordinate if the y-coordinate equals one + out_coords[offset + 2] += (ref_coords[offset + 1]) * len; + //set y-coordinate to zero + out_coords[offset + 1] -= (ref_coords[offset + 1]) * len; + } + if(location[0] == 3){ + //Add one to the z-coordinate if the y-coordinate equals zero + out_coords[offset + 2] += ( 1 - ref_coords[offset + 1]) * len; + //set y-coordinate to one + out_coords[offset + 1] += (1 - 1*ref_coords[offset + 1]) * len; + } + //Nothing more to do for face 4 + if(location[0] == 5){ + //Add one to the z-coordinate + out_coords[offset + 2] += len; + } + //split + if(location[1] == 1){ + if(location[0] == 0 ){ + if((location[2] & 2) == 0){ + //front + //scale the y coordinate if not zero + out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + } + else{ + //back + //scale the y coordinate if zero + out_coords[offset + 1] += (1 - ref_coords[offset + 1]) * (len/2); + } + if((location[2] & 1) == 0){ + //bottom + //scale the z coordinate if not zero and z is not zero if the x-coordinate of ref_coords is not zero. + out_coords[offset + 2] -= (ref_coords[offset + 0]) * (len/2); + } + else{ + //up + //scale the z coordinate if zero + out_coords[offset + 2] += (1 - 1*ref_coords[offset + 0]) * (len/2); + } + } + if(location[0] == 1 ){ + if((location[2] & 2) == 0){ + //front + //scale the y coordinate if not zero + out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + } + else{ + //back + //scale the y coordinate if zero + out_coords[offset + 1] += (1 - ref_coords[offset + 1]) * (len/2); + } + if((location[2] & 1) == 0){ + //bottom + //scale the z coordinate if not zero and z is not zero if the x-coordinate of ref_coords is zero. + out_coords[offset + 2] -= (1 - ref_coords[offset + 0]) * (len/2); + } + else{ + //up + //scale the z coordinate if zero + out_coords[offset + 2] += (ref_coords[offset + 0]) * (len/2); + } + } + if(location[0] == 2 ){ + if((location[2] & 4) == 0){ + //left + //scale the x coordinate if not zero + out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + } + else{ + //right + //scale the x coordinate if zero + out_coords[offset + 0] += (1 - ref_coords[offset + 0] )* (len/2); + } + if((location[2] & 1) == 0){ + //bottom + //scale the z coordinate if not zero + out_coords[offset + 2] -= ref_coords[offset + 1] * (len/2); + } + else{ + //up + //scale the z coordinate if zero + out_coords[offset + 2] += (1 - ref_coords[offset + 1] )* (len/2); + + } + } + if(location[0] == 3){ + if((location[2] & 4) == 0){ + //left + //scale the x coordinate if not zero + out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + } + else{ + //right + //scale the x coordinate if zero + out_coords[offset + 0] += (1 - ref_coords[offset + 0] )* (len/2); + } + if((location[2] & 1) == 0){ + //bottom + //scale the z coordinate if not zero + out_coords[offset + 2] -= (1 - ref_coords[offset + 1]) * (len/2); + } + else{ + //up + //scale the z coordinate if zero + out_coords[offset + 2] += (ref_coords[offset + 1] )* (len/2); + } + } + + if(location[0] == 4){ + if((location[2] & 4) == 0){ + //left + //scale the x coordinate if not zero + out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + } + else{ + //right + //scale the x coordinate if zero + out_coords[offset + 0] += (1 - ref_coords[offset + 0] )* (len/2); + } + if((location[2] & 2) == 0){ + //front + //scale the y coordinate if not zero + out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + } + else{ + //back + //scale the y coordinate if zero + out_coords[offset + 1] += (1 - 1*ref_coords[offset + 1]) * (len/2); + } + + } + if(location[0] == 5){ + if((location[2] & 4) == 0){ + //left + //scale the x coordinate if not zero + out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + } + else{ + //right + //scale the x coordinate if zero + out_coords[offset + 0] += (1 - ref_coords[offset + 0] )* (len/2); + } + if((location[2] & 2) == 0){ + //front + //scale the y coordinate if not zero + out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + } + else{ + //back + //scale the y coordinate if zero + out_coords[offset + 1] += (1 - 1*ref_coords[offset + 1]) * (len/2); + } + + } } + } + + + out_coords[offset + 0] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; + + } + + + } + + + + + + } + + void t8_subelement_scheme_hex_c::t8_element_vertex_reference_coords (const @@ -1989,8 +2199,7 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords (const t8_element_t * vertex number */ coords[0] = q1->x + (vertex & 1 ? 1 : 0) * len; coords[1] = q1->y + (vertex & 2 ? 1 : 0) * len; - coords[2] = q1->z + (vertex & 4 ? 1 : 0) * len; - + coords[2] = q1->z + (vertex & 4 ? 1 : 0) * len; } else { t8_element_vertex_coords_of_subelement (elem, vertex, coords); @@ -2116,7 +2325,6 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const if(face_number == 5){ coords[2] += len; } - } /* ----------- face 0 + 1 (split) --------------------*/ else{ From 3936e508be8fa0af50c6bbadd82dc26763937611 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 4 Jun 2024 14:07:32 +0200 Subject: [PATCH 23/55] Added forest example --- example/transition/Makefile.am | 4 +- example/transition/t8_transition_forest.cxx | 19 ++++---- .../transition/t8_transition_global_hex.cxx | 46 ++++++++----------- 3 files changed, 29 insertions(+), 40 deletions(-) diff --git a/example/transition/Makefile.am b/example/transition/Makefile.am index 4467e1613a..6c406055d4 100644 --- a/example/transition/Makefile.am +++ b/example/transition/Makefile.am @@ -4,7 +4,9 @@ bin_PROGRAMS += \ example/transition/t8_transition_global_hex \ - example/transition/t8_transition_basic_hex + example/transition/t8_transition_basic_hex \ + example/transition/t8_transition_forest example_transition_t8_transition_global_hex_SOURCES = example/transition/t8_transition_global_hex.cxx example_transition_t8_transition_basic_hex_SOURCES = example/transition/t8_transition_basic_hex.cxx +example_transition_t8_transition_forest_SOURCES = example/transition/t8_transition_forest.cxx diff --git a/example/transition/t8_transition_forest.cxx b/example/transition/t8_transition_forest.cxx index b5d2b3e15a..3edc00c830 100644 --- a/example/transition/t8_transition_forest.cxx +++ b/example/transition/t8_transition_forest.cxx @@ -45,7 +45,7 @@ /* Adapt a forest such that always the first child of a * tree is refined and no other elements. This results in a highly - * imbalanced forest. */ + * inbalanced forest. */ static int t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, t8_locidx_t lelement_id, t8_eclass_scheme_c *ts, const int is_family, const int num_elements, t8_element_t *elements[]) @@ -60,15 +60,15 @@ t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t // /* Do not refine after the maxlevel */ // return 0; // } - // int child_id = ts->t8_element_child_id (elements[0]); - // if (child_id == 1) { - // return 1; - // } - // return 0; - if (lelement_id == 0){ + int child_id = ts->t8_element_child_id (elements[0]); + if (child_id == 1) { return 1; } -return 0; + return 0; + // if (lelement_id == 0 || lelement_id == 5){ + // return 1; + // } +// return 0; } /* adapt, balance and partition a given forest in one step */ @@ -154,13 +154,10 @@ void t8_transition_commit () /* We need to use forest twice, so we ref it */ t8_forest_ref (forest); /* Adapt, balance, transition and partition the forest */ - t8_debugf("ref count forest %i \n", forest->rc.refcount); forest_ada_bal_tra_part = t8_test_forest_commit_abp (forest, maxlevel); t8_forest_write_vtk (forest_ada_bal_tra_part, "transition_forest"); - t8_debugf("ref count forest %i \n", forest->rc.refcount); - /* Adapt, balance, transition and partition the forest using three separate steps */ forest_abtp_3part = t8_test_forest_commit_abp_3step (forest, maxlevel); diff --git a/example/transition/t8_transition_global_hex.cxx b/example/transition/t8_transition_global_hex.cxx index 046b9ea8a2..d0646c8774 100644 --- a/example/transition/t8_transition_global_hex.cxx +++ b/example/transition/t8_transition_global_hex.cxx @@ -61,9 +61,9 @@ t8_adapt_callback (t8_forest_t forest, if (coords[0]* P8EST_ROOT_LEN < 0.5 ){ return 1; } - else if (coords[0] > 0.5){ - return -1; - } +// else if (coords[0] > 0.5){ +// return -1; +// } return 0; } @@ -77,46 +77,36 @@ t8_transition_global (void) { /* At the moment, subelements are only implemented for T8_ECLASS_HEX and quads */ t8_eclass_t eclass = T8_ECLASS_HEX; /* depending on the include file, this will be the transitioned or default hex implementation */ - t8_scheme_cxx_t *ts = t8_scheme_new_transition_hex_cxx (); - t8_eclass_scheme_c *class_scheme; t8_forest_t forest; t8_forest_t forest_adapt; t8_cmesh_t cmesh; char filename[BUFSIZ]; /* refinement setting */ - int initlevel = 2; /* initial uniform refinement level */ - class_scheme = ts->eclass_schemes[eclass]; + int level = 2; /* initial uniform refinement level */ + + t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); /* construct a single tree hex cmesh */ cmesh = t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 0, 0); + /* Create a uniformly refined forest */ + forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); - /* initialize a forest */ - t8_forest_init (&forest); + for (int adaptation_count = 1; adaptation_count <= 2; ++adaptation_count) { + t8_forest_init (&forest_adapt); - /* set forest parameter via cmesh */ - t8_forest_set_cmesh (forest, cmesh, sc_MPI_COMM_WORLD); - t8_forest_set_level (forest, initlevel); - - t8_forest_set_scheme (forest, t8_scheme_new_transition_hex_cxx ()); - - /* commit the forest */ - t8_forest_commit (forest); - - // for (int adaptation_count = 1; adaptation_count <= 0; ++adaptation_count) { - // t8_forest_init (&forest_adapt); - - // t8_forest_set_adapt (forest_adapt, forest, t8_adapt_callback, 0); - // // t8_forest_set_balance (forest_adapt, forest, 0); - // t8_forest_set_transition (forest_adapt, forest, 1); - // t8_forest_commit (forest_adapt); - + t8_forest_set_adapt (forest_adapt, forest, t8_adapt_callback, 0); + t8_forest_set_balance (forest_adapt, forest, 0); + t8_forest_set_partition(forest_adapt, forest,0); + t8_forest_set_transition (forest_adapt, forest, 0); + t8_forest_commit (forest_adapt); + t8_debugf("---------------ROUND %i ---------------------------\n\n", adaptation_count); // // t8_forest_commit (forest_adapt); /* adapt the forest */ // //snprintf (filename, BUFSIZ, "forest_REFINEMENT_half_element_adapted_mesh"); // //t8_forest_write_vtk (forest, filename); - // forest = forest_adapt; - // } + forest = forest_adapt; + } t8_forest_unref (&forest); } /* end of t8_transition_global */ From d6eaff72f7ee28c18398665f8e5f7fbfbf7fe184 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 5 Jun 2024 17:18:06 +0200 Subject: [PATCH 24/55] Added new example to test t8_forest_untransition --- .../transition/t8_transition_global_hex.cxx | 56 +++++++++++++------ src/t8_forest/t8_forest.c | 43 ++++++-------- src/t8_forest/t8_forest_adapt.cxx | 13 +---- src/t8_forest/t8_forest_cxx.cxx | 3 +- src/t8_forest/t8_forest_transition.cxx | 34 +++++++---- 5 files changed, 81 insertions(+), 68 deletions(-) diff --git a/example/transition/t8_transition_global_hex.cxx b/example/transition/t8_transition_global_hex.cxx index d0646c8774..f316049cd3 100644 --- a/example/transition/t8_transition_global_hex.cxx +++ b/example/transition/t8_transition_global_hex.cxx @@ -30,6 +30,7 @@ /* to switch between the default quad scheme and the transition implementation */ #include "t8_eclass.h" +#include "t8_forest/t8_forest_types.h" #include "t8_forest/t8_forest_general.h" #include @@ -56,18 +57,38 @@ t8_adapt_callback (t8_forest_t forest, const int is_family, const int num_elements, t8_element_t *elements[]) { - double coords[3] = {0.0,0.0,0.0}; - ts->t8_element_vertex_reference_coords(elements[0], 0, coords); - if (coords[0]* P8EST_ROOT_LEN < 0.5 ){ + // double coords[3] = {0.0,0.0,0.0}; + // ts->t8_element_vertex_reference_coords(elements[0], 0, coords); + // if (coords[0]* P8EST_ROOT_LEN < 0.5 ){ + // return 1; + // } + int child_id = ts->t8_element_child_id (elements[0]); + if (child_id == 1) { return 1; } + return 0; // else if (coords[0] > 0.5){ // return -1; // } - return 0; + // return 0; } +/* adapt, balance, transition and partition a given forest in one step */ +static t8_forest_t +t8_test_forest_commit_abpt (t8_forest_t forest) +{ + t8_forest_t forest_ada_bal_tra_par; + + /* Adapt, balance and partition the uniform forest */ + t8_forest_init (&forest_ada_bal_tra_par); + t8_forest_set_adapt (forest_ada_bal_tra_par, forest, t8_adapt_callback, 0); + t8_forest_set_balance (forest_ada_bal_tra_par, NULL, 0); + t8_forest_set_transition(forest_ada_bal_tra_par, NULL, 0); + t8_forest_set_partition (forest_ada_bal_tra_par, NULL, 0); + t8_forest_commit (forest_ada_bal_tra_par); + return forest_ada_bal_tra_par; +} @@ -92,23 +113,22 @@ t8_transition_global (void) /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); - for (int adaptation_count = 1; adaptation_count <= 2; ++adaptation_count) { - t8_forest_init (&forest_adapt); - - t8_forest_set_adapt (forest_adapt, forest, t8_adapt_callback, 0); - t8_forest_set_balance (forest_adapt, forest, 0); - t8_forest_set_partition(forest_adapt, forest,0); - t8_forest_set_transition (forest_adapt, forest, 0); - t8_forest_commit (forest_adapt); + t8_forest_write_vtk (forest, "forest_global_hex" ); + + + for (int adaptation_count = 1; adaptation_count <= 5; ++adaptation_count) { + + forest_adapt = t8_test_forest_commit_abpt(forest); + t8_debugf("---------------ROUND %i ---------------------------\n\n", adaptation_count); - // // t8_forest_commit (forest_adapt); /* adapt the forest */ - - // //snprintf (filename, BUFSIZ, "forest_REFINEMENT_half_element_adapted_mesh"); - // //t8_forest_write_vtk (forest, filename); - forest = forest_adapt; + + forest = forest_adapt; + } + t8_forest_write_vtk (forest, "transition_global_hex" ); + + t8_forest_unref (&forest_adapt); - t8_forest_unref (&forest); } /* end of t8_transition_global */ diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index cf1ad2b042..e888568712 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -481,7 +481,6 @@ t8_forest_populate_irregular (t8_forest_t forest) t8_forest_init (&forest_tmp_partition); t8_forest_set_partition (forest_tmp_partition, forest_tmp, 0); t8_forest_commit (forest_tmp_partition); - t8_debugf("-------------end populate irregular ---------\n"); forest_zero = forest_tmp_partition; } @@ -490,7 +489,6 @@ t8_forest_populate_irregular (t8_forest_t forest) t8_forest_copy_trees (forest, forest_zero, 1); t8_forest_unref (&forest_tmp_partition); - t8_debugf("-------------end populate irregular ---------\n"); } void @@ -607,14 +605,15 @@ t8_forest_commit (t8_forest_t forest) if (forest->set_from->is_transitioned){ T8_ASSERT(forest->is_transitioned == 0); t8_forest_untransition(forest); - T8_ASSERT (!t8_forest_is_transitioned (forest)); } t8_forest_t forest_adapt; - t8_forest_init (&forest_adapt); + t8_forest_init (&forest_adapt); /* forest_adapt should not change ownership of forest->set_from */ - t8_forest_ref (forest->set_from); + if (forest_from == forest->set_from) { + t8_forest_ref (forest->set_from); + } /* set user data of forest to forest_adapt */ t8_forest_set_user_data (forest_adapt, t8_forest_get_user_data (forest)); /* Construct an intermediate, adapted forest */ @@ -634,14 +633,8 @@ t8_forest_commit (t8_forest_t forest) else { /* This forest should only be adapted */ t8_forest_copy_trees (forest, forest->set_from, 0); - /* The input forest for forest_adapt() should always be a non-transitioned forest.*/ - if (forest->set_from->is_transitioned){ - t8_forest_untransition(forest); - T8_ASSERT (!t8_forest_is_transitioned (forest)); - } - - t8_forest_adapt (forest); - forest->is_transitioned = 0; + + t8_forest_adapt (forest); } } if (forest->from_method & T8_FOREST_FROM_PARTITION) { @@ -649,10 +642,9 @@ t8_forest_commit (t8_forest_t forest) partitioned = 1; /* Partition this forest */ forest->from_method -= T8_FOREST_FROM_PARTITION; - // t8_debugf("from method nach partition %i\n",forest->from_method ); if (forest->from_method > 0) { - /* The forest should also be balanced after partition */ + /* The forest should also be balanced/transitioned after partition */ t8_forest_t forest_partition; t8_forest_init (&forest_partition); @@ -699,17 +691,22 @@ t8_forest_commit (t8_forest_t forest) /* balance with repartition */ flag_rep = 0; } - /* in this case, we will use subelements after balancing */ + /* in this case, we will transition after balancing */ t8_forest_t forest_balance; t8_forest_init (&forest_balance); - /* forest_adapt should not change ownership of forest->set_from */ + /* forest_balance should not change ownership of forest->set_from */ + if (forest_from == forest->set_from) { + t8_forest_ref (forest->set_from); + } t8_forest_set_balance (forest_balance, forest->set_from, flag_rep); + /* Set profiling if enabled */ + t8_forest_set_profiling (forest_balance, forest->profile != NULL); t8_forest_commit (forest_balance); - /* The new forest will be partitioned/balanced from forest_adapt */ + /* The new forest will be partitioned/transitioned from forest_balance */ forest->set_from = forest_balance; } else{ - /* TOnly execute t8_balance. It is possible to call t8_transition afterwards. */ + /* Only execute t8_balance.*/ T8_ASSERT (forest->from_method == 0); /* This forest should only be balanced */ @@ -721,9 +718,7 @@ t8_forest_commit (t8_forest_t forest) /* balance with repartition */ t8_forest_balance (forest, 1); } - } - forest->is_transitioned = 0; } if (forest->from_method & T8_FOREST_FROM_TRANSITION) { t8_debugf("from method in transition %i\n",forest->from_method ); @@ -731,7 +726,6 @@ t8_forest_commit (t8_forest_t forest) /* this is the last from method that we execute, * nothing should be left todo */ T8_ASSERT (forest->from_method == 0); - // T8_ASSERT (t8_forest_is_balanced(forest)); /* use subelements */ t8_forest_transition (forest); forest->is_transitioned = 1; @@ -739,9 +733,11 @@ t8_forest_commit (t8_forest_t forest) if (forest_from != forest->set_from) { /* decrease reference count of intermediate input forest, possibly destroying it */ t8_forest_unref (&forest->set_from); + } /* reset forest->set_from */ forest->set_from = forest_from; + /* decrease reference count of input forest, possibly destroying it */ t8_forest_unref (&forest->set_from); } /* end set_from != NULL */ @@ -772,13 +768,10 @@ t8_forest_commit (t8_forest_t forest) /* Compute element offsets */ t8_forest_partition_create_offsets (forest); - } if (forest->global_first_desc == NULL) { - /* Compute global first desc array */ t8_forest_partition_create_first_desc (forest); - } if (forest->profile != NULL) { diff --git a/src/t8_forest/t8_forest_adapt.cxx b/src/t8_forest/t8_forest_adapt.cxx index 447e5f6772..d7f4d652f8 100644 --- a/src/t8_forest/t8_forest_adapt.cxx +++ b/src/t8_forest/t8_forest_adapt.cxx @@ -557,18 +557,7 @@ t8_forest_adapt (t8_forest_t forest) * >1 if the element should be refined into a transition cell */ refine = forest->set_adapt_fn (forest, forest->set_from, ltree_id, el_considered, tscheme, is_family, - num_elements_to_adapt_callback, elements_from); - t8_debugf("refine value %i \n", refine ); - - /* make adjustments of the refine value in the context of transitioned forests */ - // if (forest->set_from->is_transitioned == 1 || forest->set_subelements == 1) { - // if (forest->set_from->is_transitioned == 1){ - // t8_debugf("HIER\n"); - // t8_forest_adjust_refine_for_transitioned_forests (forest, tscheme, - // t8_element_array_index_locidx (telements_from, el_considered), - // ltree_id, &refine);} - - T8_ASSERT (is_family || refine != -1); + num_elements_to_adapt_callback, elements_from); T8_ASSERT (is_family || refine != -1); if (refine == 1 && tscheme->t8_element_level (elements_from[0]) >= forest->maxlevel) { /* Only refine an element regularly if it does not exceed the maximum level */ refine = 0; diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index f40cd899c6..4da398b6a5 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -1414,11 +1414,12 @@ t8_forest_copy_trees (t8_forest_t forest, t8_forest_t from, int copy_elements) } forest->first_local_tree = from->first_local_tree; forest->last_local_tree = from->last_local_tree; + forest->is_transitioned = from->is_transitioned; + if (copy_elements) { forest->local_num_elements = from->local_num_elements; forest->global_num_elements = from->global_num_elements; forest->incomplete_trees = from->incomplete_trees; - forest->is_transitioned = from->is_transitioned; } else { forest->local_num_elements = 0; diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx index 3ae008a79d..d692b91178 100644 --- a/src/t8_forest/t8_forest_transition.cxx +++ b/src/t8_forest/t8_forest_transition.cxx @@ -302,8 +302,7 @@ t8_forest_untransition_entry (t8_forest_t forest, const int is_family, int num_elements, t8_element_t *elements[]) { - T8_ASSERT (forest->is_transitioned == 1 - && forest->set_from->is_transitioned == 1); + T8_ASSERT(forest->set_from->is_transitioned == 1); //Iterate through elements array and if an element is a subelement, return -1 for //coarsening this element in forest_adapt. All other elements remain unchanged. @@ -322,20 +321,31 @@ t8_forest_untransition_entry (t8_forest_t forest, void t8_forest_untransition (t8_forest_t forest) { - T8_ASSERT (forest->is_transitioned == 1 - && forest->set_from->is_transitioned == 1); + t8_global_productionf ("Into t8_forest_untransition.\n"); + + T8_ASSERT(forest->set_from->is_transitioned); + + t8_forest_t forest_untransition; + + t8_forest_init (&forest_untransition); + /* forest_untransition should not change ownership of forest->set_from */ + t8_forest_ref (forest->set_from); + /* Construct an intermediate, untransitioned forest */ + t8_forest_set_adapt (forest_untransition, forest->set_from, t8_forest_untransition_entry, 0); + + t8_forest_commit (forest_untransition); + forest_untransition->is_transitioned = 0; + /* The new forest will be partitioned/balanced from forest_adapt */ + forest->set_from = forest_untransition; + + + t8_global_productionf ("Done t8_forest_untransition.\n"); + + /* In the following, we will call forest_adapt to coarsen all transition cells * back to their regular parent element. So, forest->set_from is a transitioned forest and * forest will be non-transitioned. */ - t8_global_productionf ("Into t8_forest_untransition.\n"); - - forest->set_adapt_fn = t8_forest_untransition_entry; - forest->set_adapt_recursive = 0; - t8_forest_copy_trees (forest, forest->set_from, 0); - t8_forest_adapt (forest); - forest->is_transitioned = 0; - t8_global_productionf ("Done t8_forest_untransition.\n"); } /* Test whether the forest is transitioned. From 74b5cd708bf6a1bcfeeceb263e9a638247918834 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Tue, 11 Jun 2024 16:46:17 +0200 Subject: [PATCH 25/55] added example file for multiple trees --- example/transition/Makefile.am | 5 +- .../transition/t8_transition_global_hex.cxx | 2 +- .../t8_transition_multiple_trees_hex.cxx | 164 ++++++++++++++++++ src/t8_forest/t8_forest.c | 6 - src/t8_forest/t8_forest_transition.cxx | 1 - .../t8_transition_conformal_hex_cxx.cxx | 5 +- .../t8_transition_conformal_hex_cxx.hxx | 68 ++++++-- 7 files changed, 220 insertions(+), 31 deletions(-) create mode 100644 example/transition/t8_transition_multiple_trees_hex.cxx diff --git a/example/transition/Makefile.am b/example/transition/Makefile.am index 6c406055d4..302b66bc46 100644 --- a/example/transition/Makefile.am +++ b/example/transition/Makefile.am @@ -5,8 +5,11 @@ bin_PROGRAMS += \ example/transition/t8_transition_global_hex \ example/transition/t8_transition_basic_hex \ - example/transition/t8_transition_forest + example/transition/t8_transition_forest \ + example/transition/t8_transition_multiple_trees_hex + example_transition_t8_transition_global_hex_SOURCES = example/transition/t8_transition_global_hex.cxx example_transition_t8_transition_basic_hex_SOURCES = example/transition/t8_transition_basic_hex.cxx example_transition_t8_transition_forest_SOURCES = example/transition/t8_transition_forest.cxx +example_transition_t8_transition_multiple_trees_hex_SOURCES = example/transition/t8_transition_multiple_trees_hex.cxx diff --git a/example/transition/t8_transition_global_hex.cxx b/example/transition/t8_transition_global_hex.cxx index f316049cd3..b416c8b72f 100644 --- a/example/transition/t8_transition_global_hex.cxx +++ b/example/transition/t8_transition_global_hex.cxx @@ -116,7 +116,7 @@ t8_transition_global (void) t8_forest_write_vtk (forest, "forest_global_hex" ); - for (int adaptation_count = 1; adaptation_count <= 5; ++adaptation_count) { + for (int adaptation_count = 1; adaptation_count <= 2; ++adaptation_count) { forest_adapt = t8_test_forest_commit_abpt(forest); diff --git a/example/transition/t8_transition_multiple_trees_hex.cxx b/example/transition/t8_transition_multiple_trees_hex.cxx new file mode 100644 index 0000000000..7ba0c81a1c --- /dev/null +++ b/example/transition/t8_transition_multiple_trees_hex.cxx @@ -0,0 +1,164 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element types in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* Description: + * This is the example file for refinement with transitioning. In this testcase, we are able to + * (i) refine a mesh according to some refinement criterion and use transition cells to make the mesh conformal + * (ii) use multiple adaptation steps in which the refinement criterion changes (e.g. the geometry) + * (iii) decide, whether we want to check the LFN function for each mesh + * (iv) decide, whether we want to get statistics printed out, regarding # of elements in the meshes and runtime infos of the several functions or other debugging information + */ + +/* to switch between the default quad scheme and the transition implementation */ +#include "t8_eclass.h" +#include "t8_forest/t8_forest_types.h" + +#include "t8_forest/t8_forest_general.h" +#include +#include +#include +#include +#include // to write vtk +#include +#include +#include /* for cmesh initialization via for example t8_cmesh_new_hypercube */ +#include +#include + + +/* In this example, the left side of a unit cube with initial level 2 is refined to construct an adapted and transitioned forest. */ + +/* Refinement criterion: All elements with x-coordinate smaller than 0.5 are being refined. All other elements remain unchanged. */ +int +t8_adapt_callback (t8_forest_t forest, + t8_forest_t forest_from, + t8_locidx_t which_tree, + t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, + const int is_family, + const int num_elements, t8_element_t *elements[]) +{ + int child_id = ts->t8_element_child_id (elements[0]); + if (child_id == 1) { + return 1; + } + return 0; +} + +/* adapt, balance, transition and partition a given forest in one step */ +static t8_forest_t +t8_test_forest_commit_abpt (t8_forest_t forest) +{ + t8_forest_t forest_ada_bal_tra_par; + + /* Adapt, balance and partition the uniform forest */ + t8_forest_init (&forest_ada_bal_tra_par); + t8_forest_set_adapt (forest_ada_bal_tra_par, forest, t8_adapt_callback, 0); + t8_forest_set_balance (forest_ada_bal_tra_par, NULL, 0); + t8_forest_set_transition(forest_ada_bal_tra_par, NULL, 0); + t8_forest_set_partition (forest_ada_bal_tra_par, NULL, 0); + t8_forest_commit (forest_ada_bal_tra_par); + + return forest_ada_bal_tra_par; +} + + + +/* Initializing, adapting balancing and transitioning a forest */ +static void +t8_transition_global (void) +{ + /* At the moment, subelements are only implemented for hexes and quads */ + t8_eclass_t eclass = T8_ECLASS_HEX; /* depending on the include file, this will be the transitioned or default hex implementation */ + t8_forest_t forest; + t8_forest_t forest_adapt; + t8_cmesh_t cmesh; + char filename[BUFSIZ]; + + /* refinement setting */ + int level = 2; /* initial uniform refinement level */ + + t8_locidx_t polygons_x = 2; + t8_locidx_t polygons_y = 1; + t8_locidx_t polygons_z = 1; + + const double boundary[24] = {0,0,0, + 2,0,0, + 0,1,0, + 2,1,0, + 0,0,1, + 2,0,1, + 0,1,1, + 2,1,1}; + + t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); + + /* construct a multiple tree hex cmesh */ + cmesh = + t8_cmesh_new_hypercube_pad (eclass, sc_MPI_COMM_WORLD, boundary, polygons_x, + polygons_y, polygons_z, 0); + + + + /* Create a uniformly refined forest */ + forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); + + t8_forest_write_vtk (forest, "forest_global_hex" ); + + + for (int adaptation_count = 1; adaptation_count <= 1; ++adaptation_count) { + + forest_adapt = t8_test_forest_commit_abpt(forest); + + t8_debugf("---------------ROUND %i ---------------------------\n\n", adaptation_count); + + forest = forest_adapt; + + } + t8_forest_write_vtk (forest, "transition_global_hex" ); + + t8_forest_unref (&forest_adapt); + +} /* end of t8_transition_global */ + + + +int +main (int argc, char **argv) +{ + int mpiret; + + mpiret = sc_MPI_Init (&argc, &argv); + SC_CHECK_MPI (mpiret); + + sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_DEFAULT); + t8_init (SC_LP_DEFAULT); + + t8_transition_global (); + + sc_finalize (); + mpiret = sc_MPI_Finalize (); + + SC_CHECK_MPI (mpiret); + + return 0; +} diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index e888568712..65e6ba6031 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -586,7 +586,6 @@ t8_forest_commit (t8_forest_t forest) /* Compute the maximum allowed refinement level */ t8_forest_compute_maxlevel (forest); - t8_debugf("Forest from method anfang commit %i\n", forest->from_method); if (forest->from_method == T8_FOREST_FROM_COPY) { SC_CHECK_ABORT (forest->set_from != NULL, "No forest to copy from was specified."); t8_forest_copy_trees (forest, forest->set_from, 1); @@ -596,7 +595,6 @@ t8_forest_commit (t8_forest_t forest) /* T8_ASSERT (forest->from_method == T8_FOREST_FROM_COPY); */ if (forest->from_method & T8_FOREST_FROM_ADAPT) { SC_CHECK_ABORT (forest->set_adapt_fn != NULL, "No adapt function specified"); - t8_debugf("from method von forest in adapt %i\n",forest->from_method ); forest->from_method -= T8_FOREST_FROM_ADAPT; if (forest->from_method > 0) { @@ -638,7 +636,6 @@ t8_forest_commit (t8_forest_t forest) } } if (forest->from_method & T8_FOREST_FROM_PARTITION) { - t8_debugf("from method in partition %i\n",forest->from_method ); partitioned = 1; /* Partition this forest */ forest->from_method -= T8_FOREST_FROM_PARTITION; @@ -678,7 +675,6 @@ t8_forest_commit (t8_forest_t forest) } } if (forest->from_method & T8_FOREST_FROM_BALANCE) { - t8_debugf("from method in balance %i\n",forest->from_method ); /* balance the forest */ forest->from_method -= T8_FOREST_FROM_BALANCE; if (forest->from_method > 0) { @@ -721,7 +717,6 @@ t8_forest_commit (t8_forest_t forest) } } if (forest->from_method & T8_FOREST_FROM_TRANSITION) { - t8_debugf("from method in transition %i\n",forest->from_method ); forest->from_method -= T8_FOREST_FROM_TRANSITION; /* this is the last from method that we execute, * nothing should be left todo */ @@ -733,7 +728,6 @@ t8_forest_commit (t8_forest_t forest) if (forest_from != forest->set_from) { /* decrease reference count of intermediate input forest, possibly destroying it */ t8_forest_unref (&forest->set_from); - } /* reset forest->set_from */ forest->set_from = forest_from; diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx index d692b91178..11592fd445 100644 --- a/src/t8_forest/t8_forest_transition.cxx +++ b/src/t8_forest/t8_forest_transition.cxx @@ -194,7 +194,6 @@ t8_forest_transition_conformal_hex (t8_forest_t forest, neigh_scheme, iface, &neigh_face); - /* TODO: Update this code block for hex / sub-pyramids. */ if (neighbor_tree >= 0) { if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, face_neighbor[0], diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index baa5bae4d1..8b69ac0242 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1952,7 +1952,7 @@ t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *ele t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; p8est_quadrant_t *q1 = &phex_w_sub->p8q; p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); - /* get location information of the given subelement */ + /* get location information of the given subelement */ int location[3] = { }; t8_element_get_location_of_subelement (elem, location); @@ -2533,7 +2533,7 @@ t8_subelement_scheme_hex_c::t8_element_to_transition_cell (const t8_element_t T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (transition_type >= 0 && transition_type <= T8_SUB_HEX_MAX_TRANSITION_TYPE); - int num_subelements = + int num_subelements = t8_element_get_number_of_subelements (transition_type); #ifdef T8_ENABLE_DEBUG @@ -2560,7 +2560,6 @@ t8_subelement_scheme_hex_c::t8_element_to_transition_cell (const t8_element_t phex_w_sub_subelement[sub_id_counter]->transition_type = transition_type; - //Überlegung transition type umwandeln in subelement id--> nicht einfach counter phex_w_sub_subelement[sub_id_counter]->subelement_id = sub_id_counter; T8_ASSERT (t8_element_is_valid (c[sub_id_counter])); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 39c369b350..9ac2460a0e 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -195,40 +195,66 @@ public: virtual int t8_element_num_face_children (const t8_element_t *elem, const int face) const; - /** Return the number of children of an element's face when the element is refined. */ + /** + * + * \param [in] elem The element. + * \param [in] face A face of elem + * \return True if the neighbor of elems' face is a sibling + * + */ virtual int t8_element_neighbor_is_sibling (const t8_element_t *elem, int face) const; - /** Return the number of sibling neighbors at a given face. */ + /** + * + * \param [in] elem The element. + * \param [in] face A face of elem + * \return Number of sibling neighbors at face + * + */ virtual int t8_element_get_num_sibling_neighbors_at_face (const t8_element_t *elem, int face) const; - /** Return zero refine value for schemes that do not have a transition implementation. */ + /** \return zero refine value for schemes that do not have a transition implementation. */ virtual int t8_element_get_transition_refine_identifier (void) const; - /** Return the corner number of an element's face corner. */ + /** Return the corner number of an element's face corner. + * \param [in] element The element. + * \param [in] face A face index for \a element. + * \param [in] corner A corner index for the face 0 <= \a corner < num_face_corners. + * \return The corner number of the \a corner-th vertex of \a face. + */ virtual int t8_element_get_face_corner (const t8_element_t *element, int face, int corner) const; - /** Return the face numbers of the faces sharing an element's corner. */ + /** Return the face numbers of the faces sharing an element's corner. + * \param [in] element The element. + * \param [in] corner A corner index for the face. + * \param [in] face A face index for \a corner. + * \return The face number of the \a face-th face at \a corner. + */ virtual int t8_element_get_corner_face (const t8_element_t *element, int corner, int face) const; - /** Construct the child element of a given number. */ + /** Construct the child element of a given number. + * \param [in] elem This must be a valid element, bigger than maxlevel. + * \param [in] childid The number of the child to construct. + * \param [in,out] child The storage for this element must exist + * and match the element class of the child. + * On output, a valid element. + * It is valid to call this function with elem = child. + */ virtual void t8_element_child (const t8_element_t *elem, int childid, t8_element_t *child) const; /** Construct all sibling neighbors of elem at face - it is required that sibling neighbors of elem at face exist */ virtual void - - - - t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t + t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t *elem, const int face, const int @@ -409,18 +435,22 @@ public: * \param [in] user_data User data. * \param [out] out_coords The coordinates of the point in the reference space of the tree. */ - virtual void t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, - double *out_coords) - const; + virtual void + t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, + double *out_coords) const; -/** Construct a transition cell of type type */ - virtual void t8_element_to_transition_cell (const t8_element_t *elem, - int type, - t8_element_t *c[]); +/** Construct a transition cell of type type + * + * \param [in] elem The element. + * \param [in] type The transition type + * \param [out] out_coords The coordinates of the point in the reference space of the tree. + */ + virtual void + t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *c[]); /** Determine the number of sibling subelements, of a transition cell of a specific type */ - virtual int t8_element_get_number_of_subelements (int - transition_type) + virtual int + t8_element_get_number_of_subelements (int transition_type) const; /** Test whether a given element is a subelement or not */ From c035cb572874d54f5d98f1cf07a2f6472b7cb632 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 12 Jun 2024 10:55:08 +0200 Subject: [PATCH 26/55] Better documentaion in t8_forest_transition.h --- src/t8_forest/t8_forest_transition.h | 72 ++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/src/t8_forest/t8_forest_transition.h b/src/t8_forest/t8_forest_transition.h index 023c113ec1..d1cd5290ce 100644 --- a/src/t8_forest/t8_forest_transition.h +++ b/src/t8_forest/t8_forest_transition.h @@ -36,7 +36,8 @@ T8_EXTERN_C_BEGIN (); -/* In this function, use a binary encoding (depending on the face enumeration), to determine which subelement type to use. + + /** In this function, use a binary encoding (depending on the face enumeration), to determine which subelement type to use. * Every face has a flag parameter, which is set to 1, if there is a neighbour with a higher level * and to 0, if the level of the neighbour is at most the level of the element. * @@ -53,29 +54,58 @@ T8_EXTERN_C_BEGIN (); * Note, that this procedure is independent of the eclass (we only show an example for the quad scheme). * Each neighbour-structure will lead to a unique binary code. * Within the element scheme of the given eclass, this binary code is used to construct the right subelement type, - * in order to remove hanging nodes from the mesh. */ -int t8_forest_transition_adapt (t8_forest_t forest, - t8_forest_t - forest_from, - t8_locidx_t - ltree_id, - t8_locidx_t - lelement_id, - t8_eclass_scheme_c *ts, - int num_elements, - t8_element_t *elements[]); - -/* This function is the point of entry for the hanging-faces-removing subelements. + * in order to remove hanging nodes from the mesh. + + * \param [in] forest the forest to which the new elements belong + * \param [in] forest_from the forest that is adapted. + * \param [in] which_tree the local tree containing \a elements + * \param [in] lelement_id the local element id in \a forest_old in the tree of the current element + * \param [in] ts the eclass scheme of the tree + * \param [in] is_family if 1, the first \a num_elements entries in \a elements form a family. If 0, they do not. + * \param [in] num_elements the number of entries in \a elements that are defined + * \param [in] elements Pointers to a family or, if \a is_family is zero, + * pointer to one element. + * \return transition type + 1 (to avoid return value 1) + */ + + +int +t8_forest_transition_adapt (t8_forest_t forest, + t8_forest_t forest_from, + t8_locidx_t ltree_id, + t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, + int num_elements, + t8_element_t *elements[]); + + + /** This function is the point of entry for the hanging-faces-removing subelements. * In this function, the corresponding callback function for the refine value in forest_adapt is set - * and the forest is adapted. */ -void t8_forest_transition (t8_forest_t forest); + * and the forest is adapted. + * \param [in,out] forest The input forest consists of hanging nodes on faces- + * The output forest contains transition cells and no hanging nodes on faces. + */ +void +t8_forest_transition (t8_forest_t forest); + + +/** This function is the point of entry in order to untransition a forest before adapting it. + * Every transition cell gets coarsened back to its parent element. + * \param [in,out] forest The input forest consists of subelements- + * The output forest does not. + */ + +void +t8_forest_untransition (t8_forest_t forest); -/* This function is the point of entry in order to untransition a forest before adapting it. - * Every transition cell gets coarsened back to its parent element. */ -void t8_forest_untransition (t8_forest_t forest); + /** Check whether the forest is transitioned, meaning that subelements exist. + * \param [in] forest The input forest that may or may not contains subelements + * \return true if forest contains subelements or false if not. + * + */ -/* Check whether the forest is transitioned, meaning that subelements exist. */ -int t8_forest_is_transitioned (t8_forest_t forest); +int +t8_forest_is_transitioned (t8_forest_t forest); T8_EXTERN_C_END (); From 1fe0f32b8ee9b57bd83302159cd1a7b86a5b8ec2 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 12 Jun 2024 12:47:03 +0200 Subject: [PATCH 27/55] Little clean-up + documentation --- example/transition/t8_transition_forest.cxx | 2 +- .../t8_transition_multiple_trees_hex.cxx | 2 +- .../t8_transition_conformal_hex_cxx.cxx | 38 +- .../t8_transition_conformal_hex_cxx.hxx | 468 ++++++++++-------- 4 files changed, 276 insertions(+), 234 deletions(-) diff --git a/example/transition/t8_transition_forest.cxx b/example/transition/t8_transition_forest.cxx index 3edc00c830..9b804a71f4 100644 --- a/example/transition/t8_transition_forest.cxx +++ b/example/transition/t8_transition_forest.cxx @@ -45,7 +45,7 @@ /* Adapt a forest such that always the first child of a * tree is refined and no other elements. This results in a highly - * inbalanced forest. */ + * imbalanced forest. */ static int t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, t8_locidx_t lelement_id, t8_eclass_scheme_c *ts, const int is_family, const int num_elements, t8_element_t *elements[]) diff --git a/example/transition/t8_transition_multiple_trees_hex.cxx b/example/transition/t8_transition_multiple_trees_hex.cxx index 7ba0c81a1c..e4ab7d81c0 100644 --- a/example/transition/t8_transition_multiple_trees_hex.cxx +++ b/example/transition/t8_transition_multiple_trees_hex.cxx @@ -125,7 +125,7 @@ t8_transition_global (void) t8_forest_write_vtk (forest, "forest_global_hex" ); - for (int adaptation_count = 1; adaptation_count <= 1; ++adaptation_count) { + for (int adaptation_count = 1; adaptation_count <= 2; ++adaptation_count) { forest_adapt = t8_test_forest_commit_abpt(forest); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 8b69ac0242..a8db87d25a 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -234,9 +234,6 @@ t8_subelement_scheme_hex_c::t8_element_parent (const t8_element_t *elem, /* the parent of any element will never be a subelement */ t8_element_reset_subelement_values (parent); - // t8_element_copy_surround (q, r); - - // SC_ABORT_NOT_REACHED(); } void @@ -1015,10 +1012,7 @@ t8_subelement_scheme_hex_c::t8_element_children (const t8_element_t *elem, for (ichild = 0; ichild < P8EST_CHILDREN; ++ichild) { t8_element_reset_subelement_values (c[ichild]); - // t8_element_copy_surround (q, &phex_w_sub_children[ichild]->p8q); } - - // SC_ABORT_NOT_REACHED(); } int @@ -1164,7 +1158,6 @@ t8_subelement_scheme_hex_c::t8_element_first_descendant (const t8_element_t * a subelement, we reset the corresponding subelement values. */ t8_element_reset_subelement_values (desc); - // SC_ABORT_NOT_REACHED(); } void @@ -1228,18 +1221,13 @@ t8_subelement_scheme_hex_c::t8_element_nca (const t8_element_t *elem1, T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); -// #if 0 -// /* TODO: This assertions throws an error since it expects a 3D hex. -// * this does not make sense. investigate. */ -// T8_ASSERT (t8_element_surround_matches (q1, q2)); -// #endif /* In case of subelements, we use the parent quadrant and construct nca of the parent quadrant */ t8_element_reset_subelement_values (nca); p8est_nearest_common_ancestor (q1, q2, r); } -//Nummerierung der Seiten(der Pyramiden) wie in Davids Masterarbeit + t8_element_shape_t t8_subelement_scheme_hex_c::t8_element_face_shape (const t8_element_t *elem, int face) const @@ -1749,8 +1737,6 @@ int location[3] = { }; } else { /* in this case the face neighbor is no sibling */ - // int location[3] = { }; - // t8_element_get_location_of_subelement (elem, location); /* setting the anchor node of the neighbor element */ n->x = q->x; @@ -2617,14 +2603,13 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const * We will use the binary representation to determine the location of the given subelement. * * We need to know: - * i) the face number of the first vertex (values: {0,1,2,3}). + * i) the face number of the first vertex (values: {0,1,2,3,4,5}). * ii) whether this face is split in half (values: {0,1}). - * iii) if the subelement is the first or second subelement at the face (values: {0,1}). + * iii) the subelement_id_type. * * These information are then saved in the location array which will be used by the element_vertex function, * to automatically determine the vertex coordinates of the given subelement. * - * The location array for the above example would be {1,1,1} (upper face, split = true, second subelement at the upper face). */ /* 1) convert the transition type from a decimal to a binary representation */ int type = phex_w_sub->transition_type; @@ -2931,7 +2916,7 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell t8_element_get_id_from_location (t8_element_get_transition_type (pseudo_neigh), location_neigh); } - //Now, elem is no subelement. + //Elem is no subelement. else{ /* In this case, we have the following examplary situation for the 2D quad case: * @@ -3077,21 +3062,12 @@ t8_subelement_scheme_hex_c::t8_element_get_id_from_location (int type, } } -// t8_productionf("subelements count % i \n transition type %i, und location [0]= %i, location[1] = %i, location [2] = %i \n", subelements_count, type ,location[0] ,location[1] ,location[2] ); /* get the sub_id */ sub_id = subelements_count - 1; return sub_id; } -int -t8_subelement_scheme_hex_c::t8_element_get_face_number_of_hypotenuse (const - t8_element_t - *elem) -{ - SC_ABORT_NOT_REACHED(); - -} void t8_subelement_scheme_hex_c::t8_element_new (int length, t8_element_t **elem) const @@ -3134,12 +3110,6 @@ t8_subelement_scheme_hex_c::t8_element_scheme_supports_transitioning (void) return T8_HEX_TRANSITION_IS_IMPLEMENTED; } -int -t8_subelement_scheme_hex_c::t8_element_transition_scheme_is_conformal (void) -{ - return T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL; -} - int t8_subelement_scheme_hex_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const{ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 9ac2460a0e..2f211099f3 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -137,63 +137,88 @@ public: ~t8_subelement_scheme_hex_c (); - /** Allocate memory for a given number of elements. - * In debugging mode, ensure that all elements are valid \ref t8_element_is_valid. + /** Allocate memory for an array of subelements and initialize them. + * \param [in] length The number of hex to be allocated. + * \param [in,out] elems On input an array of \b length many unallocated + * element pointers. + * On output all these pointers will point to an allocated + * and initialized element. + * \note Not every element that is created in t8code will be created by a call + * to this function. However, if an element is not created using \ref t8_element_new, + * then it is guaranteed that \ref t8_element_init is called on it. + * \note In debugging mode, an element that was created with \ref t8_element_new + * must pass \ref t8_element_is_valid. + * \note If an element was created by \ref t8_element_new then \ref t8_element_init + * may not be called for it. Thus, \ref t8_element_new should initialize an element + * in the same way as a call to \ref t8_element_init would. + * \see t8_element_init + * \see t8_element_is_valid */ - virtual void t8_element_new (int length, t8_element_t **elem) const; + virtual void + t8_element_new (int length, t8_element_t **elem) const; -/** Return the maximum level allowed for this element class. */ - virtual int t8_element_maxlevel (void) const; + /** Return the maximum allowed level for this element class. + * \return The maximum allowed level for elements of this class (in this case HEX). + */ + virtual int + t8_element_maxlevel (void) const; /** Return the type of each child in the ordering of the implementation. */ - virtual t8_eclass_t t8_element_child_eclass (int childid) const; + virtual t8_eclass_t + t8_element_child_eclass (int childid) const; /** Return the refinement level of an element. */ - virtual int t8_element_level (const t8_element_t *elem) const; + virtual int + t8_element_level (const t8_element_t *elem) const; /** Copy one element to another */ - virtual void t8_element_copy (const t8_element_t *source, - t8_element_t *dest) const; + virtual void + t8_element_copy (const t8_element_t *source, + t8_element_t *dest) const; /** Compare to elements. returns negative if elem1 < elem2, zero if elem1 equals elem2 * and positive if elem1 > elem2. * If elem2 is a copy of elem1 then the elements are equal. * If both elements are sibling subelements, return 0 if they are identical (same sub_id) and 1 otherwise. */ - virtual int t8_element_compare (const t8_element_t *elem1, + virtual int + t8_element_compare (const t8_element_t *elem1, const t8_element_t *elem2) const; /** Construct the parent of a given element. */ - virtual void t8_element_parent (const t8_element_t *elem, + virtual void + t8_element_parent (const t8_element_t *elem, t8_element_t *parent) const; /** Construct a same-size sibling of a given element. */ - virtual void t8_element_sibling (const t8_element_t *elem, + virtual void + t8_element_sibling (const t8_element_t *elem, int sibid, t8_element_t *sibling) const; /** Compute the number of face of a given element. */ - virtual int t8_element_num_faces (const t8_element_t *elem) const; + virtual int + t8_element_num_faces (const t8_element_t *elem) const; /** Compute the maximum number of faces of a given element and all of its * descendants. * \param [in] elem The element. * \return The maximum number of faces of \a elem and its descendants. */ - virtual int t8_element_max_num_faces (const t8_element_t *elem) - const; + virtual int + t8_element_max_num_faces (const t8_element_t *elem) const; /** Return the number of children of an element when it is refined. */ - virtual int t8_element_num_children (const t8_element_t *elem) - const; + virtual int + t8_element_num_children (const t8_element_t *elem) const; /** Return the number of siblings of an element (or the number of elements in the family of elem) */ - virtual int t8_element_num_siblings (const t8_element_t *elem) - const; + virtual int + t8_element_num_siblings (const t8_element_t *elem) const; /** Return the number of children of an element's face when the element is refined. */ - virtual int t8_element_num_face_children (const t8_element_t *elem, - const int face) const; + virtual int + t8_element_num_face_children (const t8_element_t *elem, const int face) const; /** * @@ -202,8 +227,8 @@ public: * \return True if the neighbor of elems' face is a sibling * */ - virtual int t8_element_neighbor_is_sibling (const t8_element_t - *elem, int face) const; + virtual int + t8_element_neighbor_is_sibling (const t8_element_t *elem, int face) const; /** * @@ -212,15 +237,13 @@ public: * \return Number of sibling neighbors at face * */ - virtual int t8_element_get_num_sibling_neighbors_at_face (const - t8_element_t - *elem, - int face) - const; + virtual int + t8_element_get_num_sibling_neighbors_at_face (const t8_element_t *elem, + int face) const; /** \return zero refine value for schemes that do not have a transition implementation. */ - virtual int t8_element_get_transition_refine_identifier (void) - const; + virtual int + t8_element_get_transition_refine_identifier (void) const; /** Return the corner number of an element's face corner. * \param [in] element The element. @@ -228,8 +251,9 @@ public: * \param [in] corner A corner index for the face 0 <= \a corner < num_face_corners. * \return The corner number of the \a corner-th vertex of \a face. */ - virtual int t8_element_get_face_corner (const t8_element_t *element, - int face, int corner) const; + virtual int + t8_element_get_face_corner (const t8_element_t *element, + int face, int corner) const; /** Return the face numbers of the faces sharing an element's corner. * \param [in] element The element. @@ -237,8 +261,9 @@ public: * \param [in] face A face index for \a corner. * \return The face number of the \a face-th face at \a corner. */ - virtual int t8_element_get_corner_face (const t8_element_t *element, - int corner, int face) const; + virtual int + t8_element_get_corner_face (const t8_element_t *element, + int corner, int face) const; /** Construct the child element of a given number. * \param [in] elem This must be a valid element, bigger than maxlevel. @@ -248,9 +273,10 @@ public: * On output, a valid element. * It is valid to call this function with elem = child. */ - virtual void t8_element_child (const t8_element_t *elem, - int childid, - t8_element_t *child) const; + virtual void + t8_element_child (const t8_element_t *elem, + int childid, + t8_element_t *child) const; /** Construct all sibling neighbors of elem at face - it is required that sibling neighbors of elem at face exist */ virtual void @@ -264,153 +290,168 @@ public: int *neigh_face); /** Construct all children of a given element. */ - virtual void t8_element_children (const t8_element_t *elem, - int length, - t8_element_t *c[]) const; + virtual void + t8_element_children (const t8_element_t *elem, + int length, + t8_element_t *c[]) const; /** Return the child id of an element */ - virtual int t8_element_child_id (const t8_element_t *elem) const; + virtual int + t8_element_child_id (const t8_element_t *elem) const; /** Compute the ancestor id of an element */ - virtual int t8_element_ancestor_id (const t8_element_t *elem, - int level) const; + virtual int + t8_element_ancestor_id (const t8_element_t *elem, + int level) const; /** Return nonzero if collection of elements is a family */ - virtual int t8_element_is_family (t8_element_t *const *fam) const; + virtual int + t8_element_is_family (t8_element_t *const *fam) const; /** Construct the nearest common ancestor of two elements in the same tree. */ - virtual void t8_element_nca (const t8_element_t *elem1, - const t8_element_t *elem2, - t8_element_t *nca) const; + virtual void + t8_element_nca (const t8_element_t *elem1, + const t8_element_t *elem2, + t8_element_t *nca) const; /** Compute the element shape of the face of an element. */ - virtual t8_element_shape_t t8_element_face_shape (const t8_element_t *elem, - int face) const; + virtual t8_element_shape_t + t8_element_face_shape (const t8_element_t *elem, + int face) const; /** Given an element and a face of the element, compute all children of * the element that touch the face. */ /** Given an element and a face of the element, compute all children of * the element that touch the face. */ - virtual void t8_element_children_at_face (const t8_element_t *elem, - int face, - t8_element_t *children[], - int num_children, - int *child_indices) const; + virtual void + t8_element_children_at_face (const t8_element_t *elem, + int face, + t8_element_t *children[], + int num_children, + int *child_indices) const; /** Given a face of an element and a child number of a child of that face, return the face number * of the child of the element that matches the child face. */ - virtual int t8_element_face_child_face (const t8_element_t *elem, - int face, - int face_child) const; + virtual int + t8_element_face_child_face (const t8_element_t *elem, + int face, int face_child) const; /** Given a face of an element return the face number * of the parent of the element that matches the element's face. Or return -1 if * no face of the parent matches the face. */ - virtual int t8_element_face_parent_face (const t8_element_t *elem, - int face) const; + virtual int + t8_element_face_parent_face (const t8_element_t *elem, + int face) const; /** Transform the coordinates of a hexaliteral considered as boundary element * in a tree-tree connection. */ - virtual void t8_element_transform_face (const t8_element_t *elem1, - t8_element_t *elem2, - int orientation, int sign, - int is_smaller_face) const; + virtual void + t8_element_transform_face (const t8_element_t *elem1, + t8_element_t *elem2, + int orientation, int sign, + int is_smaller_face) const; /** Given a boundary face inside a root tree's face construct * the element inside the root tree that has the given face as a * face. */ - virtual int t8_element_extrude_face (const t8_element_t *face, - const t8_eclass_scheme_c - *face_scheme, - t8_element_t *elem, - int root_face) const; + virtual int + t8_element_extrude_face (const t8_element_t *face, + const t8_eclass_scheme_c *face_scheme, + t8_element_t *elem, + int root_face) const; /** Return the tree face id given a boundary face. */ - virtual int t8_element_tree_face (const t8_element_t *elem, - int face) const; + virtual int + t8_element_tree_face (const t8_element_t *elem, + int face) const; /** Construct the first descendant of an element that touches a given face. */ - virtual void t8_element_first_descendant_face (const t8_element_t - *elem, int face, - t8_element_t - *first_desc, - int level) const; + virtual void + t8_element_first_descendant_face (const t8_element_t *elem, int face, + t8_element_t *first_desc, + int level) const; /** Construct the last descendant of an element that touches a given face. */ - virtual void t8_element_last_descendant_face (const t8_element_t - *elem, int face, - t8_element_t - *last_desc, - int level) const; + virtual void + t8_element_last_descendant_face (const t8_element_t *elem, int face, + t8_element_t *last_desc, + int level) const; /** Construct the boundary element at a specific face. */ - virtual void t8_element_boundary_face (const t8_element_t *elem, - int face, - t8_element_t *boundary, - const t8_eclass_scheme_c - *boundary_scheme) const; + virtual void + t8_element_boundary_face (const t8_element_t *elem, + int face, t8_element_t *boundary, + const t8_eclass_scheme_c *boundary_scheme) const; /** Construct all codimension-one boundary elements of a given element. */ - virtual void t8_element_boundary (const t8_element_t *elem, - int min_dim, int length, - t8_element_t **boundary) const; + virtual void + t8_element_boundary (const t8_element_t *elem, + int min_dim, int length, + t8_element_t **boundary) const; /** Compute whether a given element shares a given face with its root tree. * \param [in] elem The input element. * \param [in] face A face of \a elem. * \return True if \a face is a subface of the element's root element. */ - virtual int t8_element_is_root_boundary (const t8_element_t *elem, - int face) const; + virtual int + t8_element_is_root_boundary (const t8_element_t *elem, + int face) const; /** Construct the face neighbor of a given element if this face neighbor * is inside the root tree. Return 0 otherwise. */ - virtual int t8_element_face_neighbor_inside (const t8_element_t - *elem, - t8_element_t *neigh, - int face, - int *neigh_face) const; + virtual int + t8_element_face_neighbor_inside (const t8_element_t *elem, + t8_element_t *neigh, + int face, + int *neigh_face) const; /** Initialize an element according to a given linear id */ - virtual void t8_element_set_linear_id (t8_element_t *elem, - int level, - t8_linearidx_t id) const; + virtual void + t8_element_set_linear_id (t8_element_t *elem, + int level, t8_linearidx_t id) const; /** Calculate the linear id of an element */ - virtual t8_linearidx_t t8_element_get_linear_id (const - t8_element_t *elem, - int level) const; + virtual t8_linearidx_t + t8_element_get_linear_id (constt8_element_t *elem, + int level) const; /** Calculate the first descendant of a given element e. That is, the * first element in a uniform refinement of e of the maximal possible level. */ - virtual void t8_element_first_descendant (const t8_element_t *elem, - t8_element_t *desc, - int level) const; + virtual void + t8_element_first_descendant (const t8_element_t *elem, + t8_element_t *desc, + int level) const; /** Calculate the last descendant of a given element e. That is, the * last element in a uniform refinement of e of the maximal possible level. */ - virtual void t8_element_last_descendant (const t8_element_t *elem, - t8_element_t *desc, - int level) const; + virtual void + t8_element_last_descendant (const t8_element_t *elem, + t8_element_t *desc, + int level) const; /** Compute s as a successor of t*/ - virtual void t8_element_successor (const t8_element_t *t, t8_element_t *s) const; + virtual void + t8_element_successor (const t8_element_t *t, t8_element_t *s) const; /** Get the integer coordinates of the anchor node of an element */ - virtual void t8_element_anchor (const t8_element_t *elem, - int anchor[3]) const; + virtual void + t8_element_anchor (const t8_element_t *elem, + int anchor[3]) const; /** Get the integer root length of an element, that is the length of * the level 0 ancestor. */ - virtual int t8_element_root_len (const t8_element_t *elem) const; + virtual int + t8_element_root_len (const t8_element_t *elem) const; /** Compute the integer coordinates of a given element vertex. */ - virtual void t8_element_vertex_coords (const t8_element_t *t, - int vertex, - int coords[]) const; + virtual void + t8_element_vertex_coords (const t8_element_t *t, + int vertex, + int coords[]) const; /** Compute the integer coordinates of a given element vertex. @@ -448,57 +489,84 @@ public: virtual void t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *c[]); -/** Determine the number of sibling subelements, of a transition cell of a specific type */ +/** Determine the number of sibling subelements, of a transition cell of a specific type + * + * \param [in] type The transition type. + * \return The number of sibling subelements, of a transition cell with the given transition type. + */ virtual int - t8_element_get_number_of_subelements (int transition_type) - const; + t8_element_get_number_of_subelements (int transition_type) const; -/** Test whether a given element is a subelement or not */ - virtual int t8_element_is_subelement (const t8_element * - elem) const; +/** Test whether a given element is a subelement or not + * + * \param [in] elem The element. + * \return true if elem is a subelement, otherwise false. + */ + virtual int + t8_element_is_subelement (const t8_element * elem) const; + + +/** Get the subelement type of an element + * + * \param [in] elem The element. + * \return Transition type of elem. + */ + virtual int + t8_element_get_transition_type (const t8_element * elem); -/** Get the subelement type of elem */ - virtual int t8_element_get_transition_type (const - t8_element * elem); -/** Get the subelement id of elem */ - virtual int t8_element_get_subelement_id (const t8_element * elem) const; +/** Get the subelement ID of an element + * + * \param [in] elem The element. + * \return Subelement ID of \a elem. + */ + virtual int + t8_element_get_subelement_id (const t8_element * elem) const; -/** Get the subelement id of the neighbor subelement of elem at face elem_face - * that is a sibling of the subelement neigh. +/** */ - virtual int t8_element_find_neighbor_in_transition_cell (const - t8_element_t - *elem, - const - t8_element_t - *neigh, - int - elem_face); - -/** Get the face-number of the hypotenuse of the triangular subelement */ - virtual int t8_element_get_face_number_of_hypotenuse (const - t8_element_t - *elem); - -/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ - virtual int t8_element_scheme_supports_transitioning (void); - -/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ - virtual int t8_element_transition_scheme_is_conformal (void); - -/** Returns true, if there is one element in the tree, that does not refine into 2^dim children. - * Returns false otherwise. - * \return non-zero if there is one element in the tree that does not refine into 2^dim children. - */ - virtual int t8_element_refines_irregular (void) const; + /** Get the subelement ID of the neighbor subelement of elem at face elem_face + * that is a sibling of the subelement neigh (That means: lives in the same transition cell) + * + * \param [in] elem The element. + * \param [in] neigh The neighbor. + * \param [in] elem_face The face number of elem + * \return Subelement ID of \a neigh which is a neighbor of \a elem at face \a elem_face. + */ + virtual int + t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, + const t8_element_t *neigh, + int elem_face); + -/** Get the shape of a given element. Subelements are pyramids */ - virtual t8_element_shape_t t8_element_shape (const t8_element_t *elem) - const; + /** Check if the eclass scheme has an implementation for subelements. + * \return True if the scheme has an implementation for subelements, otherwise return false. + */ + virtual int + t8_element_scheme_supports_transitioning (void); + +/** Checks if there is one element in the tree, that does not refine into 2^dim children. + * + * \return True, if there is one element in the tree that does not refine into 2^dim children, return false otherwise. + */ + virtual int + t8_element_refines_irregular (void) const; -/** Return the number of vertices of an element */ - virtual int t8_element_num_corners (const t8_element_t *elem) const; +/** Get the shape of a given element. Subelements of the hexahedral transition scheme are pyramids. + * + * \param [in] elem The element. + * \return Shape of \a elem. + */ + virtual t8_element_shape_t + t8_element_shape (const t8_element_t *elem) const; + +/** Return the number of vertices of an element. A subelement in the hexahedral transition scheme has five vertices. + * + * \param [in] elem The element. + * \return Number of vertices of \a elem. + */ + virtual int + t8_element_num_corners (const t8_element_t *elem) const; /** Compute the coordinates of a given element vertex inside a reference tree * that is embedded into [0,1]^d (d = dimension). @@ -507,10 +575,9 @@ public: * \param [out] coords An array of at least as many doubles as the element's dimension * whose entries will be filled with the coordinates of \a vertex. */ - virtual void t8_element_vertex_reference_coords (const t8_element_t - *t, int vertex, - double coords[]) - const; + virtual void + t8_element_vertex_reference_coords (const t8_element_t *t, int vertex, + double coords[]) const; #ifdef T8_ENABLE_DEBUG /** TODO: this should be the new element_print_element function */ @@ -522,65 +589,63 @@ public: protected: /** This function determines the vertex coordinates of subelements. - * \param [in] elem A valid subelement - * \param [in] vertex the number of the vertex whose coordinates should be determined + * \param [in] elem A valid subelement + * \param [in] vertex the number of the vertex whose coordinates should be determined * \param [out] coords An array whose entries will be filled with the coordinates of the - * subelement. + * subelement. * Note that subelements can have another number of vertices compared to the used * eclass scheme. For example, subelements that remove hanging nodes from the HEX scheme * are triangles with 3 instead of 4 vertices. */ - void t8_element_vertex_coords_of_subelement (const - t8_element_t *t, - int vertex, - int coords[]) - const; + void + t8_element_vertex_coords_of_subelement (const t8_element_t *t, + int vertex, + int coords[]) const; /** This function will determine the location of a specific subelement in the parent element. * Since different subelement types are possible, it is a priori not known where for example the * subelement with id 3 is located. - * \param [in] elem A valid subelement - * \param [out] An array, whose entries are face_number, split and sub_face_id - * face_number: the face number (clockwise enumeration), the given subelement is adjacent to (value between 0 and 3) + * \param [in] elem A valid subelement + * \param [out] location An array, whose entries are face_number, split and sub_id_type + * face_number: the face number the given subelement is adjacent to (value between 0 and 5) * It can be translated to the HEX enumeration via subelement_location_to_parent_dual_face[location[0]] - * split: whether there is a hanging node at the face, the subelement is adjacent to + * split: whether there is a hanging node at the face, the subelement is adjacent to * (value 0 if there is not hanging node and 1 if there is one) - * sub_face_id: if there is a hanging node at the face, it is important to know if the given - * subelement is the first or the second subelement at this face - * (value 0 if it is the first and 1 if it is the second) + * sub_id_type: if there is a hanging node at the face, it is important to know where exactly the subelement is located. * The information in the location can be used to automatically determine the vertices of any subelement. * Since this function is only used to determine the vertices of subelements, it can be declared as a private/protected function. */ - void t8_element_get_location_of_subelement (const - t8_element_t - *elem, - int location[]) - const; + void + t8_element_get_location_of_subelement (const t8_element_t *elem, + int location[]) const; - /** This help function returns the subelement if of an element whose location and transition type is known. */ - int t8_element_get_id_from_location (int type, - int location[]); + /** This help function returns the subelement ID of an element whose location and transition type is known. + * \param [in] type Transition type + * \param [in] location The location array of a subelement. + * \param [out] subelement_ID The subelement ID of the subelement with transition type \a type and location array \a location[] + */ + int + t8_element_get_id_from_location (int type, int location[]); /** This function copies the subelement values from source to dest. - * \param [in] source A valid element - * \param [in,out] dest A valid element, whose subelement values are equal to those of source + * \param [in] source A valid element + * \param [in,out] dest A valid element, whose subelement values are equal to those of source */ - void t8_element_copy_subelement_values (const - t8_element_t *source, - t8_element_t *dest) - const; + void + t8_element_copy_subelement_values (const t8_element_t *source, + t8_element_t *dest) const; - /** This function resets the subelement values of an element to the default value -1. + /** This function resets the subelement values of an element to the default value 0. * \param [in,out] elem A valid element, whose subelement values have been reset. */ - void t8_element_reset_subelement_values (t8_element_t *elem) - const; + void + t8_element_reset_subelement_values (t8_element_t *elem) const; /** Check if two elements are equal. * \param [in] ts Implementation of a class scheme. * \param [in] elem1 The first element. * \param [in] elem2 The second element. - * \return 1 if the elements are equal, 0 if they are not equal + * \return 1 (true) if the elements are equal, 0 (false) if they are not equal */ virtual int t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const; @@ -611,6 +676,14 @@ protected: virtual void t8_element_init (int length, t8_element_t *elem) const; + /** Pack multiple elements (also subelements) into contiguous memory, so they can be sent via MPI. + * \param [in] elements Array of elements that are to be packed + * \param [in] count Number of elements to pack + * \param [in,out] send_buffer Buffer in which to pack the elements + * \param [in] buffer_size size of the buffer (in order to check that we don't access out of range) + * \param [in, out] position the position of the first byte that is not already packed + * \param [in] comm MPI Communicator + */ virtual void t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, void *send_buffer, int buffer_size, int *position, sc_MPI_Comm comm) const; @@ -640,11 +713,10 @@ protected: * \param [in] source A element * \return true, if the subelement values are valid */ - int t8_element_subelement_values_are_valid (const - t8_element_t - *elem) const; + int + t8_element_subelement_values_are_valid (const t8_element_t *elem) const; - /** + /** * Print a given element. For a example for a triangle print the coordinates * and the level of the triangle. This function is only available in the * debugging configuration. From 4d3f6b32195e6a03cd57c98950f7e0342911a4b9 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 12 Jun 2024 14:56:56 +0200 Subject: [PATCH 28/55] clang-format --- .../transition/t8_transition_basic_hex.cxx | 142 +- example/transition/t8_transition_forest.cxx | 45 +- .../transition/t8_transition_global_hex.cxx | 61 +- .../t8_transition_multiple_trees_hex.cxx | 66 +- src/t8_element_cxx.hxx | 20 +- src/t8_forest/t8_forest.c | 101 +- src/t8_forest/t8_forest_adapt.cxx | 67 +- src/t8_forest/t8_forest_balance.cxx | 2 +- src/t8_forest/t8_forest_cxx.cxx | 3 +- src/t8_forest/t8_forest_general.h | 14 +- src/t8_forest/t8_forest_partition.cxx | 2 +- src/t8_forest/t8_forest_transition.cxx | 184 +- src/t8_forest/t8_forest_transition.h | 21 +- src/t8_forest/t8_forest_types.h | 4 +- .../t8_default_common_cxx.cxx | 14 +- .../t8_default_common_cxx.hxx | 10 +- .../t8_transition_conformal_hex.cxx | 9 +- .../t8_transition_conformal_hex_cxx.cxx | 2665 ++++++++--------- .../t8_transition_conformal_hex_cxx.hxx | 263 +- .../t8_transition_conformal_quad.cxx | 13 +- .../t8_transition_conformal_quad_cxx.cxx | 1086 +++---- .../t8_transition_conformal_quad_cxx.hxx | 465 ++- .../t8_transition/t8_transition_cxx.hxx | 6 +- .../t8_gtest_forest_commit.cxx | 29 +- .../t8_gtest_child_parent_face.cxx | 3 +- .../t8_gtest_descendant.cxx | 1 - test/t8_schemes_transition/t8_gtest_equal.cxx | 1 - .../t8_gtest_face_descendant.cxx | 3 +- .../t8_gtest_face_neigh.cxx | 3 +- test/t8_schemes_transition/t8_gtest_nca.cxx | 1 - .../t8_gtest_pack_unpack.cxx | 1 - .../t8_gtest_successor.cxx | 2 +- 32 files changed, 2262 insertions(+), 3045 deletions(-) diff --git a/example/transition/t8_transition_basic_hex.cxx b/example/transition/t8_transition_basic_hex.cxx index 00d299b342..9348b47515 100644 --- a/example/transition/t8_transition_basic_hex.cxx +++ b/example/transition/t8_transition_basic_hex.cxx @@ -49,15 +49,15 @@ * Do not refine an element if it has reached the maximum level. (Hint: ts->t8_element_level) */ -#include /* General t8code header, always include this. */ -#include /* cmesh definition and basic interface. */ -#include /* A collection of exemplary cmeshes */ -#include /* forest definition and basic interface. */ -#include /* save forest */ -#include /* geometrical information of the forest */ +#include /* General t8code header, always include this. */ +#include /* cmesh definition and basic interface. */ +#include /* A collection of exemplary cmeshes */ +#include /* forest definition and basic interface. */ +#include /* save forest */ +#include /* geometrical information of the forest */ #include #include -#include /* default refinement scheme. */ +#include /* default refinement scheme. */ #include #include "t8_eclass.h" #include @@ -71,10 +71,10 @@ t8_check_coordinates (double *coords) { /* The initial hex_element is the unit hex with vertices (0,0,0), (1,0,0), (0,1,0), (1,1,0), (0,0,1) ,(1,0,1), (0,1,1) and (1,1,1). * We know that therefore, all children (even our subelements) will have vertices with coordinates 0, 0.5 or 1. */ - double eps = 1e-126; /* testing up to float precision */ - if ((fabs (coords[0] - 0.0) < eps || fabs (coords[0] - 0.5) < eps || fabs (coords[0] - 1.0) < eps) && - (fabs (coords[1] - 0.0) < eps || fabs (coords[1] - 0.5) < eps || fabs (coords[1] - 1.0) < eps) && - (fabs (coords[2] - 0.0) < eps || fabs (coords[2] - 0.5) < eps || fabs (coords[2] - 1.0) < eps)){ + double eps = 1e-126; /* testing up to float precision */ + if ((fabs (coords[0] - 0.0) < eps || fabs (coords[0] - 0.5) < eps || fabs (coords[0] - 1.0) < eps) + && (fabs (coords[1] - 0.0) < eps || fabs (coords[1] - 0.5) < eps || fabs (coords[1] - 1.0) < eps) + && (fabs (coords[2] - 0.0) < eps || fabs (coords[2] - 0.5) < eps || fabs (coords[2] - 1.0) < eps)) { return true; } return false; @@ -82,19 +82,18 @@ t8_check_coordinates (double *coords) #endif static void -t8_test_hex_local (t8_element_t *hex_element, - t8_eclass_scheme_c *class_scheme) +t8_test_hex_local (t8_element_t *hex_element, t8_eclass_scheme_c *class_scheme) { t8_debugf ("~~~~~~~~~~ Into the t8_test_hex_local function ~~~~~~~~~~\n"); - t8_element_t *parent; - int num_children, num_vertices; - int child_id; - double coords[3]; + t8_element_t *parent; + int num_children, num_vertices; + int child_id; + double coords[3]; /* Allocate enough memory for hex children */ num_children = class_scheme->t8_element_num_children (hex_element); - t8_element_t **children = T8_ALLOC (t8_element_t *, num_children); + t8_element_t **children = T8_ALLOC (t8_element_t *, num_children); class_scheme->t8_element_new (num_children, children); /* Create all subelements for the given type from the initial hex element. */ @@ -103,9 +102,8 @@ t8_test_hex_local (t8_element_t *hex_element, /* transition cell must be a family of subelements */ T8_ASSERT (class_scheme->t8_element_is_family (children)); - t8_debugf - ("The children array consists of %i elements, whose IDs range from 0 to %i.\n", - num_children, num_children - 1); + t8_debugf ("The children array consists of %i elements, whose IDs range from 0 to %i.\n", num_children, + num_children - 1); /* Iterate through all subelements and determine their vertex coordinates */ for (child_id = 0; child_id < num_children; ++child_id) { @@ -118,25 +116,21 @@ t8_test_hex_local (t8_element_t *hex_element, #endif /* determine the shape of the subelement and use it to determine the number of vertices it has (pyramid -> 5 vertices) */ - const t8_element_shape_t shape = - class_scheme->t8_element_shape (children[child_id]); + const t8_element_shape_t shape = class_scheme->t8_element_shape (children[child_id]); num_vertices = t8_eclass_num_vertices[shape]; t8_debugf ("Num vertices %i \n", num_vertices); - T8_ASSERT (num_vertices == - class_scheme->t8_element_num_corners (children[child_id])); + T8_ASSERT (num_vertices == class_scheme->t8_element_num_corners (children[child_id])); /* Iterate over all vertices of the subelement and determine their coordinates */ - int vertex_count; + int vertex_count; for (vertex_count = 0; vertex_count < num_vertices; ++vertex_count) { - class_scheme->t8_element_vertex_reference_coords (children[child_id], - vertex_count, coords); - t8_debugf - ("Child ID: %d; Vertex: %d; Ref cords in [0,1]^2: (%lf,%lf,%lf)\n", - child_id, vertex_count, coords[0], coords[1], coords[2]); + class_scheme->t8_element_vertex_reference_coords (children[child_id], vertex_count, coords); + t8_debugf ("Child ID: %d; Vertex: %d; Ref cords in [0,1]^2: (%lf,%lf,%lf)\n", child_id, vertex_count, coords[0], + coords[1], coords[2]); T8_ASSERT (t8_check_coordinates (coords)); - } /* end of vertex loop */ - } /* end of subelement loop */ + } /* end of vertex loop */ + } /* end of subelement loop */ /* coarsen the transition cell back to its parent, which must be equal to the initial quad_element */ class_scheme->t8_element_new (1, &parent); @@ -148,27 +142,25 @@ t8_test_hex_local (t8_element_t *hex_element, class_scheme->t8_element_destroy (num_children, children); T8_FREE (children); - t8_debugf - ("~~~~~~~~~~ The t8_test_hex_local function finished successful ~~~~~~~~~~\n"); + t8_debugf ("~~~~~~~~~~ The t8_test_hex_local function finished successful ~~~~~~~~~~\n"); } - static void t8_transition_local (t8_eclass_t eclass) { t8_debugf ("~~~~~~~~~~ Into the t8_transition_local function ~~~~~~~~~~\n"); - t8_scheme_cxx_t *ts = t8_scheme_new_transition_hex_cxx (); + t8_scheme_cxx_t *ts = t8_scheme_new_transition_hex_cxx (); t8_eclass_scheme_c *class_scheme; - t8_element_t *hex_element, *parent; - int subelement_id; - double coords[3]; - int num_subelements; - int num_vertices; + t8_element_t *hex_element, *parent; + int subelement_id; + double coords[3]; + int num_subelements; + int num_vertices; /* At the moment, subelements are only implemented for the quad and hex scheme. */ T8_ASSERT (eclass = T8_ECLASS_HEX); - + class_scheme = ts->eclass_schemes[eclass]; /* Allocate memory for a new hex element and initialize it */ @@ -180,34 +172,29 @@ t8_transition_local (t8_eclass_t eclass) t8_test_hex_local (hex_element, class_scheme); /* Make checks for all transition types */ - int type; - for (type = 1; type <= T8_SUB_HEX_MAX_TRANSITION_TYPE; type++) { + int type; + for (type = 1; type <= T8_SUB_HEX_MAX_TRANSITION_TYPE; type++) { /* Allocate enough memory for subelements of the given type and initialize them */ - num_subelements = - class_scheme->t8_element_get_number_of_subelements (type); + num_subelements = class_scheme->t8_element_get_number_of_subelements (type); - t8_element_t **transition_cell = - T8_ALLOC (t8_element_t *, num_subelements); + t8_element_t **transition_cell = T8_ALLOC (t8_element_t *, num_subelements); class_scheme->t8_element_new (num_subelements, transition_cell); /* Create all subelements for the given type from the initial hex element. */ - class_scheme->t8_element_to_transition_cell (hex_element, type, - transition_cell); + class_scheme->t8_element_to_transition_cell (hex_element, type, transition_cell); /* transition cell must be a family of subelements */ T8_ASSERT (class_scheme->t8_element_is_family (transition_cell)); t8_debugf ("The given type is type %i.\n", type); - t8_debugf - ("The transition cell of type %i consists of %i subelements, whose IDs range from 0 to %i.\n", - type, num_subelements, num_subelements - 1); + t8_debugf ("The transition cell of type %i consists of %i subelements, whose IDs range from 0 to %i.\n", type, + num_subelements, num_subelements - 1); /* Iterate through all subelements and determine their vertex coordinates */ for (subelement_id = 0; subelement_id < num_subelements; ++subelement_id) { /* All elements in a transition cell are subelements */ - T8_ASSERT (class_scheme->t8_element_is_subelement - (transition_cell[subelement_id])); + T8_ASSERT (class_scheme->t8_element_is_subelement (transition_cell[subelement_id])); #if T8_ENABLE_DEBUG /* Print the current subelement */ @@ -215,29 +202,20 @@ t8_transition_local (t8_eclass_t eclass) #endif /* determine the shape of the subelement and use it to determine the number of vertices it has (triangle -> 3 vertices) */ - const t8_element_shape_t shape = - class_scheme->t8_element_shape (transition_cell[subelement_id]); + const t8_element_shape_t shape = class_scheme->t8_element_shape (transition_cell[subelement_id]); num_vertices = t8_eclass_num_vertices[shape]; - T8_ASSERT (num_vertices == - class_scheme->t8_element_num_corners (transition_cell - [subelement_id])); - T8_ASSERT (num_vertices == - class_scheme->t8_element_num_faces (transition_cell - [subelement_id])); + T8_ASSERT (num_vertices == class_scheme->t8_element_num_corners (transition_cell[subelement_id])); + T8_ASSERT (num_vertices == class_scheme->t8_element_num_faces (transition_cell[subelement_id])); /* Iterate over all vertices of the subelement and determine their coordinates */ - int vertex_count; + int vertex_count; for (vertex_count = 0; vertex_count < num_vertices; ++vertex_count) { - class_scheme->t8_element_vertex_reference_coords (transition_cell - [subelement_id], - vertex_count, - coords); - t8_debugf - ("Subelement ID: %d; Vertex: %d; Ref cords in [0,1]^3: (%lf,%lf,%lf)\n", - subelement_id, vertex_count, coords[0], coords[1], coords[2]); + class_scheme->t8_element_vertex_reference_coords (transition_cell[subelement_id], vertex_count, coords); + t8_debugf ("Subelement ID: %d; Vertex: %d; Ref cords in [0,1]^3: (%lf,%lf,%lf)\n", subelement_id, vertex_count, + coords[0], coords[1], coords[2]); T8_ASSERT (t8_check_coordinates (coords)); - } /* end of vertex loop */ - } /* end of subelement loop */ + } /* end of vertex loop */ + } /* end of subelement loop */ /* coarsen the transition cell back to its parent, which must be equal to the initial quad_element */ class_scheme->t8_element_new (1, &parent); @@ -249,25 +227,21 @@ t8_transition_local (t8_eclass_t eclass) class_scheme->t8_element_destroy (num_subelements, transition_cell); T8_FREE (transition_cell); - } /* end of transition type loop */ + } /* end of transition type loop */ /* free more memory */ class_scheme->t8_element_destroy (1, &hex_element); t8_scheme_cxx_unref (&ts); - t8_debugf - ("~~~~~~~~~~ The t8_transition_local function finished successful ~~~~~~~~~~\n"); - -} /* end of t8_transition_local */ - - + t8_debugf ("~~~~~~~~~~ The t8_transition_local function finished successful ~~~~~~~~~~\n"); +} /* end of t8_transition_local */ int main (int argc, char **argv) { - int mpiret; -/* Initialize MPI. This has to happen before we initialize sc or t8code. */ + int mpiret; + /* Initialize MPI. This has to happen before we initialize sc or t8code. */ mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); @@ -286,5 +260,3 @@ main (int argc, char **argv) return 0; } - - diff --git a/example/transition/t8_transition_forest.cxx b/example/transition/t8_transition_forest.cxx index 9b804a71f4..a23ef6bd7f 100644 --- a/example/transition/t8_transition_forest.cxx +++ b/example/transition/t8_transition_forest.cxx @@ -20,14 +20,14 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include -#include +#include #include #include #include /* A collection of exemplary cmeshes */ #include -#include -#include /* geometrical information of the forest */ -#include +#include +#include /* geometrical information of the forest */ +#include #include #include #include @@ -42,7 +42,6 @@ * After these two forests are created, we check for equality. */ - /* Adapt a forest such that always the first child of a * tree is refined and no other elements. This results in a highly * imbalanced forest. */ @@ -68,14 +67,14 @@ t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t // if (lelement_id == 0 || lelement_id == 5){ // return 1; // } -// return 0; + // return 0; } /* adapt, balance and partition a given forest in one step */ static t8_forest_t t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) { - t8_debugf("---------start t8_test_forest_commit_abp ---------------------\n"); + t8_debugf ("---------start t8_test_forest_commit_abp ---------------------\n"); t8_forest_t forest_ada_bal_par; @@ -85,11 +84,11 @@ t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) t8_forest_set_user_data (forest_ada_bal_par, &maxlevel); t8_forest_set_adapt (forest_ada_bal_par, forest, t8_test_adapt_balance, 0); t8_forest_set_balance (forest_ada_bal_par, NULL, 0); - t8_forest_set_transition(forest_ada_bal_par, NULL, 0); + t8_forest_set_transition (forest_ada_bal_par, NULL, 0); t8_forest_set_partition (forest_ada_bal_par, NULL, 0); t8_forest_commit (forest_ada_bal_par); - t8_debugf("---------finsish t8_test_forest_commit_abp ---------------------\n"); + t8_debugf ("---------finsish t8_test_forest_commit_abp ---------------------\n"); return forest_ada_bal_par; } @@ -97,7 +96,7 @@ t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) static t8_forest_t t8_test_forest_commit_abp_3step (t8_forest_t forest, int maxlevel) { - t8_debugf("---------start t8_test_forest_commit_abtp_3step ---------------------\n"); + t8_debugf ("---------start t8_test_forest_commit_abtp_3step ---------------------\n"); t8_forest_t forest_adapt; t8_forest_t forest_balance; @@ -125,29 +124,29 @@ t8_test_forest_commit_abp_3step (t8_forest_t forest, int maxlevel) /* partrition the forest */ t8_forest_set_partition (forest_partition, forest_transition, 0); t8_forest_commit (forest_partition); -t8_debugf("---------finsish t8_test_forest_commit_abtp_3step ---------------------\n"); + t8_debugf ("---------finsish t8_test_forest_commit_abtp_3step ---------------------\n"); return forest_partition; } -void t8_transition_commit () +void +t8_transition_commit () { - t8_cmesh_t cmesh; + t8_cmesh_t cmesh; t8_forest_t forest; t8_forest_t forest_ada_bal_tra_part; t8_forest_t forest_abtp_3part; /* construct a single tree hex cmesh */ cmesh = t8_cmesh_new_hypercube (T8_ECLASS_HEX, sc_MPI_COMM_WORLD, 0, 0, 0); - t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); - int maxlevel = 2; + int maxlevel = 2; for (int level = 2; level <= maxlevel; level++) { - /* ref the cmesh since we reuse it */ + /* ref the cmesh since we reuse it */ t8_cmesh_ref (cmesh); t8_debugf ("Testing forest commit level %i\n", level); - + /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); @@ -166,22 +165,18 @@ void t8_transition_commit () t8_forest_unref (&forest_ada_bal_tra_part); t8_forest_unref (&forest_abtp_3part); - - } - t8_cmesh_unref(&cmesh); - t8_scheme_cxx_unref (&scheme); - + t8_cmesh_unref (&cmesh); + t8_scheme_cxx_unref (&scheme); t8_debugf ("Done testing forest commit."); } - int main (int argc, char **argv) { - int mpiret; -/* Initialize MPI. This has to happen before we initialize sc or t8code. */ + int mpiret; + /* Initialize MPI. This has to happen before we initialize sc or t8code. */ mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); diff --git a/example/transition/t8_transition_global_hex.cxx b/example/transition/t8_transition_global_hex.cxx index b416c8b72f..8ccab41a56 100644 --- a/example/transition/t8_transition_global_hex.cxx +++ b/example/transition/t8_transition_global_hex.cxx @@ -37,39 +37,33 @@ #include #include #include -#include // to write vtk +#include // to write vtk #include #include #include /* for cmesh initialization via for example t8_cmesh_new_hypercube */ -#include +#include #include - /* In this example, the left side of a unit cube with initial level 2 is refined to construct an adapted and transitioned forest. */ /* Refinement criterion: All elements with x-coordinate smaller than 0.5 are being refined. All other elements remain unchanged. */ int -t8_adapt_callback (t8_forest_t forest, - t8_forest_t forest_from, - t8_locidx_t which_tree, - t8_locidx_t lelement_id, - t8_eclass_scheme_c *ts, - const int is_family, - const int num_elements, t8_element_t *elements[]) +t8_adapt_callback (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, const int is_family, const int num_elements, t8_element_t *elements[]) { // double coords[3] = {0.0,0.0,0.0}; // ts->t8_element_vertex_reference_coords(elements[0], 0, coords); // if (coords[0]* P8EST_ROOT_LEN < 0.5 ){ // return 1; // } - int child_id = ts->t8_element_child_id (elements[0]); + int child_id = ts->t8_element_child_id (elements[0]); if (child_id == 1) { return 1; } return 0; -// else if (coords[0] > 0.5){ -// return -1; -// } + // else if (coords[0] > 0.5){ + // return -1; + // } // return 0; } @@ -83,60 +77,55 @@ t8_test_forest_commit_abpt (t8_forest_t forest) t8_forest_init (&forest_ada_bal_tra_par); t8_forest_set_adapt (forest_ada_bal_tra_par, forest, t8_adapt_callback, 0); t8_forest_set_balance (forest_ada_bal_tra_par, NULL, 0); - t8_forest_set_transition(forest_ada_bal_tra_par, NULL, 0); + t8_forest_set_transition (forest_ada_bal_tra_par, NULL, 0); t8_forest_set_partition (forest_ada_bal_tra_par, NULL, 0); t8_forest_commit (forest_ada_bal_tra_par); return forest_ada_bal_tra_par; } - - /* Initializing, adapting balancing and transitioning a forest */ static void t8_transition_global (void) { /* At the moment, subelements are only implemented for T8_ECLASS_HEX and quads */ - t8_eclass_t eclass = T8_ECLASS_HEX; /* depending on the include file, this will be the transitioned or default hex implementation */ - t8_forest_t forest; - t8_forest_t forest_adapt; - t8_cmesh_t cmesh; - char filename[BUFSIZ]; + t8_eclass_t eclass + = T8_ECLASS_HEX; /* depending on the include file, this will be the transitioned or default hex implementation */ + t8_forest_t forest; + t8_forest_t forest_adapt; + t8_cmesh_t cmesh; + char filename[BUFSIZ]; /* refinement setting */ - int level = 2; /* initial uniform refinement level */ + int level = 2; /* initial uniform refinement level */ t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); /* construct a single tree hex cmesh */ cmesh = t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 0, 0); - /* Create a uniformly refined forest */ + /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); - t8_forest_write_vtk (forest, "forest_global_hex" ); - + t8_forest_write_vtk (forest, "forest_global_hex"); for (int adaptation_count = 1; adaptation_count <= 2; ++adaptation_count) { - forest_adapt = t8_test_forest_commit_abpt(forest); + forest_adapt = t8_test_forest_commit_abpt (forest); - t8_debugf("---------------ROUND %i ---------------------------\n\n", adaptation_count); - - forest = forest_adapt; + t8_debugf ("---------------ROUND %i ---------------------------\n\n", adaptation_count); + forest = forest_adapt; } - t8_forest_write_vtk (forest, "transition_global_hex" ); - - t8_forest_unref (&forest_adapt); - -} /* end of t8_transition_global */ + t8_forest_write_vtk (forest, "transition_global_hex"); + t8_forest_unref (&forest_adapt); +} /* end of t8_transition_global */ int main (int argc, char **argv) { - int mpiret; + int mpiret; mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); diff --git a/example/transition/t8_transition_multiple_trees_hex.cxx b/example/transition/t8_transition_multiple_trees_hex.cxx index e4ab7d81c0..8da9e534c2 100644 --- a/example/transition/t8_transition_multiple_trees_hex.cxx +++ b/example/transition/t8_transition_multiple_trees_hex.cxx @@ -37,25 +37,19 @@ #include #include #include -#include // to write vtk +#include // to write vtk #include #include #include /* for cmesh initialization via for example t8_cmesh_new_hypercube */ -#include +#include #include - /* In this example, the left side of a unit cube with initial level 2 is refined to construct an adapted and transitioned forest. */ /* Refinement criterion: All elements with x-coordinate smaller than 0.5 are being refined. All other elements remain unchanged. */ int -t8_adapt_callback (t8_forest_t forest, - t8_forest_t forest_from, - t8_locidx_t which_tree, - t8_locidx_t lelement_id, - t8_eclass_scheme_c *ts, - const int is_family, - const int num_elements, t8_element_t *elements[]) +t8_adapt_callback (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, const int is_family, const int num_elements, t8_element_t *elements[]) { int child_id = ts->t8_element_child_id (elements[0]); if (child_id == 1) { @@ -74,78 +68,62 @@ t8_test_forest_commit_abpt (t8_forest_t forest) t8_forest_init (&forest_ada_bal_tra_par); t8_forest_set_adapt (forest_ada_bal_tra_par, forest, t8_adapt_callback, 0); t8_forest_set_balance (forest_ada_bal_tra_par, NULL, 0); - t8_forest_set_transition(forest_ada_bal_tra_par, NULL, 0); + t8_forest_set_transition (forest_ada_bal_tra_par, NULL, 0); t8_forest_set_partition (forest_ada_bal_tra_par, NULL, 0); t8_forest_commit (forest_ada_bal_tra_par); return forest_ada_bal_tra_par; } - - /* Initializing, adapting balancing and transitioning a forest */ static void t8_transition_global (void) { /* At the moment, subelements are only implemented for hexes and quads */ - t8_eclass_t eclass = T8_ECLASS_HEX; /* depending on the include file, this will be the transitioned or default hex implementation */ - t8_forest_t forest; - t8_forest_t forest_adapt; - t8_cmesh_t cmesh; - char filename[BUFSIZ]; + t8_eclass_t eclass + = T8_ECLASS_HEX; /* depending on the include file, this will be the transitioned or default hex implementation */ + t8_forest_t forest; + t8_forest_t forest_adapt; + t8_cmesh_t cmesh; + char filename[BUFSIZ]; /* refinement setting */ - int level = 2; /* initial uniform refinement level */ + int level = 2; /* initial uniform refinement level */ t8_locidx_t polygons_x = 2; t8_locidx_t polygons_y = 1; t8_locidx_t polygons_z = 1; - const double boundary[24] = {0,0,0, - 2,0,0, - 0,1,0, - 2,1,0, - 0,0,1, - 2,0,1, - 0,1,1, - 2,1,1}; + const double boundary[24] = { 0, 0, 0, 2, 0, 0, 0, 1, 0, 2, 1, 0, 0, 0, 1, 2, 0, 1, 0, 1, 1, 2, 1, 1 }; t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); /* construct a multiple tree hex cmesh */ - cmesh = - t8_cmesh_new_hypercube_pad (eclass, sc_MPI_COMM_WORLD, boundary, polygons_x, - polygons_y, polygons_z, 0); - - + cmesh = t8_cmesh_new_hypercube_pad (eclass, sc_MPI_COMM_WORLD, boundary, polygons_x, polygons_y, polygons_z, 0); /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); - t8_forest_write_vtk (forest, "forest_global_hex" ); - + t8_forest_write_vtk (forest, "forest_global_hex"); for (int adaptation_count = 1; adaptation_count <= 2; ++adaptation_count) { - forest_adapt = t8_test_forest_commit_abpt(forest); - - t8_debugf("---------------ROUND %i ---------------------------\n\n", adaptation_count); + forest_adapt = t8_test_forest_commit_abpt (forest); - forest = forest_adapt; + t8_debugf ("---------------ROUND %i ---------------------------\n\n", adaptation_count); + forest = forest_adapt; } - t8_forest_write_vtk (forest, "transition_global_hex" ); - - t8_forest_unref (&forest_adapt); - -} /* end of t8_transition_global */ + t8_forest_write_vtk (forest, "transition_global_hex"); + t8_forest_unref (&forest_adapt); +} /* end of t8_transition_global */ int main (int argc, char **argv) { - int mpiret; + int mpiret; mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); diff --git a/src/t8_element_cxx.hxx b/src/t8_element_cxx.hxx index 0cb5ca382a..a735613606 100644 --- a/src/t8_element_cxx.hxx +++ b/src/t8_element_cxx.hxx @@ -739,7 +739,7 @@ struct t8_eclass_scheme * \param [in, out] position the position of the first byte that is not already packed * \param [in] comm MPI Communicator */ -/*-----------------------------------Functions for transition schemes------------------------------------------------*/ + /*-----------------------------------Functions for transition schemes------------------------------------------------*/ /** Return zero refine value for schemes that do not have a transition implementation. * \param [in] elem A valid element * \return Integer, used as the refine value during transition adaptation. @@ -752,8 +752,8 @@ struct t8_eclass_scheme * \param [in] elem A valid element * \return true if elem is a subelement */ - virtual int - t8_element_is_subelement (const t8_element *elem) const + virtual int + t8_element_is_subelement (const t8_element *elem) const = 0; /** Return the number of subelements in a transition cell of type transition_type @@ -761,7 +761,7 @@ struct t8_eclass_scheme * \return the number of subelements, this transition cell consists of */ virtual int - t8_element_get_number_of_subelements (int transition_type) const + t8_element_get_number_of_subelements (int transition_type) const = 0; /** Return the subelement id of a given element. @@ -769,9 +769,10 @@ struct t8_eclass_scheme * \return the subelement id of elem (0 if elem is no subelement) */ virtual int - t8_element_get_subelement_id (const t8_element * elem) const = 0; + t8_element_get_subelement_id (const t8_element *elem) const + = 0; - /** This function refines a parent element into subelements. + /** This function refines a parent element into subelements. * Depending on the subelement type, the number of subelements * to fill the parent element, can differ. * \param [in] elem A valid element @@ -779,14 +780,15 @@ struct t8_eclass_scheme * \param [out] subelements An array of all subelements of the parent quad element elem */ virtual void - t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *subelements[]) + t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *subelements[]) = 0; /** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ virtual int - t8_element_scheme_supports_transitioning (void) = 0; + t8_element_scheme_supports_transitioning (void) + = 0; - /* --------------------------End functions of transition scheme---------------------*/ + /* --------------------------End functions of transition scheme---------------------*/ virtual void t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, void *send_buffer, int buffer_size, diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index 65e6ba6031..1c7a8a0f76 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -78,28 +78,25 @@ t8_forest_is_initialized (t8_forest_t forest) int t8_forest_supports_transitioning (t8_forest_t forest) { - int supports_transition = 1; - int supports_transition_all_procs = 0; /* Result over all procs */ - int int_eclass; - int mpiret; + int supports_transition = 1; + int supports_transition_all_procs = 0; /* Result over all procs */ + int int_eclass; + int mpiret; t8_eclass_scheme_c *tscheme; /* Iterate over all eclasses */ - for (int_eclass = (int) T8_ECLASS_ZERO; int_eclass < (int) T8_ECLASS_COUNT; - int_eclass++) { + for (int_eclass = (int) T8_ECLASS_ZERO; int_eclass < (int) T8_ECLASS_COUNT; int_eclass++) { /* If the forest has trees of the current eclass, check if elements of this * eclass supports transitioning. */ if (forest->cmesh->num_local_trees_per_eclass[int_eclass] > 0) { tscheme = forest->scheme_cxx->eclass_schemes[int_eclass]; - supports_transition = supports_transition - && t8_element_scheme_supports_transitioning (tscheme); + supports_transition = supports_transition && t8_element_scheme_supports_transitioning (tscheme); } } /* Combine the process-local results via a logic or and distribute the * result over all procs (in the communicator).*/ - mpiret = - sc_MPI_Allreduce (&supports_transition, &supports_transition_all_procs, 1, - sc_MPI_INT, sc_MPI_LAND, forest->mpicomm); + mpiret = sc_MPI_Allreduce (&supports_transition, &supports_transition_all_procs, 1, sc_MPI_INT, sc_MPI_LAND, + forest->mpicomm); SC_CHECK_MPI (mpiret); return supports_transition_all_procs; @@ -256,18 +253,16 @@ t8_forest_set_balance (t8_forest_t forest, const t8_forest_t set_from, int no_re } void -t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, - int set_transition_with_balance) +t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, int set_transition_with_balance) { T8_ASSERT (t8_forest_is_initialized (forest)); if (set_transition_with_balance) { - t8_debugf("-------------set transition with balance -------------\n"); + t8_debugf ("-------------set transition with balance -------------\n"); /* balance with repartition */ t8_forest_set_balance (forest, set_from, 0); } - if (set_from != NULL) { /* Note that it is possible to apply transitioning to a forest without transition implementation. * In this case, the transition refine routine will return 0, keeping the forest unchanged. @@ -546,8 +541,8 @@ t8_forest_commit (t8_forest_t forest) forest->incomplete_trees = 0; forest->is_transitioned = 0; } - else { - /* set_from != NULL */ + else { + /* set_from != NULL */ t8_forest_t forest_from = forest->set_from; /* temporarily store set_from, since we may overwrite it */ T8_ASSERT (forest->mpicomm == sc_MPI_COMM_NULL); @@ -600,18 +595,18 @@ t8_forest_commit (t8_forest_t forest) if (forest->from_method > 0) { /* The forest should also be partitioned/balanced/transitioned. * We first untransition the forest, then adapt the forest, then balance and then partition and then possibly transition the forest again*/ - if (forest->set_from->is_transitioned){ - T8_ASSERT(forest->is_transitioned == 0); - t8_forest_untransition(forest); + if (forest->set_from->is_transitioned) { + T8_ASSERT (forest->is_transitioned == 0); + t8_forest_untransition (forest); } - + t8_forest_t forest_adapt; - t8_forest_init (&forest_adapt); + t8_forest_init (&forest_adapt); /* forest_adapt should not change ownership of forest->set_from */ if (forest_from == forest->set_from) { - t8_forest_ref (forest->set_from); - } + t8_forest_ref (forest->set_from); + } /* set user data of forest to forest_adapt */ t8_forest_set_user_data (forest_adapt, t8_forest_get_user_data (forest)); /* Construct an intermediate, adapted forest */ @@ -631,8 +626,8 @@ t8_forest_commit (t8_forest_t forest) else { /* This forest should only be adapted */ t8_forest_copy_trees (forest, forest->set_from, 0); - - t8_forest_adapt (forest); + + t8_forest_adapt (forest); } } if (forest->from_method & T8_FOREST_FROM_PARTITION) { @@ -671,7 +666,6 @@ t8_forest_commit (t8_forest_t forest) forest->trees = sc_array_new (sizeof (t8_tree_struct_t)); /* partition the forest */ t8_forest_partition (forest); - } } if (forest->from_method & T8_FOREST_FROM_BALANCE) { @@ -691,9 +685,9 @@ t8_forest_commit (t8_forest_t forest) t8_forest_t forest_balance; t8_forest_init (&forest_balance); /* forest_balance should not change ownership of forest->set_from */ - if (forest_from == forest->set_from) { - t8_forest_ref (forest->set_from); - } + if (forest_from == forest->set_from) { + t8_forest_ref (forest->set_from); + } t8_forest_set_balance (forest_balance, forest->set_from, flag_rep); /* Set profiling if enabled */ t8_forest_set_profiling (forest_balance, forest->profile != NULL); @@ -701,19 +695,19 @@ t8_forest_commit (t8_forest_t forest) /* The new forest will be partitioned/transitioned from forest_balance */ forest->set_from = forest_balance; } - else{ - /* Only execute t8_balance.*/ - T8_ASSERT (forest->from_method == 0); - - /* This forest should only be balanced */ - if (forest->set_balance == T8_FOREST_BALANCE_NO_REPART) { - /* balance without repartition */ - t8_forest_balance (forest, 0); - } else { - /* balance with repartition */ - t8_forest_balance (forest, 1); - } + /* Only execute t8_balance.*/ + T8_ASSERT (forest->from_method == 0); + + /* This forest should only be balanced */ + if (forest->set_balance == T8_FOREST_BALANCE_NO_REPART) { + /* balance without repartition */ + t8_forest_balance (forest, 0); + } + else { + /* balance with repartition */ + t8_forest_balance (forest, 1); + } } } if (forest->from_method & T8_FOREST_FROM_TRANSITION) { @@ -746,7 +740,7 @@ t8_forest_commit (t8_forest_t forest) forest->set_for_coarsening = 0; forest->set_from = NULL; forest->committed = 1; - t8_debugf("Forest is transitioned %i \n", forest->is_transitioned); + t8_debugf ("Forest is transitioned %i \n", forest->is_transitioned); t8_debugf ("Committed forest with %li local elements and %lli " "global elements.\n\tTree range is from %lli to %lli.\n", (long) forest->local_num_elements, (long long) forest->global_num_elements, @@ -755,13 +749,11 @@ t8_forest_commit (t8_forest_t forest) if (forest->tree_offsets == NULL) { /* Compute the tree offset array */ t8_forest_partition_create_tree_offsets (forest); - } if (forest->element_offsets == NULL) { /* Compute element offsets */ t8_forest_partition_create_offsets (forest); - } if (forest->global_first_desc == NULL) { /* Compute global first desc array */ @@ -833,13 +825,12 @@ t8_forest_get_global_num_subelements (t8_forest_t forest) void t8_forest_comm_global_num_subelements (t8_forest_t forest) { - int mpiret; - t8_gloidx_t local_num_subel; - t8_gloidx_t global_num_subel; + int mpiret; + t8_gloidx_t local_num_subel; + t8_gloidx_t global_num_subel; local_num_subel = (t8_gloidx_t) forest->local_num_subelements; - mpiret = sc_MPI_Allreduce (&local_num_subel, &global_num_subel, 1, - T8_MPI_GLOIDX, sc_MPI_SUM, forest->mpicomm); + mpiret = sc_MPI_Allreduce (&local_num_subel, &global_num_subel, 1, T8_MPI_GLOIDX, sc_MPI_SUM, forest->mpicomm); SC_CHECK_MPI (mpiret); forest->global_num_subelements = global_num_subel; } @@ -1495,7 +1486,7 @@ t8_forest_profile_get_balance (t8_forest_t forest, int *balance_rounds) void t8_forest_compute_elements_offset (t8_forest_t forest) { - + t8_locidx_t itree, num_trees; t8_locidx_t current_offset; t8_tree_t tree; @@ -1504,8 +1495,7 @@ t8_forest_compute_elements_offset (t8_forest_t forest) /* Get the number of local trees */ num_trees = t8_forest_get_num_local_trees (forest); - - + current_offset = 0; /* Iterate through all trees, sum up the element counts and set it as * the element_offsets */ @@ -1513,7 +1503,6 @@ t8_forest_compute_elements_offset (t8_forest_t forest) tree = t8_forest_get_tree (forest, itree); tree->elements_offset = current_offset; current_offset += t8_forest_get_tree_element_count (tree); - } /* At the end, we counted all elements */ T8_ASSERT (current_offset == forest->local_num_elements); @@ -1574,7 +1563,7 @@ t8_forest_new_uniform (t8_cmesh_t cmesh, t8_scheme_cxx_t *scheme, const int leve /* Initialize the forest */ t8_forest_init (&forest); - T8_ASSERT(t8_forest_is_initialized(forest)); + T8_ASSERT (t8_forest_is_initialized (forest)); /* Set the cmesh, scheme and level */ t8_forest_set_cmesh (forest, cmesh, comm); t8_forest_set_scheme (forest, scheme); @@ -1718,6 +1707,6 @@ t8_forest_unref (t8_forest_t *pforest) T8_ASSERT (forest->rc.refcount > 0); T8_ASSERT (forest != NULL); if (t8_refcount_unref (&forest->rc)) { - t8_forest_reset (pforest); + t8_forest_reset (pforest); } } \ No newline at end of file diff --git a/src/t8_forest/t8_forest_adapt.cxx b/src/t8_forest/t8_forest_adapt.cxx index d7f4d652f8..3975615001 100644 --- a/src/t8_forest/t8_forest_adapt.cxx +++ b/src/t8_forest/t8_forest_adapt.cxx @@ -365,17 +365,12 @@ t8_forest_adapt_refine_recursive (t8_forest_t forest, t8_locidx_t ltreeid, t8_lo * independent of the specific refine function that has been applied before. This function * checks if these rules are fulfilled and may change the refine value. */ void -t8_forest_adjust_refine_for_transitioned_forests (const t8_forest_t forest, - t8_eclass_scheme_c *tscheme, - const t8_element_t - *current_element, - const t8_locidx_t ltree_id, +t8_forest_adjust_refine_for_transitioned_forests (const t8_forest_t forest, t8_eclass_scheme_c *tscheme, + const t8_element_t *current_element, const t8_locidx_t ltree_id, int *prefine) { /* refine values >1 are only allowed for eclass schemes that support transitioning */ - T8_ASSERT (! - (tscheme->t8_element_get_transition_refine_identifier () == 0 - && *prefine > 1)); + T8_ASSERT (!(tscheme->t8_element_get_transition_refine_identifier () == 0 && *prefine > 1)); /* Existing transition cells must be removed during adaptation. * We establish the rule to coarsen a transition cell back to its parent in case of refine = 0. */ @@ -418,8 +413,8 @@ t8_forest_adapt (t8_forest_t forest) int num_elements_to_adapt_callback; int zz; int ci; - unsigned int num_subelements; /* This is only needed when transitioning is enabled. */ - t8_locidx_t subel_inserted; /* This is only needed when transitioning is enabled. */ + unsigned int num_subelements; /* This is only needed when transitioning is enabled. */ + t8_locidx_t subel_inserted; /* This is only needed when transitioning is enabled. */ int refine; int is_family; int element_removed = 0; @@ -557,7 +552,8 @@ t8_forest_adapt (t8_forest_t forest) * >1 if the element should be refined into a transition cell */ refine = forest->set_adapt_fn (forest, forest->set_from, ltree_id, el_considered, tscheme, is_family, - num_elements_to_adapt_callback, elements_from); T8_ASSERT (is_family || refine != -1); + num_elements_to_adapt_callback, elements_from); + T8_ASSERT (is_family || refine != -1); if (refine == 1 && tscheme->t8_element_level (elements_from[0]) >= forest->maxlevel) { /* Only refine an element regularly if it does not exceed the maximum level */ refine = 0; @@ -595,29 +591,26 @@ t8_forest_adapt (t8_forest_t forest) el_considered++; } else if (refine > 1) { - /* refinement into transition cell */ - - /* determine the number of subelements of the given type for memory allocation */ - num_subelements = - tscheme->t8_element_get_number_of_subelements (refine - 1); - - /* We need to reallocate memory for the transition cell */ - elements = T8_REALLOC (elements, t8_element_t *, num_subelements); - - (void) t8_element_array_push_count (telements, num_subelements); - for (zz = 0; zz < num_subelements; zz++) { - elements[zz] = - t8_element_array_index_locidx (telements, el_inserted + zz); - } - tscheme->t8_element_to_transition_cell (elements_from[0], refine - 1, - elements); - el_inserted += num_subelements; - el_considered++; + /* refinement into transition cell */ + + /* determine the number of subelements of the given type for memory allocation */ + num_subelements = tscheme->t8_element_get_number_of_subelements (refine - 1); + + /* We need to reallocate memory for the transition cell */ + elements = T8_REALLOC (elements, t8_element_t *, num_subelements); + + (void) t8_element_array_push_count (telements, num_subelements); + for (zz = 0; zz < num_subelements; zz++) { + elements[zz] = t8_element_array_index_locidx (telements, el_inserted + zz); + } + tscheme->t8_element_to_transition_cell (elements_from[0], refine - 1, elements); + el_inserted += num_subelements; + el_considered++; - /* Each time we entry this case, a parent element is refined into subelements. + /* Each time we entry this case, a parent element is refined into subelements. * We will count the global number of constructed subelements and give this number as additional output. */ - subel_inserted += num_subelements; - } + subel_inserted += num_subelements; + } else if (refine == -1) { /* The elements form a family and are to be coarsened. */ /* Make room for one more new element. */ @@ -699,7 +692,7 @@ t8_forest_adapt (t8_forest_t forest) /* We now adapted all local trees */ /* Compute the new global number of elements */ - /* Compute the new global number of elements and subelements */ + /* Compute the new global number of elements and subelements */ t8_forest_comm_global_num_elements (forest); /* Updating other processes about local (in)complete trees. @@ -720,14 +713,12 @@ t8_forest_adapt (t8_forest_t forest) t8_forest_comm_global_num_subelements (forest); /* If any subelement is constructed, give output this number as an additional information. */ if (forest->global_num_subelements > 0) { - t8_global_productionf - ("Done t8_forest_adapt with %lld total elements, %li of which are subelements.\n", - (long long) forest->global_num_elements, forest->global_num_subelements); + t8_global_productionf ("Done t8_forest_adapt with %lld total elements, %li of which are subelements.\n", + (long long) forest->global_num_elements, forest->global_num_subelements); } else { - t8_global_productionf ("Done t8_forest_adapt with %lld total elements\n", (long long) forest->global_num_elements); + t8_global_productionf ("Done t8_forest_adapt with %lld total elements\n", (long long) forest->global_num_elements); } - /* if profiling is enabled, measure runtime */ if (forest->profile != NULL) { diff --git a/src/t8_forest/t8_forest_balance.cxx b/src/t8_forest/t8_forest_balance.cxx index 0fa2ca2bf0..904e9c8070 100644 --- a/src/t8_forest/t8_forest_balance.cxx +++ b/src/t8_forest/t8_forest_balance.cxx @@ -193,7 +193,7 @@ t8_forest_balance (t8_forest_t forest, int repartition) t8_forest_set_profiling (forest_temp, 1); } t8_global_productionf ("Profiling: %i\n", forest->profile != NULL); - + /* Adapt the forest */ t8_forest_commit (forest_temp); /* Store the runtimes of adapt and ghost */ diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index 4da398b6a5..9037a2176c 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -184,7 +184,6 @@ t8_forest_compute_maxlevel (t8_forest_t forest) /* If there are trees of this class, compute the maxlevel of the class */ ts = t8_forest_get_eclass_scheme_before_commit (forest, (t8_eclass_t) eclass_it); maxlevel = ts->t8_element_maxlevel (); - /* Compute the minimum of this level and the stored maxlevel */ if (forest->maxlevel == -1) { @@ -1162,7 +1161,7 @@ t8_forest_populate (t8_forest_t forest) t8_eclass_scheme_c *eclass_scheme; t8_gloidx_t cmesh_first_tree, cmesh_last_tree; int is_empty; - + SC_CHECK_ABORT (forest->set_level <= forest->maxlevel, "Given refinement level exceeds the maximum.\n"); /* TODO: create trees and quadrants according to uniform refinement */ t8_cmesh_uniform_bounds (forest->cmesh, forest->set_level, forest->scheme_cxx, &forest->first_local_tree, diff --git a/src/t8_forest/t8_forest_general.h b/src/t8_forest/t8_forest_general.h index a30b090738..44ac12b453 100644 --- a/src/t8_forest/t8_forest_general.h +++ b/src/t8_forest/t8_forest_general.h @@ -383,7 +383,7 @@ t8_forest_comm_global_num_elements (t8_forest_t forest); * of the local subelement counts. * \param [in] forest The forest. */ -void +void t8_forest_comm_global_num_subelements (t8_forest_t forest); /** Return the number of global subelements in the forest. @@ -391,8 +391,8 @@ t8_forest_comm_global_num_subelements (t8_forest_t forest); * \return The number of subelements (summed over all processes) in \a forest. * \a forest must be committed before calling this function. */ -t8_gloidx_t t8_forest_get_global_num_subelements (t8_forest_t forest); - +t8_gloidx_t +t8_forest_get_global_num_subelements (t8_forest_t forest); /** Set a source forest to use subelements during commit, that will remove hanging faces from the adapted mesh. * \param [in, out] forest The forest. @@ -401,12 +401,8 @@ t8_gloidx_t t8_forest_get_global_num_subelements (t8_forest_t forest); * has been used before, then balance will still be set (0 does not unset balance). * \note This feature is currently only available for the 2D quad scheme. */ -void -t8_forest_set_transition (t8_forest_t forest, - const t8_forest_t set_from, - int - set_transition_with_balance); - +void +t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, int set_transition_with_balance); /** After allocating and adding properties to a forest, commit the changes. * This call sets up the internal state of the forest. diff --git a/src/t8_forest/t8_forest_partition.cxx b/src/t8_forest/t8_forest_partition.cxx index 52e79d90a4..b8ff2cb8a3 100644 --- a/src/t8_forest/t8_forest_partition.cxx +++ b/src/t8_forest/t8_forest_partition.cxx @@ -130,7 +130,7 @@ t8_forest_partition_test_desc (t8_forest_t forest) /* This forest is empty, nothing to do */ return; } - + tree = t8_forest_get_tree (forest, 0); ts = t8_forest_get_eclass_scheme (forest, tree->eclass); /* Get the first descendant id of this rank */ diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx index 11592fd445..02801c9dd1 100644 --- a/src/t8_forest/t8_forest_transition.cxx +++ b/src/t8_forest/t8_forest_transition.cxx @@ -24,7 +24,6 @@ * In this file, we define the call-back function that is used to construct transition cells. */ - #include "t8_eclass.h" #include #include @@ -44,24 +43,18 @@ T8_EXTERN_C_BEGIN (); * It will return a values p>1 in order to exchange the current element with a transition cell of type p, * which is defined in the conformal_quad scheme. */ int -t8_forest_transition_conformal_quad (t8_forest_t forest, - t8_forest_t forest_from, - t8_locidx_t ltree_id, - t8_locidx_t lelement_id, - t8_eclass_scheme_c *ts, - const int is_family, - int num_elements, - t8_element_t *elements[]) +t8_forest_transition_conformal_quad (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t ltree_id, + t8_locidx_t lelement_id, t8_eclass_scheme_c *ts, const int is_family, + int num_elements, t8_element_t *elements[]) { - int iface, num_faces, neigh_face, transition_type = 0; - t8_gloidx_t neighbor_tree; - t8_eclass_t neigh_class; + int iface, num_faces, neigh_face, transition_type = 0; + t8_gloidx_t neighbor_tree; + t8_eclass_t neigh_class; t8_eclass_scheme_c *neigh_scheme; - t8_element_t *element = elements[0], **face_neighbor; + t8_element_t *element = elements[0], **face_neighbor; /* hanging faces can only exist at non-maxlevel elements */ - if (forest_from->maxlevel_existing <= 0 || - ts->t8_element_level (element) < forest_from->maxlevel) { + if (forest_from->maxlevel_existing <= 0 || ts->t8_element_level (element) < forest_from->maxlevel) { num_faces = ts->t8_element_num_faces (element); @@ -86,9 +79,7 @@ t8_forest_transition_conformal_quad (t8_forest_t forest, for (iface = 0; iface < num_faces; iface++) { /* Get the element class and scheme of the face neighbor */ - neigh_class = t8_forest_element_neighbor_eclass (forest_from, - ltree_id, element, - iface); + neigh_class = t8_forest_element_neighbor_eclass (forest_from, ltree_id, element, iface); neigh_scheme = t8_forest_get_eclass_scheme (forest_from, neigh_class); @@ -98,16 +89,11 @@ t8_forest_transition_conformal_quad (t8_forest_t forest, neigh_scheme->t8_element_new (1, face_neighbor); /* Compute the virtual face neighbor of element at this face */ - neighbor_tree = t8_forest_element_face_neighbor (forest_from, ltree_id, - element, - face_neighbor[0], - neigh_scheme, + neighbor_tree = t8_forest_element_face_neighbor (forest_from, ltree_id, element, face_neighbor[0], neigh_scheme, iface, &neigh_face); if (neighbor_tree >= 0) { - if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, - face_neighbor[0], - neigh_scheme)) { + if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, face_neighbor[0], neigh_scheme)) { /* Compute transition type as the decimal representation of the binary concatenation */ transition_type += 1 << ((num_faces - 1) - iface); } @@ -121,35 +107,29 @@ t8_forest_transition_conformal_quad (t8_forest_t forest, if (transition_type == 0) { /* no hanging faces in this case */ return 0; } - else if (transition_type == 15) { /* four hanging faces in this case */ + else if (transition_type == 15) { /* four hanging faces in this case */ return 1; } - else { /* use a transition cell of subelements and add 1 to every type, to avoid refine = 1 */ + else { /* use a transition cell of subelements and add 1 to every type, to avoid refine = 1 */ return transition_type + 1; } } - return 0; /* if elem has maxlevel then keep it unchanged since there will never be hanging faces */ -} /* end of t8_forest_transition_conformal_quad */ + return 0; /* if elem has maxlevel then keep it unchanged since there will never be hanging faces */ +} /* end of t8_forest_transition_conformal_quad */ int -t8_forest_transition_conformal_hex (t8_forest_t forest, - t8_forest_t forest_from, - t8_locidx_t ltree_id, - t8_locidx_t lelement_id, - t8_eclass_scheme_c *ts, - const int is_family, - int num_elements, - t8_element_t *elements[]) +t8_forest_transition_conformal_hex (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t ltree_id, + t8_locidx_t lelement_id, t8_eclass_scheme_c *ts, const int is_family, + int num_elements, t8_element_t *elements[]) { - int iface, num_faces, neigh_face, transition_type = 0; - t8_gloidx_t neighbor_tree; - t8_eclass_t neigh_class; + int iface, num_faces, neigh_face, transition_type = 0; + t8_gloidx_t neighbor_tree; + t8_eclass_t neigh_class; t8_eclass_scheme_c *neigh_scheme; - t8_element_t *element = elements[0], **face_neighbor; + t8_element_t *element = elements[0], **face_neighbor; /* Hanging faces can only exist at non-maxlevel elements */ - if (forest_from->maxlevel_existing <= 0 || - ts->t8_element_level (element) < forest_from->maxlevel) { + if (forest_from->maxlevel_existing <= 0 || ts->t8_element_level (element) < forest_from->maxlevel) { num_faces = ts->t8_element_num_faces (element); @@ -175,9 +155,7 @@ t8_forest_transition_conformal_hex (t8_forest_t forest, for (iface = 0; iface < num_faces; iface++) { /* Get the element class and scheme of the face neighbor */ - neigh_class = t8_forest_element_neighbor_eclass (forest_from, - ltree_id, element, - iface); + neigh_class = t8_forest_element_neighbor_eclass (forest_from, ltree_id, element, iface); neigh_scheme = t8_forest_get_eclass_scheme (forest_from, neigh_class); @@ -188,16 +166,11 @@ t8_forest_transition_conformal_hex (t8_forest_t forest, neigh_scheme->t8_element_new (1, face_neighbor); /* Compute the virtual face neighbor of element at this face */ - neighbor_tree = t8_forest_element_face_neighbor (forest_from, ltree_id, - element, - face_neighbor[0], - neigh_scheme, + neighbor_tree = t8_forest_element_face_neighbor (forest_from, ltree_id, element, face_neighbor[0], neigh_scheme, iface, &neigh_face); if (neighbor_tree >= 0) { - if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, - face_neighbor[0], - neigh_scheme)) { + if (t8_forest_element_has_leaf_desc (forest_from, neighbor_tree, face_neighbor[0], neigh_scheme)) { /* Compute transition type as the decimal representation of the binary concatenation */ transition_type += 1 << ((num_faces - 1) - iface); } @@ -211,31 +184,25 @@ t8_forest_transition_conformal_hex (t8_forest_t forest, if (transition_type == 0) { /* no hanging faces in this case */ return 0; } - else if (transition_type == 63) { /* Six hanging faces in this case */ + else if (transition_type == 63) { /* Six hanging faces in this case */ return 1; } - else { /* use a transition cell of subelements and add 1 to every type, to avoid refine = 1 */ + else { /* use a transition cell of subelements and add 1 to every type, to avoid refine = 1 */ return transition_type + 1; } } - return 0; /* if elem has maxlevel then keep it unchanged since there will never be hanging faces */ + return 0; /* if elem has maxlevel then keep it unchanged since there will never be hanging faces */ } /* This is the entry function for all transition schemes, called bei forest_adapt. * The eclass of the current element hands off to the specific refine implementation above. * Other schemes, for other eclasses can easily be added. */ int -t8_forest_transition_entry (t8_forest_t forest, - t8_forest_t forest_from, - t8_locidx_t ltree_id, - t8_locidx_t lelement_id, - t8_eclass_scheme_c *ts, - const int is_family, - int num_elements, t8_element_t *elements[]) +t8_forest_transition_entry (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t ltree_id, t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, const int is_family, int num_elements, t8_element_t *elements[]) { T8_ASSERT (forest->set_subelements == 1); - T8_ASSERT (forest->is_transitioned == 0 - && forest->set_from->is_transitioned == 0); + T8_ASSERT (forest->is_transitioned == 0 && forest->set_from->is_transitioned == 0); /* TODO: there may be a better way for this than using switch statements and int functions */ @@ -249,25 +216,21 @@ t8_forest_transition_entry (t8_forest_t forest, * The default_common implementation of the above function returns 0. */ return 0; case T8_TRANSITION_CONFORMAL_QUAD_REFINE_FUNCTION: - return t8_forest_transition_conformal_quad (forest, forest_from, ltree_id, - lelement_id, ts, is_family, - num_elements, elements); - case T8_TRANSITION_CONFORMAL_HEX_REFINE_FUNCTION: - return t8_forest_transition_conformal_hex (forest, forest_from, ltree_id, - lelement_id, ts, is_family, - num_elements, elements); + return t8_forest_transition_conformal_quad (forest, forest_from, ltree_id, lelement_id, ts, is_family, num_elements, + elements); + case T8_TRANSITION_CONFORMAL_HEX_REFINE_FUNCTION: + return t8_forest_transition_conformal_hex (forest, forest_from, ltree_id, lelement_id, ts, is_family, num_elements, + elements); default: - SC_ABORT - ("The given eclass scheme must specify a valid transition refine function."); + SC_ABORT ("The given eclass scheme must specify a valid transition refine function."); } -} /* end of t8_forest_transition_entry */ +} /* end of t8_forest_transition_entry */ void t8_forest_transition (t8_forest_t forest) { T8_ASSERT (forest->set_subelements == 1); - T8_ASSERT (forest->is_transitioned == 0 - && forest->set_from->is_transitioned == 0); + T8_ASSERT (forest->is_transitioned == 0 && forest->set_from->is_transitioned == 0); /* in the following, we will call forest_adapt to with the transition * refinement function in order to transition the forest. The refinement is then * based on forest->set_from, which must be balanced. */ @@ -286,66 +249,56 @@ t8_forest_transition (t8_forest_t forest) t8_forest_adapt (forest); t8_global_productionf ("Done t8_forest_transition.\n"); -} /* end of t8_forest_transition */ - +} /* end of t8_forest_transition */ /* This is the entry function for all untransition a forest, called bei forest_adapt * in t8_forest_untransition. */ int -t8_forest_untransition_entry (t8_forest_t forest, - t8_forest_t forest_from, - t8_locidx_t ltree_id, - t8_locidx_t lelement_id, - t8_eclass_scheme_c *ts, - const int is_family, - int num_elements, t8_element_t *elements[]) +t8_forest_untransition_entry (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t ltree_id, + t8_locidx_t lelement_id, t8_eclass_scheme_c *ts, const int is_family, int num_elements, + t8_element_t *elements[]) { - T8_ASSERT(forest->set_from->is_transitioned == 1); + T8_ASSERT (forest->set_from->is_transitioned == 1); - //Iterate through elements array and if an element is a subelement, return -1 for - //coarsening this element in forest_adapt. All other elements remain unchanged. + //Iterate through elements array and if an element is a subelement, return -1 for + //coarsening this element in forest_adapt. All other elements remain unchanged. t8_element_t *element = elements[0]; - if(ts->t8_element_is_subelement(element)){ + if (ts->t8_element_is_subelement (element)) { return -1; } - else{ + else { return 0; } - -} - +} void t8_forest_untransition (t8_forest_t forest) { t8_global_productionf ("Into t8_forest_untransition.\n"); - T8_ASSERT(forest->set_from->is_transitioned); - - t8_forest_t forest_untransition; - - t8_forest_init (&forest_untransition); - /* forest_untransition should not change ownership of forest->set_from */ - t8_forest_ref (forest->set_from); - /* Construct an intermediate, untransitioned forest */ - t8_forest_set_adapt (forest_untransition, forest->set_from, t8_forest_untransition_entry, 0); + T8_ASSERT (forest->set_from->is_transitioned); - t8_forest_commit (forest_untransition); - forest_untransition->is_transitioned = 0; - /* The new forest will be partitioned/balanced from forest_adapt */ - forest->set_from = forest_untransition; + t8_forest_t forest_untransition; + t8_forest_init (&forest_untransition); + /* forest_untransition should not change ownership of forest->set_from */ + t8_forest_ref (forest->set_from); + /* Construct an intermediate, untransitioned forest */ + t8_forest_set_adapt (forest_untransition, forest->set_from, t8_forest_untransition_entry, 0); - t8_global_productionf ("Done t8_forest_untransition.\n"); + t8_forest_commit (forest_untransition); + forest_untransition->is_transitioned = 0; + /* The new forest will be partitioned/balanced from forest_adapt */ + forest->set_from = forest_untransition; + t8_global_productionf ("Done t8_forest_untransition.\n"); /* In the following, we will call forest_adapt to coarsen all transition cells * back to their regular parent element. So, forest->set_from is a transitioned forest and * forest will be non-transitioned. */ - -} +} /* Test whether the forest is transitioned. * Note 1) We allow non-committed forests in this implementation since this check is used in forest_commit() @@ -355,10 +308,10 @@ int t8_forest_is_transitioned (t8_forest_t forest) { t8_eclass_scheme_c *tscheme; - t8_locidx_t tree_count, num_trees; - t8_tree_t current_tree; + t8_locidx_t tree_count, num_trees; + t8_tree_t current_tree; t8_element_array_t *telements; - t8_locidx_t elem_count, num_elems; + t8_locidx_t elem_count, num_elems; /* iterate through the forest and check for subelements */ num_trees = t8_forest_get_num_local_trees (forest); @@ -367,8 +320,7 @@ t8_forest_is_transitioned (t8_forest_t forest) telements = ¤t_tree->elements; num_elems = (t8_locidx_t) t8_element_array_get_count (telements); for (elem_count = 0; elem_count < num_elems; elem_count++) { - t8_element_t *current_element = - t8_element_array_index_locidx (telements, elem_count); + t8_element_t *current_element = t8_element_array_index_locidx (telements, elem_count); tscheme = forest->scheme_cxx->eclass_schemes[current_tree->eclass]; if (tscheme->t8_element_is_subelement (current_element)) { /* subelement found -> return true */ @@ -379,6 +331,6 @@ t8_forest_is_transitioned (t8_forest_t forest) /* only return false if there is no subelement in the forest */ return 0; -} /* end of t8_forest_is_transitioned */ +} /* end of t8_forest_is_transitioned */ T8_EXTERN_C_END (); diff --git a/src/t8_forest/t8_forest_transition.h b/src/t8_forest/t8_forest_transition.h index d1cd5290ce..e2ca490e89 100644 --- a/src/t8_forest/t8_forest_transition.h +++ b/src/t8_forest/t8_forest_transition.h @@ -36,8 +36,7 @@ T8_EXTERN_C_BEGIN (); - - /** In this function, use a binary encoding (depending on the face enumeration), to determine which subelement type to use. +/** In this function, use a binary encoding (depending on the face enumeration), to determine which subelement type to use. * Every face has a flag parameter, which is set to 1, if there is a neighbour with a higher level * and to 0, if the level of the neighbour is at most the level of the element. * @@ -68,18 +67,11 @@ T8_EXTERN_C_BEGIN (); * \return transition type + 1 (to avoid return value 1) */ - int -t8_forest_transition_adapt (t8_forest_t forest, - t8_forest_t forest_from, - t8_locidx_t ltree_id, - t8_locidx_t lelement_id, - t8_eclass_scheme_c *ts, - int num_elements, - t8_element_t *elements[]); - +t8_forest_transition_adapt (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t ltree_id, t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, int num_elements, t8_element_t *elements[]); - /** This function is the point of entry for the hanging-faces-removing subelements. +/** This function is the point of entry for the hanging-faces-removing subelements. * In this function, the corresponding callback function for the refine value in forest_adapt is set * and the forest is adapted. * \param [in,out] forest The input forest consists of hanging nodes on faces- @@ -88,7 +80,6 @@ t8_forest_transition_adapt (t8_forest_t forest, void t8_forest_transition (t8_forest_t forest); - /** This function is the point of entry in order to untransition a forest before adapting it. * Every transition cell gets coarsened back to its parent element. * \param [in,out] forest The input forest consists of subelements- @@ -98,13 +89,13 @@ t8_forest_transition (t8_forest_t forest); void t8_forest_untransition (t8_forest_t forest); - /** Check whether the forest is transitioned, meaning that subelements exist. +/** Check whether the forest is transitioned, meaning that subelements exist. * \param [in] forest The input forest that may or may not contains subelements * \return true if forest contains subelements or false if not. * */ -int +int t8_forest_is_transitioned (t8_forest_t forest); T8_EXTERN_C_END (); diff --git a/src/t8_forest/t8_forest_types.h b/src/t8_forest/t8_forest_types.h index e11b727d76..6a9d5be253 100644 --- a/src/t8_forest/t8_forest_types.h +++ b/src/t8_forest/t8_forest_types.h @@ -87,7 +87,7 @@ typedef struct t8_forest Once an element got removed, the flag sets to 1 (true) and stays. For a committed forest this flag is either true on all ranks or false on all ranks. */ - int is_transitioned; /* Flag parameter that states whether the forest is transitioned or not */ + int is_transitioned; /* Flag parameter that states whether the forest is transitioned or not */ t8_forest_t set_from; /**< Temporarily store source forest. */ t8_forest_from_t from_method; /**< Method to derive from \b set_from. */ t8_forest_adapt_t set_adapt_fn; /**< refinement and coarsen function. Called when \b from_method @@ -98,7 +98,7 @@ typedef struct t8_forest See \ref t8_forest_set_balance. If 0, no balance. If 1 balance with repartitioning, if 2 balance without repartitioning, \see t8_forest_balance */ - int set_subelements; /**< Flag to decide whether subelements should be used in the forest */ + int set_subelements; /**< Flag to decide whether subelements should be used in the forest */ int do_ghost; /**< If True, a ghost layer will be created when the forest is committed. */ t8_ghost_type_t ghost_type; /**< If a ghost layer will be created, the type of neighbors that count as ghost. */ int ghost_algorithm; /**< Controls the algorithm used for ghost. 1 = balanced only. 2 = also unbalanced diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx index c97f75bb5c..b4fbaf4aca 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx @@ -178,25 +178,23 @@ t8_default_scheme_common_c::t8_element_get_transition_refine_identifier () const } int -t8_default_scheme_common_c::t8_element_is_subelement (const t8_element * elem) const +t8_default_scheme_common_c::t8_element_is_subelement (const t8_element *elem) const { /* We implement this function since it is a "check" function and * should not abort the code even if no subelements are implemented in the given eclass. * Schemes that support subelements must provide their own implementation of this function. */ /* No subelements are implemented and therefore we return false meaning "is no subelement". */ - t8_debugf - ("This is the default_common implementation of the t8_element_is_subelement check.\n"); + t8_debugf ("This is the default_common implementation of the t8_element_is_subelement check.\n"); return 0; } int -t8_default_scheme_common_c::t8_element_get_subelement_id (const t8_element * elem) const +t8_default_scheme_common_c::t8_element_get_subelement_id (const t8_element *elem) const { SC_ABORT ("This function is not implemented for the given scheme.\n"); } - int t8_default_scheme_common_c::t8_element_get_number_of_subelements (int transition_type) const { @@ -204,14 +202,11 @@ t8_default_scheme_common_c::t8_element_get_number_of_subelements (int transition } void -t8_default_scheme_common_c::t8_element_to_transition_cell (const t8_element_t - *elem, int type, - t8_element_t *c[]) +t8_default_scheme_common_c::t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *c[]) { SC_ABORT ("This function is not implemented for the given scheme.\n"); } - int t8_default_scheme_common_c::t8_element_scheme_supports_transitioning (void) { @@ -219,5 +214,4 @@ t8_default_scheme_common_c::t8_element_scheme_supports_transitioning (void) return 0; } - T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx index d09aafbef9..52ef47f595 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx @@ -127,7 +127,7 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { virtual void t8_element_anchor (const t8_element_t *elem, int anchor[3]) const = 0; -/*-----------------------------Functions for transition schemes---------------------------------*/ + /*-----------------------------Functions for transition schemes---------------------------------*/ /** Return zero refine value for schemes that do not have a transition implementation. * \param [in] elem A valid element @@ -139,7 +139,7 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { /** Check whether a given element is a subelement * \param [in] elem A valid element * \return true if elem is a subelement - */ + */ virtual int t8_element_is_subelement (const t8_element *elem) const; @@ -150,13 +150,12 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { virtual int t8_element_get_number_of_subelements (int transition_type) const; - /** Return the subelement id of a given element. * \param [in] elem A valid element * \return the subelement id of elem (0 if elem is no subelement) */ virtual int - t8_element_get_subelement_id (const t8_element * elem) const; + t8_element_get_subelement_id (const t8_element *elem) const; /** This function refines a parent element into subelements. * Depending on the subelement type, the number of subelements @@ -169,10 +168,9 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *c[]); /** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ - virtual int + virtual int t8_element_scheme_supports_transitioning (void); - #if T8_ENABLE_DEBUG virtual void t8_element_debug_print (const t8_element_t *elem) const; diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx index 456cf04142..c44ef70da5 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx @@ -34,10 +34,10 @@ /* We want to export the whole implementation to be callable from "C" */ T8_EXTERN_C_BEGIN (); -t8_scheme_cxx_t * +t8_scheme_cxx_t * t8_scheme_new_transition_hex_cxx (void) { - t8_scheme_cxx_t *s; + t8_scheme_cxx_t *s; s = T8_ALLOC_ZERO (t8_scheme_cxx_t, 1); t8_refcount_init (&s->rc); @@ -46,10 +46,11 @@ t8_scheme_new_transition_hex_cxx (void) s->eclass_schemes[T8_ECLASS_LINE] = new t8_default_scheme_line_c (); s->eclass_schemes[T8_ECLASS_QUAD] = new t8_default_scheme_quad_c (); s->eclass_schemes[T8_ECLASS_HEX] = new t8_subelement_scheme_hex_c (); - s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); + s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); s->eclass_schemes[T8_ECLASS_TET] = NULL; s->eclass_schemes[T8_ECLASS_PRISM] = NULL; - s->eclass_schemes[T8_ECLASS_PYRAMID] = new t8_default_scheme_pyramid_c (); /* can be used for hybrid meshes - not conformal as long as no conformal transition pyr class exists */ + s->eclass_schemes[T8_ECLASS_PYRAMID] + = new t8_default_scheme_pyramid_c (); /* can be used for hybrid meshes - not conformal as long as no conformal transition pyr class exists */ return s; } diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index a8db87d25a..4b6254db11 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -58,14 +58,8 @@ * f_4 <-> f_4 (assuming a neighboring transition cell) f_4 <-> f_4 */ -const int subelement_face_dual[6][5] = { - {0, 0, 0, 0, 4}, - {1, 1, 1, 1, 4}, - {0, 2, 0, 2, 4}, - {1, 3, 3, 3, 4}, - {2, 2, 2, 2, 4}, - {3, 3, 3, 3, 4} - }; +const int subelement_face_dual[6][5] = { { 0, 0, 0, 0, 4 }, { 1, 1, 1, 1, 4 }, { 0, 2, 0, 2, 4 }, + { 1, 3, 3, 3, 4 }, { 2, 2, 2, 2, 4 }, { 3, 3, 3, 3, 4 } }; /* Connectivity of a subelements location within a transition cell * and the parent hexs faces: @@ -75,18 +69,14 @@ const int subelement_face_dual[6][5] = { * location[0] = 3 -> parents dual face = 2 * location[0] = 4 -> parents dual face = 5 * location[0] = 5 -> parents dual face = 4 */ -const int subelement_location_to_parent_dual_face[6] = { 1, 0, 3, 2, 5, 4 }; +const int subelement_location_to_parent_dual_face[6] = { 1, 0, 3, 2, 5, 4 }; /* Connectivity of a subelements location within a transition cell (only if the subelements are not split) * --> gets subelement_duals */ -const int subelement_face_to_dual_subelement[6][5] = { - { 2, 3, 4, 5, -1 }, - { 2, 3, 4, 5, -1 }, - { 0, 1, 4, 5, -1 }, - { 0, 1, 4, 5, -1 }, - { 0, 1, 2, 3, -1 }, - { 0, 1, 2, 3, -1 }, +const int subelement_face_to_dual_subelement[6][5] = { + { 2, 3, 4, 5, -1 }, { 2, 3, 4, 5, -1 }, { 0, 1, 4, 5, -1 }, + { 0, 1, 4, 5, -1 }, { 0, 1, 2, 3, -1 }, { 0, 1, 2, 3, -1 }, }; /* Connectivity of a subelements location within a transition cell * and the parent hexs faces: Wie in mit Koordinatensystem in Davids Masterarbeit @@ -98,7 +88,7 @@ const int subelement_face_to_dual_subelement[6][5] = { * location[0] = 4 (bottom) -> parents face = 4 * location[0] = 5 (up) -> parents face = 5 */ -const int subelement_location_to_parent_face[6] = { 0, 1, 2, 3, 4, 5}; +const int subelement_location_to_parent_face[6] = { 0, 1, 2, 3, 4, 5 }; /* *INDENT-ON* */ /* We want to export the whole implementation to be callable from "C" */ @@ -106,8 +96,8 @@ T8_EXTERN_C_BEGIN (); /* This function is used by other element functions and we thus need to * declare it up here */ -t8_linearidx_t t8_element_get_linear_id (const t8_element_t *elem, - int level); +t8_linearidx_t +t8_element_get_linear_id (const t8_element_t *elem, int level); int t8_subelement_scheme_hex_c::t8_element_maxlevel (void) const @@ -127,48 +117,37 @@ t8_subelement_scheme_hex_c::t8_element_child_eclass (int childid) const int t8_subelement_scheme_hex_c::t8_element_level (const t8_element_t *elem) const { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; T8_ASSERT (t8_element_is_valid (elem)); return (int) ((const t8_hex_with_subelements *) phex_w_sub)->p8q.level; } void -t8_subelement_scheme_hex_c::t8_element_copy (const t8_element_t *source, - t8_element_t *dest) const +t8_subelement_scheme_hex_c::t8_element_copy (const t8_element_t *source, t8_element_t *dest) const { - const t8_hex_with_subelements *phex_w_sub_source = - (const t8_hex_with_subelements *) source; - t8_hex_with_subelements *phex_w_sub_dest = - (t8_hex_with_subelements *) dest; + const t8_hex_with_subelements *phex_w_sub_source = (const t8_hex_with_subelements *) source; + t8_hex_with_subelements *phex_w_sub_dest = (t8_hex_with_subelements *) dest; const p8est_quadrant_t *q = &phex_w_sub_source->p8q; - p8est_quadrant_t *r = &phex_w_sub_dest->p8q; + p8est_quadrant_t *r = &phex_w_sub_dest->p8q; T8_ASSERT (t8_element_is_valid (source)); T8_ASSERT (t8_element_is_valid (dest)); - if (q == r && - phex_w_sub_source->transition_type == - phex_w_sub_dest->transition_type && - phex_w_sub_source->subelement_id == phex_w_sub_dest->subelement_id) { + if (q == r && phex_w_sub_source->transition_type == phex_w_sub_dest->transition_type + && phex_w_sub_source->subelement_id == phex_w_sub_dest->subelement_id) { /* Do nothing if they are already the same hexahedra. */ return; } *r = *q; t8_element_copy_subelement_values (source, dest); - } int -t8_subelement_scheme_hex_c::t8_element_compare (const t8_element_t *elem1, - const t8_element_t *elem2) - const +t8_subelement_scheme_hex_c::t8_element_compare (const t8_element_t *elem1, const t8_element_t *elem2) const { - const t8_hex_with_subelements *phex_w_sub_elem1 = - (const t8_hex_with_subelements *) elem1; - const t8_hex_with_subelements *phex_w_sub_elem2 = - (const t8_hex_with_subelements *) elem2; + const t8_hex_with_subelements *phex_w_sub_elem1 = (const t8_hex_with_subelements *) elem1; + const t8_hex_with_subelements *phex_w_sub_elem2 = (const t8_hex_with_subelements *) elem2; const p8est_quadrant_t *q = &phex_w_sub_elem1->p8q; const p8est_quadrant_t *r = &phex_w_sub_elem2->p8q; @@ -176,19 +155,15 @@ t8_subelement_scheme_hex_c::t8_element_compare (const t8_element_t *elem1, T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); - int compare = p8est_quadrant_compare (q, r); + int compare = p8est_quadrant_compare (q, r); - if (compare == 0 && (t8_element_is_subelement (elem1) - || t8_element_is_subelement (elem2))) { - // t8_debugf ("Caution, t8_element_compare is used with subelements.\n"); - if (t8_element_is_subelement (elem1) - && t8_element_is_subelement (elem2)) { + if (compare == 0 && (t8_element_is_subelement (elem1) || t8_element_is_subelement (elem2))) { + // t8_debugf ("Caution, t8_element_compare is used with subelements.\n"); + if (t8_element_is_subelement (elem1) && t8_element_is_subelement (elem2)) { /* Caution: The compare function is used for two subelements. */ - if (phex_w_sub_elem1->transition_type == - phex_w_sub_elem2->transition_type - && phex_w_sub_elem1->subelement_id == - phex_w_sub_elem2->subelement_id) { + if (phex_w_sub_elem1->transition_type == phex_w_sub_elem2->transition_type + && phex_w_sub_elem1->subelement_id == phex_w_sub_elem2->subelement_id) { /* both subelements are identical */ return 0; } @@ -196,10 +171,10 @@ t8_subelement_scheme_hex_c::t8_element_compare (const t8_element_t *elem1, return 1; } else if (t8_element_is_subelement (elem1)) { - return -1; /* elem1 is subelement and therefore smaller */ + return -1; /* elem1 is subelement and therefore smaller */ } else if (t8_element_is_subelement (elem2)) { - return 1; /* elem2 is subelement and therefore smaller */ + return 1; /* elem2 is subelement and therefore smaller */ } } @@ -210,16 +185,13 @@ t8_subelement_scheme_hex_c::t8_element_compare (const t8_element_t *elem1, } void -t8_subelement_scheme_hex_c::t8_element_parent (const t8_element_t *elem, - t8_element_t *parent) const +t8_subelement_scheme_hex_c::t8_element_parent (const t8_element_t *elem, t8_element_t *parent) const { - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements *phex_w_sub_parent = - (t8_hex_with_subelements *) parent; + const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_parent = (t8_hex_with_subelements *) parent; const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - p8est_quadrant_t *r = &phex_w_sub_parent->p8q; + p8est_quadrant_t *r = &phex_w_sub_parent->p8q; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (parent)); @@ -233,21 +205,16 @@ t8_subelement_scheme_hex_c::t8_element_parent (const t8_element_t *elem, /* the parent of any element will never be a subelement */ t8_element_reset_subelement_values (parent); - } void -t8_subelement_scheme_hex_c::t8_element_sibling (const t8_element_t *elem, - int sibid, - t8_element_t *sibling) const +t8_subelement_scheme_hex_c::t8_element_sibling (const t8_element_t *elem, int sibid, t8_element_t *sibling) const { - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements *phex_w_sub_sibling = - (t8_hex_with_subelements *) sibling; + const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_sibling = (t8_hex_with_subelements *) sibling; const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - p8est_quadrant_t *r = &phex_w_sub_sibling->p8q; + p8est_quadrant_t *r = &phex_w_sub_sibling->p8q; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -266,13 +233,11 @@ t8_subelement_scheme_hex_c::t8_element_num_faces (const t8_element_t *elem) cons { T8_ASSERT (t8_element_is_valid (elem)); - return (t8_element_is_subelement (elem) ? T8_HEX_SUBELEMENT_FACES : - P8EST_FACES); + return (t8_element_is_subelement (elem) ? T8_HEX_SUBELEMENT_FACES : P8EST_FACES); } int -t8_subelement_scheme_hex_c::t8_element_max_num_faces (const t8_element_t - *elem) const +t8_subelement_scheme_hex_c::t8_element_max_num_faces (const t8_element_t *elem) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -281,8 +246,7 @@ t8_subelement_scheme_hex_c::t8_element_max_num_faces (const t8_element_t } int -t8_subelement_scheme_hex_c::t8_element_num_children (const t8_element_t - *elem) const +t8_subelement_scheme_hex_c::t8_element_num_children (const t8_element_t *elem) const { /* Note that children of subelements equal the children of the parent hexahedra. * Therefore, the number of children of a subelement equals P8EST_CHILDREN */ @@ -293,54 +257,44 @@ t8_subelement_scheme_hex_c::t8_element_num_children (const t8_element_t /* *INDENT-OFF* */ /* indent bug, indent adds a second "const" modifier */ -int -t8_subelement_scheme_hex_c::t8_element_num_siblings (const t8_element_t * - elem) const +int +t8_subelement_scheme_hex_c::t8_element_num_siblings (const t8_element_t *elem) const { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; - //no hanging nodes - if (phex_w_sub->transition_type == 0){ + //no hanging nodes + if (phex_w_sub->transition_type == 0) { return P8EST_CHILDREN; } - int num_hanging_faces = 0; - int iface; - for (iface = 0; iface < P8EST_FACES; iface++) { - /* Count the number of ones of the binary transition type. + int num_hanging_faces = 0; + int iface; + for (iface = 0; iface < P8EST_FACES; iface++) { + /* Count the number of ones of the binary transition type. * This number equals the number of hanging faces. */ - // binary shift << 1 Left-shift, d.h. *2¹ - // Right shift >> 1 Right-shift, d.h. *2⁻¹ - num_hanging_faces += - (phex_w_sub->transition_type & (1 << iface)) >> iface; + // binary shift << 1 Left-shift, d.h. *2¹ + // Right shift >> 1 Right-shift, d.h. *2⁻¹ + num_hanging_faces += (phex_w_sub->transition_type & (1 << iface)) >> iface; } - return P8EST_FACES + 3*num_hanging_faces; + return P8EST_FACES + 3 * num_hanging_faces; } int -t8_subelement_scheme_hex_c::t8_element_num_face_children (const t8_element_t - *elem, - int face) const +t8_subelement_scheme_hex_c::t8_element_num_face_children (const t8_element_t *elem, int face) const { /* this function is not implemented for subelements */ - T8_ASSERT (!t8_element_is_subelement (elem)); + T8_ASSERT (!t8_element_is_subelement (elem)); - T8_ASSERT (t8_element_is_valid (elem)); + T8_ASSERT (t8_element_is_valid (elem)); /* if we use hex scheme without set_transition, then we are only balanced * and four neighbors are possible */ return 4; - } int -t8_subelement_scheme_hex_c::t8_element_neighbor_is_sibling (const - t8_element_t - *elem, - const int face) - const +t8_subelement_scheme_hex_c::t8_element_neighbor_is_sibling (const t8_element_t *elem, const int face) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_subelement (elem)); @@ -352,97 +306,87 @@ t8_subelement_scheme_hex_c::t8_element_neighbor_is_sibling (const return 0; } - int t8_subelement_scheme_hex_c::t8_element_get_num_sibling_neighbors_at_face (const t8_element_t *elem, - const int face) const + const int face) const { - const t8_hex_with_subelements *hex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *hex_w_sub = (const t8_hex_with_subelements *) elem; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_subelement (elem)); T8_ASSERT (face == 0 || face == 1 || face == 2 || face == 3); -int location[3] = { }; + int location[3] = {}; //( location[0] = face_number of transition cell, location[1] = if split or not ( 1 = split ), location[2] = sub_id - t8_element_get_location_of_subelement (elem, location); - int split = location[1]; - int hex_face = location[0]; - int neigh_hex_face; - int transition_type; -if( split == 1){ - return 1; -} -else{ -neigh_hex_face = subelement_face_to_dual_subelement[hex_face][face]; -transition_type = hex_w_sub->transition_type; - -if ((transition_type & (int) pow(2, 5 - neigh_hex_face)) != 0 ){ - return 2; -}else{ - return 1; -} + t8_element_get_location_of_subelement (elem, location); + int split = location[1]; + int hex_face = location[0]; + int neigh_hex_face; + int transition_type; + if (split == 1) { + return 1; + } + else { + neigh_hex_face = subelement_face_to_dual_subelement[hex_face][face]; + transition_type = hex_w_sub->transition_type; -} + if ((transition_type & (int) pow (2, 5 - neigh_hex_face)) != 0) { + return 2; + } + else { + return 1; + } + } } int t8_subelement_scheme_hex_c::t8_element_get_transition_refine_identifier () const { - + return T8_TRANSITION_CONFORMAL_HEX_REFINE_FUNCTION; } /* *INDENT-ON* */ int -t8_subelement_scheme_hex_c::t8_element_get_face_corner (const t8_element_t - *elem, int face, - int corner) const +t8_subelement_scheme_hex_c::t8_element_get_face_corner (const t8_element_t *elem, int face, int corner) const { T8_ASSERT (t8_element_is_valid (elem)); if (!t8_element_is_subelement (elem)) { - - //face has to be between 0 and 4 - //Corner has to be between 0 and 4 - T8_ASSERT (0 <= face && face < P8EST_FACES); - T8_ASSERT (0 <= corner && corner < 4); + + //face has to be between 0 and 4 + //Corner has to be between 0 and 4 + T8_ASSERT (0 <= face && face < P8EST_FACES); + T8_ASSERT (0 <= corner && corner < 4); return p8est_face_corners[face][corner]; } else { - int t8_face_corners_subelement[5][4] = { - {0, 2, 4 ,-1}, //f0 - {1, 3, 4, -1}, //f1 - {0, 1, 4, -1}, //f2 - {2, 3, 4, -1}, //f3 - {0, 1, 2, 3} //f4 + int t8_face_corners_subelement[5][4] = { + { 0, 2, 4, -1 }, //f0 + { 1, 3, 4, -1 }, //f1 + { 0, 1, 4, -1 }, //f2 + { 2, 3, 4, -1 }, //f3 + { 0, 1, 2, 3 } //f4 }; T8_ASSERT (0 <= face && face < T8_HEX_SUBELEMENT_FACES); T8_ASSERT (0 <= corner && corner < 5); return t8_face_corners_subelement[face][corner]; } - } int -t8_subelement_scheme_hex_c::t8_element_get_corner_face (const t8_element_t - *elem, int corner, - int face) const +t8_subelement_scheme_hex_c::t8_element_get_corner_face (const t8_element_t *elem, int corner, int face) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); - SC_ABORT ("This function is not implemented yet.\n"); - return 0; + SC_ABORT ("This function is not implemented yet.\n"); + return 0; } - void -t8_subelement_scheme_hex_c::t8_element_child (const t8_element_t *elem, - int childid, - t8_element_t *child) const +t8_subelement_scheme_hex_c::t8_element_child (const t8_element_t *elem, int childid, t8_element_t *child) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -464,41 +408,34 @@ t8_subelement_scheme_hex_c::t8_element_child (const t8_element_t *elem, T8_ASSERT (p8est_quadrant_is_parent (q, r)); } t8_element_reset_subelement_values (child); - } void -t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t - *elem, const int face, - const int num_neighbors, - t8_element_t - *neighbor_at_face[], - int *neigh_face) +t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_hex ( + const t8_element_t *elem, const int face, const int num_neighbors, t8_element_t *neighbor_at_face[], int *neigh_face) { T8_ASSERT (t8_element_is_subelement (elem)); T8_ASSERT (t8_element_neighbor_is_sibling (elem, face)); T8_ASSERT ((num_neighbors == 1) || (num_neighbors == 2)); T8_ASSERT (t8_element_is_valid (neighbor_at_face[0])); - + /* source = elem, destination = neighbor at face. --> They have the same anchor node + Morton index + level.*/ t8_element_copy (elem, neighbor_at_face[0]); -/* Expand neighbor_at_face to a subelement (subelement_id + transititon_type) + copy it into phex_w_sub_neighbor_at_face*/ - t8_hex_with_subelements * - phex_w_sub_neighbor_at_face = - (t8_hex_with_subelements *) neighbor_at_face[0]; - + /* Expand neighbor_at_face to a subelement (subelement_id + transititon_type) + copy it into phex_w_sub_neighbor_at_face*/ + t8_hex_with_subelements *phex_w_sub_neighbor_at_face = (t8_hex_with_subelements *) neighbor_at_face[0]; + //iterator variable int iter; //Get information about the location of the subelement. - int location[3] = { }; + int location[3] = {}; // location[0] = face_number of transition cell, location[1] = if split or not ( 1 = split ), location[2] = sub_id - t8_element_get_location_of_subelement (elem, location); - + t8_element_get_location_of_subelement (elem, location); + //Create a temporary variable to store the possible subelement_id of the neighbor int subelement_id_tmp = 0; int transition_type_tmp = 0; int amount_subelements = 0; - int transition_type = t8_element_get_transition_type(elem); + int transition_type = t8_element_get_transition_type (elem); int neigh_hex_face; int hlp; @@ -510,489 +447,461 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h */ neigh_face[0] = subelement_face_dual[location[0]][face]; - + //First check if (the own) face is split. - if(location[1] == 0){ //Not split + if (location[1] == 0) { //Not split //get hex_face_number of the face_neighbored subelement // neigh_hex_face is only correct, if the neighbor lies not at the same hex face. - neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; + neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; /*Check if the dual subelement is split. If it's split,the element has two neighbors * as siblings (case 2). Then we always take the left, front or down (in this order) subelement (the subelement with the lower sub * element ID). If the transition type is = 1 at the hex_face, it's split.*/ -//-----------------------------CASE 1-------------------------------------------------------- + //-----------------------------CASE 1-------------------------------------------------------- -//make rightshift until only the bits for the faces before our neighbors face are left. + //make rightshift until only the bits for the faces before our neighbors face are left. transition_type_tmp = transition_type >> (5 - neigh_hex_face); - + amount_subelements = 0; - - int i = (int) pow(2,5 - neigh_hex_face); + int i = (int) pow (2, 5 - neigh_hex_face); + + if ((transition_type & i) == 0) { //neighbor not split - if((transition_type & i) == 0){ //neighbor not split + for (iter = 0; iter <= neigh_hex_face; iter++) { - for(iter = 0 ; iter <= neigh_hex_face ; iter++){ - //Count the elements until our neighbored hex_face. - if(((transition_type_tmp >> iter ) & 1) != 0 ){ - amount_subelements += 4; - } - else{ - amount_subelements += 1; - } + if (((transition_type_tmp >> iter) & 1) != 0) { + amount_subelements += 4; } - + else { + amount_subelements += 1; + } + } //The subelement_id of the neighbor is then the amount of subelements till then - 1 - subelement_id_tmp = amount_subelements - 1 ; + subelement_id_tmp = amount_subelements - 1; phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; - } -//-------------------------CASE 2-------------------------------------- - else { //neighbor is split. We have to return 2 subelements. - amount_subelements = 0; - int subelement_id_tmp2 = 0; // In here we store the second subelement ID in case 2 if elem has two neighbors - /* For case 2 we need a second face neighbor */ - - t8_hex_with_subelements * - phex_w_sub_neighbor_at_face2 = - (t8_hex_with_subelements *) neighbor_at_face[1]; - - t8_element_copy (elem, neighbor_at_face[1]); + //-------------------------CASE 2-------------------------------------- + else { //neighbor is split. We have to return 2 subelements. + amount_subelements = 0; + int subelement_id_tmp2 = 0; // In here we store the second subelement ID in case 2 if elem has two neighbors + /* For case 2 we need a second face neighbor */ + t8_hex_with_subelements *phex_w_sub_neighbor_at_face2 = (t8_hex_with_subelements *) neighbor_at_face[1]; + t8_element_copy (elem, neighbor_at_face[1]); - //make rightshift until only the bits for the faces before our neighbors face are left. + //make rightshift until only the bits for the faces before our neighbors face are left. transition_type_tmp = transition_type >> (5 - neigh_hex_face); - for(iter = 0 ; iter <= neigh_hex_face ; iter++){ - + for (iter = 0; iter <= neigh_hex_face; iter++) { + //Count the elements until our neighbored hex_face. - if(((transition_type_tmp >> iter ) & 1) != 0 ){ - amount_subelements += 4; - } - else{ - amount_subelements += 1; - } + if (((transition_type_tmp >> iter) & 1) != 0) { + amount_subelements += 4; + } + else { + amount_subelements += 1; } + } - //If we know the hex_face_number of the neighbored element, we know which subelement_IDs to take. - if (location[0] == 0){ //For hex_face 0 its always the "front" two sub-ids - subelement_id_tmp = amount_subelements - 4; - subelement_id_tmp2 = amount_subelements - 2; - } - if (location[0] == 1){ //For hex_face 1 its always the right to sub-ids - subelement_id_tmp = amount_subelements - 3; - subelement_id_tmp2 = amount_subelements - 1; - } - if (location[0] == 2){ //for hex_face 2 its the "front" sub-ids - if( ( face == 0 ) || ( face == 1 ) ){ - subelement_id_tmp = amount_subelements - 4; + if (location[0] == 0) { //For hex_face 0 its always the "front" two sub-ids + subelement_id_tmp = amount_subelements - 4; subelement_id_tmp2 = amount_subelements - 2; } - if( ( face == 2 ) || ( face == 3 ) ){ - subelement_id_tmp = amount_subelements - 4; - subelement_id_tmp2 = amount_subelements - 3; - } - } - if (location[0] == 3){ //for hex_face 3 its the "back" sub-ids - if( ( face == 0 ) || ( face == 1 ) ){ - subelement_id_tmp = amount_subelements - 3; + if (location[0] == 1) { //For hex_face 1 its always the right to sub-ids + subelement_id_tmp = amount_subelements - 3; subelement_id_tmp2 = amount_subelements - 1; } - else if( ( face == 2 ) || ( face == 3 ) ){ - subelement_id_tmp = amount_subelements - 2; + if (location[0] == 2) { //for hex_face 2 its the "front" sub-ids + if ((face == 0) || (face == 1)) { + subelement_id_tmp = amount_subelements - 4; + subelement_id_tmp2 = amount_subelements - 2; + } + if ((face == 2) || (face == 3)) { + subelement_id_tmp = amount_subelements - 4; + subelement_id_tmp2 = amount_subelements - 3; + } + } + if (location[0] == 3) { //for hex_face 3 its the "back" sub-ids + if ((face == 0) || (face == 1)) { + subelement_id_tmp = amount_subelements - 3; + subelement_id_tmp2 = amount_subelements - 1; + } + else if ((face == 2) || (face == 3)) { + subelement_id_tmp = amount_subelements - 2; + subelement_id_tmp2 = amount_subelements - 1; + } + } //for hex_face 4 its the "down" sub-ids + if (location[0] == 4) { + subelement_id_tmp = amount_subelements - 4; + subelement_id_tmp2 = amount_subelements - 3; + } + if (location[0] == 5) { //for hex_face 5 its the "up" sub-ids + subelement_id_tmp = amount_subelements - 2; subelement_id_tmp2 = amount_subelements - 1; - } - } //for hex_face 4 its the "down" sub-ids - if (location[0] == 4){ - subelement_id_tmp = amount_subelements - 4; - subelement_id_tmp2 = amount_subelements - 3; + } + + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; + phex_w_sub_neighbor_at_face2->subelement_id = subelement_id_tmp2; + + if (neigh_face != NULL) { + neigh_face[1] = neigh_face[0]; + } } - if (location[0] == 5){ //for hex_face 5 its the "up" sub-ids - subelement_id_tmp = amount_subelements - 2; - subelement_id_tmp2 = amount_subelements - 1; - } - - phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; - phex_w_sub_neighbor_at_face2->subelement_id = subelement_id_tmp2; - - if ( neigh_face != NULL ){ - neigh_face[1] = neigh_face[0]; } - } -} - //-------------------------CASE 3-------------------------------------- - else{ + else { //The own face is split //get hex_face_number of the face_neighbored subelement - //Condition that the neighbor lies not on the same hex face: - hlp = 0; -//hex face 0 and 1 - if( location[0] == 0 || location[0] == 1){ - if( ((location[2] & 2) == 0 ) && (face == 1)) {//front - hlp += 1 ; - } - if( ((location[2] & 2) != 0 ) && (face == 0)) {//back - hlp += 1 ; - } - - if( ((location[2] & 1) == 0 ) && (face == 3)) {//bottom - hlp +=1 ; - } - if( ((location[2] & 1) != 0 ) && (face == 2)) {//up - hlp +=1 ; - } - } - //hex face 2 and 3 - if( location[0] == 2 || location[0] == 3){ - if( ((location[2] & 4) == 0 ) && (face == 1)) {//left - hlp +=1 ; - } - if( ((location[2] & 4) != 0 ) && (face == 0)) {//right - hlp +=1 ; - } - - if( ((location[2] & 1) == 0 ) && (face == 3)) {//bottom - hlp +=1 ; - } - if( ((location[2] & 1) != 0 ) && (face == 2)) {//up - hlp +=1 ; - } - } - - //hex face 4 and 5 - if( location[0] == 4 || location[0] == 5){ - if( ((location[2] & 4) == 0 ) && (face == 1)) {//left - hlp +=1 ; - } - if( ((location[2] & 4) != 0 ) && (face == 0)) {//right - hlp +=1 ; - } - - if( ((location[2] & 2) == 0 ) && (face == 3)) {//front - hlp +=1 ; - } - if( ((location[2] & 2) != 0 ) && (face == 2)) {//back - hlp +=1 ; - } - } - -//if none of these conditions is true, we are in case 3 -neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; -if( (hlp == 0) && ((transition_type & (int) pow(2,5 - neigh_hex_face)) == 0)){ - - if((transition_type & (int) pow(2,5 - neigh_hex_face)) == 0){ //neighbor not split - - //it's not possible, that the neighbor lies on the same hex face here, because the own face is split here and if the neighbor would lie on the same face - //its face would obviously be split too. - neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; - //make rightshift until only the bits for the faces before our neighbors face are left. - transition_type_tmp = transition_type >> (5 - neigh_hex_face); + //Condition that the neighbor lies not on the same hex face: + hlp = 0; + //hex face 0 and 1 + if (location[0] == 0 || location[0] == 1) { + if (((location[2] & 2) == 0) && (face == 1)) { //front + hlp += 1; + } + if (((location[2] & 2) != 0) && (face == 0)) { //back + hlp += 1; + } + + if (((location[2] & 1) == 0) && (face == 3)) { //bottom + hlp += 1; + } + if (((location[2] & 1) != 0) && (face == 2)) { //up + hlp += 1; + } + } + //hex face 2 and 3 + if (location[0] == 2 || location[0] == 3) { + if (((location[2] & 4) == 0) && (face == 1)) { //left + hlp += 1; + } + if (((location[2] & 4) != 0) && (face == 0)) { //right + hlp += 1; + } + + if (((location[2] & 1) == 0) && (face == 3)) { //bottom + hlp += 1; + } + if (((location[2] & 1) != 0) && (face == 2)) { //up + hlp += 1; + } + } + + //hex face 4 and 5 + if (location[0] == 4 || location[0] == 5) { + if (((location[2] & 4) == 0) && (face == 1)) { //left + hlp += 1; + } + if (((location[2] & 4) != 0) && (face == 0)) { //right + hlp += 1; + } + + if (((location[2] & 2) == 0) && (face == 3)) { //front + hlp += 1; + } + if (((location[2] & 2) != 0) && (face == 2)) { //back + hlp += 1; + } + } + + //if none of these conditions is true, we are in case 3 + neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; + if ((hlp == 0) && ((transition_type & (int) pow (2, 5 - neigh_hex_face)) == 0)) { + + if ((transition_type & (int) pow (2, 5 - neigh_hex_face)) == 0) { //neighbor not split + + //it's not possible, that the neighbor lies on the same hex face here, because the own face is split here and if the neighbor would lie on the same face + //its face would obviously be split too. + neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; + //make rightshift until only the bits for the faces before our neighbors face are left. + transition_type_tmp = transition_type >> (5 - neigh_hex_face); + + for (iter = 0; iter <= neigh_hex_face; iter++) { - for(iter = 0; iter <= neigh_hex_face; iter++){ - //Count the elements until our neighbored hex_face. - if(((transition_type_tmp >> iter ) & 1) != 0 ){ - amount_subelements += 4; + if (((transition_type_tmp >> iter) & 1) != 0) { + amount_subelements += 4; } - else{ + else { amount_subelements += 1; } } - subelement_id_tmp = amount_subelements - 1; + subelement_id_tmp = amount_subelements - 1; + } + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; } -phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; -} - - -//---------------------------CASE 4-------------------------------------- - else{ - //It's possible, that the neighbored subelement has the same face_hex number as the element itself - // - amount_subelements = 0; - subelement_id_tmp = 0; - hlp = 0; - + //---------------------------CASE 4-------------------------------------- + else { + //It's possible, that the neighbored subelement has the same face_hex number as the element itself + // + amount_subelements = 0; + subelement_id_tmp = 0; + hlp = 0; -//Now we need the subelement_id_type (location[2]) to determine the exact location of the -//subelement in the transition cell + //Now we need the subelement_id_type (location[2]) to determine the exact location of the + //subelement in the transition cell - /* We have to go through all hex_faces + /* We have to go through all hex_faces */ - if(location[0] == 0 || location[0] == 1){ // hex_face = 0/1 - if((location[2] & 2) != 0 ){//back - if(face == 0){ //then it's the element before. + if (location[0] == 0 || location[0] == 1) { // hex_face = 0/1 + if ((location[2] & 2) != 0) { //back + if (face == 0) { //then it's the element before. subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; hlp += 1; - } - } - else{ - if(face == 1){ //then it's the element after. + } + } + else { + if (face == 1) { //then it's the element after. subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; hlp += 1; - } - } - if((location[2] & 1) != 0){//up - if(face == 2){ //then it's the element below - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; - hlp += 1; - } } - else{ //down - if(face == 3){// down + } + if ((location[2] & 1) != 0) { //up + if (face == 2) { //then it's the element below + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; + hlp += 1; + } + } + else { //down + if (face == 3) { // down subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 2; hlp += 1; - } - } - } - - if(location[0] == 2 || location[0] == 3){ // hex_face = 2/3 - if((location[2] & 4) != 0 ){ //right - if( face == 0){ //then it's the element before. - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; - hlp += 1; - } + } + } } - else{ //left - if ( face == 1 ){ // then it's the next element - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; - hlp += 1; - } - } - if((location[2] & 1) != 0){//up - if(face == 2 ){ //then it's the element below - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; - hlp += 1; - } + if (location[0] == 2 || location[0] == 3) { // hex_face = 2/3 + if ((location[2] & 4) != 0) { //right + if (face == 0) { //then it's the element before. + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; + hlp += 1; + } + } + else { //left + if (face == 1) { // then it's the next element + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; + hlp += 1; } - else{ //down - if(face == 3){//then its the element above + } + if ((location[2] & 1) != 0) { //up + if (face == 2) { //then it's the element below + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; + hlp += 1; + } + } + else { //down + if (face == 3) { //then its the element above subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 2; hlp += 1; - } + } + } } - } - if(location[0] == 4 || location[0] == 5){ // hex_face = 4/5 - if((location[2] & 4) != 0 ){//right - if(face == 0){ //then it's the element before. + if (location[0] == 4 || location[0] == 5) { // hex_face = 4/5 + if ((location[2] & 4) != 0) { //right + if (face == 0) { //then it's the element before. subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; hlp += 1; - } - else{ //left - if(face == 1){ //then it's the next element. - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; - hlp += 1; - } } - } - if((location[2] & 2) != 0){//back - if(face == 2){ //then it's the element in front - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; + else { //left + if (face == 1) { //then it's the next element. + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; hlp += 1; } } - else{ //front - if(face == 3){ + } + if ((location[2] & 2) != 0) { //back + if (face == 2) { //then it's the element in front + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; + hlp += 1; + } + } + else { //front + if (face == 3) { subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 2; hlp += 1; - } - } + } + } } neigh_face[0] = subelement_location_to_parent_dual_face[face]; phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; -if(hlp == 0){ //if the neighbor lies not on the same hex face as elem - //get hex_face_number of the face_neighbored subelement - neigh_face[0] = subelement_face_dual[location[0]][face]; - - neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; + if (hlp == 0) { //if the neighbor lies not on the same hex face as elem + //get hex_face_number of the face_neighbored subelement + neigh_face[0] = subelement_face_dual[location[0]][face]; + neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; //The neighbored element is not at the same hex face //First count the amount of subelements until the hex_face of the neighbored subelement is reached. //make rightshift until only the bits for the faces before our neighbors face are left. transition_type_tmp = transition_type >> (5 - neigh_hex_face); - for(iter = 0; iter <= neigh_hex_face; iter++){ - + for (iter = 0; iter <= neigh_hex_face; iter++) { + //Count the elements until our neighbored hex_face. - if(((transition_type_tmp >> iter ) & 1) != 0 ){ - amount_subelements += 4; + if (((transition_type_tmp >> iter) & 1) != 0) { + amount_subelements += 4; } - else{ + else { amount_subelements += 1; } } - //For the hex_faces 0 or 1 all possible neighbors will have a subelement_id that is greater than the own subelement_id - if( (location[0] == 0) || (location[0] == 1)){ - if(face == 0){ + if ((location[0] == 0) || (location[0] == 1)) { + if (face == 0) { subelement_id_tmp = amount_subelements - 4 + phex_w_sub_neighbor_at_face->subelement_id; } - if(face == 1){ + if (face == 1) { subelement_id_tmp = amount_subelements - 5 + phex_w_sub_neighbor_at_face->subelement_id; } - if(face == 2 || face == 3){ + if (face == 2 || face == 3) { //We have to distinguish if the element is in the front or back. - if((location[2] & 2) == 0){//front - subelement_id_tmp = amount_subelements - 4 + location[0]; + if ((location[2] & 2) == 0) { //front + subelement_id_tmp = amount_subelements - 4 + location[0]; } - else{ - subelement_id_tmp = amount_subelements - 2 + location[0]; + else { + subelement_id_tmp = amount_subelements - 2 + location[0]; } } } /* Because all faces = 0 of subelements at hex face 2,3,4 and 5 touch the hex_face 0, * all faces = 1 touch hex_face 1 and all faces = 2 touch the hex_face 4, * and all faces = 3 touch hex_face 5, we can hardcode these cases */ - else{ - if( face == 0){ + else { + if (face == 0) { //We have to distinguish if the element is in the front or back. - if(location[0] >= 4 ){ - if((location[2] & 2) == 0){//front - if(location[0] == 4){ // we are at hex_face 4 - subelement_id_tmp = 0; - } - else{ //hex face 5 - subelement_id_tmp = 2; + if (location[0] >= 4) { + if ((location[2] & 2) == 0) { //front + if (location[0] == 4) { // we are at hex_face 4 + subelement_id_tmp = 0; + } + else { //hex face 5 + subelement_id_tmp = 2; } } - else{//back - if(location[0] == 4){ // we are at hex_face 4 - subelement_id_tmp = 1; + else { //back + if (location[0] == 4) { // we are at hex_face 4 + subelement_id_tmp = 1; } - if(location[0] == 5){ - subelement_id_tmp = 4; + if (location[0] == 5) { + subelement_id_tmp = 4; } + } } - } - if (location[0] <= 3 ) { //only for hex faces 2 and the the subelements can be up or down + if (location[0] <= 3) { //only for hex faces 2 and the the subelements can be up or down - if((location[2] & 1) == 0){//down - if(location[0] == 2){ // we are at hex_face 2 - subelement_id_tmp = 0; - } - if(location[0] == 3){ - subelement_id_tmp = 1; - } - else{ //up - if(location[0] == 2){ // we are at hex_face 2 - subelement_id_tmp = 2; + if ((location[2] & 1) == 0) { //down + if (location[0] == 2) { // we are at hex_face 2 + subelement_id_tmp = 0; } - if(location[0] == 3){ - subelement_id_tmp = 3; - } - } + if (location[0] == 3) { + subelement_id_tmp = 1; + } + else { //up + if (location[0] == 2) { // we are at hex_face 2 + subelement_id_tmp = 2; + } + if (location[0] == 3) { + subelement_id_tmp = 3; + } + } + } + } } - - } - - } - //same for face = 1 - if(face == 1){ + //same for face = 1 + if (face == 1) { //We have to distinguish if the element is in the front or back. - if((location[2] & 2) == 0){//front - if(location[0] == 4){ // we are at hex_face 4 - subelement_id_tmp = amount_subelements - 4; + if ((location[2] & 2) == 0) { //front + if (location[0] == 4) { // we are at hex_face 4 + subelement_id_tmp = amount_subelements - 4; } - if(location[0] == 5){ - subelement_id_tmp = amount_subelements - 2; + if (location[0] == 5) { + subelement_id_tmp = amount_subelements - 2; } } - else{//back - if(location[0] == 4){ // we are at hex_face 4 - subelement_id_tmp = amount_subelements - 3; - } - if(location[0] == 5){ - subelement_id_tmp = amount_subelements - 1; - } + else { //back + if (location[0] == 4) { // we are at hex_face 4 + subelement_id_tmp = amount_subelements - 3; + } + if (location[0] == 5) { + subelement_id_tmp = amount_subelements - 1; + } } - if((location[2] & 1) == 0){//down - if(location[0] == 2){ // we are at hex_face 2 - subelement_id_tmp = amount_subelements - 4; + if ((location[2] & 1) == 0) { //down + if (location[0] == 2) { // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 4; } - if(location[0] == 3){ - subelement_id_tmp = amount_subelements - 3; + if (location[0] == 3) { + subelement_id_tmp = amount_subelements - 3; } - else{ //up - if(location[0] == 2){ // we are at hex_face 2 - subelement_id_tmp = amount_subelements - 2; + else { //up + if (location[0] == 2) { // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 2; } - if(location[0] == 3){ - subelement_id_tmp = amount_subelements - 1; - } - } + if (location[0] == 3) { + subelement_id_tmp = amount_subelements - 1; + } + } + } } - - } - //same for face = 2 - if(face == 3 || face == 2){ + //same for face = 2 + if (face == 3 || face == 2) { //We have to distinguish if the element is in the front or back. - if((location[2] & 4) == 0){//right - if(location[0] == 2){ // we are at hex_face 2 - subelement_id_tmp = amount_subelements - 3; - } - if(location[0] == 3){ - subelement_id_tmp = amount_subelements - 1; - } + if ((location[2] & 4) == 0) { //right + if (location[0] == 2) { // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 3; + } + if (location[0] == 3) { + subelement_id_tmp = amount_subelements - 1; + } } - else{//left - if(location[0] == 2){ // we are at hex_face 2 - subelement_id_tmp = amount_subelements - 4; + else { //left + if (location[0] == 2) { // we are at hex_face 2 + subelement_id_tmp = amount_subelements - 4; } - if(location[0] == 3){ - subelement_id_tmp = amount_subelements - 2; + if (location[0] == 3) { + subelement_id_tmp = amount_subelements - 2; } } - - } - - } - phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; - } + } + } + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; } - -} - phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; + } + } + phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; } - - - void -t8_subelement_scheme_hex_c::t8_element_children (const t8_element_t *elem, - int length, - t8_element_t *c[]) const +t8_subelement_scheme_hex_c::t8_element_children (const t8_element_t *elem, int length, t8_element_t *c[]) const { /* if elem is a subelement, then this function will construct the children of its parent p8est quadrant */ - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements **phex_w_sub_children = - (t8_hex_with_subelements **) c; + const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements **phex_w_sub_children = (t8_hex_with_subelements **) c; const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - int ichild; + int ichild; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (length == P8EST_CHILDREN); #ifdef T8_ENABLE_DEBUG { - int i; + int i; for (i = 0; i < P8EST_CHILDREN; i++) { T8_ASSERT (t8_element_is_valid (c[i])); } @@ -1000,15 +909,9 @@ t8_subelement_scheme_hex_c::t8_element_children (const t8_element_t *elem, #endif /* set coordinates and levels of the children */ - p8est_quadrant_children (q, &phex_w_sub_children[0]->p8q, - &phex_w_sub_children[1]->p8q, - &phex_w_sub_children[2]->p8q, - &phex_w_sub_children[3]->p8q, - &phex_w_sub_children[4]->p8q, - &phex_w_sub_children[5]->p8q, - &phex_w_sub_children[6]->p8q, - &phex_w_sub_children[7]->p8q -); + p8est_quadrant_children (q, &phex_w_sub_children[0]->p8q, &phex_w_sub_children[1]->p8q, &phex_w_sub_children[2]->p8q, + &phex_w_sub_children[3]->p8q, &phex_w_sub_children[4]->p8q, &phex_w_sub_children[5]->p8q, + &phex_w_sub_children[6]->p8q, &phex_w_sub_children[7]->p8q); for (ichild = 0; ichild < P8EST_CHILDREN; ++ichild) { t8_element_reset_subelement_values (c[ichild]); @@ -1018,24 +921,18 @@ t8_subelement_scheme_hex_c::t8_element_children (const t8_element_t *elem, int t8_subelement_scheme_hex_c::t8_element_child_id (const t8_element_t *elem) const { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; const p8est_quadrant_t *q = &phex_w_sub->p8q; T8_ASSERT (t8_element_is_valid (elem)); - return (t8_element_is_subelement (elem) ? phex_w_sub->subelement_id : - p8est_quadrant_child_id (q)); - - + return (t8_element_is_subelement (elem) ? phex_w_sub->subelement_id : p8est_quadrant_child_id (q)); } int -t8_subelement_scheme_hex_c::t8_element_ancestor_id (const t8_element_t *elem, - int level) const +t8_subelement_scheme_hex_c::t8_element_ancestor_id (const t8_element_t *elem, int level) const { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; const p8est_quadrant_t *q = &phex_w_sub->p8q; /* this function is not implemented for subelements */ @@ -1048,13 +945,12 @@ int t8_subelement_scheme_hex_c::t8_element_is_family (t8_element_t *const *fam) const { /* Note that this test is very rudimentary, especially when there subelements are in fam */ - t8_hex_with_subelements **phex_w_sub_family = - (t8_hex_with_subelements **) fam; + t8_hex_with_subelements **phex_w_sub_family = (t8_hex_with_subelements **) fam; #ifdef T8_ENABLE_DEBUG { - int i; - int num_siblings = t8_element_num_siblings (fam[0]); + int i; + int num_siblings = t8_element_num_siblings (fam[0]); for (i = 0; i < num_siblings; i++) { T8_ASSERT (t8_element_is_valid (fam[i])); } @@ -1068,39 +964,28 @@ t8_subelement_scheme_hex_c::t8_element_is_family (t8_element_t *const *fam) cons return 1; } /* If the first element of fam is no subelement we check the following elements of fam */ - else { + else { /* If any of the following elements is a subelement, then they can not form a family */ - if ((phex_w_sub_family[1]->transition_type != 0) || - (phex_w_sub_family[2]->transition_type != 0) || - (phex_w_sub_family[3]->transition_type != 0) || - (phex_w_sub_family[4]->transition_type != 0) || - (phex_w_sub_family[5]->transition_type != 0) || - (phex_w_sub_family[6]->transition_type != 0) || - (phex_w_sub_family[7]->transition_type != 0)) { + if ((phex_w_sub_family[1]->transition_type != 0) || (phex_w_sub_family[2]->transition_type != 0) + || (phex_w_sub_family[3]->transition_type != 0) || (phex_w_sub_family[4]->transition_type != 0) + || (phex_w_sub_family[5]->transition_type != 0) || (phex_w_sub_family[6]->transition_type != 0) + || (phex_w_sub_family[7]->transition_type != 0)) { return 0; } /* If all elements of fam are no subelements, then we can use the p8est check is_family */ else { - return p8est_quadrant_is_family (&phex_w_sub_family[0]->p8q, - &phex_w_sub_family[1]->p8q, - &phex_w_sub_family[2]->p8q, - &phex_w_sub_family[3]->p8q, - &phex_w_sub_family[4]->p8q, - &phex_w_sub_family[5]->p8q, - &phex_w_sub_family[6]->p8q, - &phex_w_sub_family[7]->p8q); + return p8est_quadrant_is_family ( + &phex_w_sub_family[0]->p8q, &phex_w_sub_family[1]->p8q, &phex_w_sub_family[2]->p8q, &phex_w_sub_family[3]->p8q, + &phex_w_sub_family[4]->p8q, &phex_w_sub_family[5]->p8q, &phex_w_sub_family[6]->p8q, &phex_w_sub_family[7]->p8q); } } } void -t8_subelement_scheme_hex_c::t8_element_set_linear_id (t8_element_t *elem, - int level, - t8_linearidx_t id) - const +t8_subelement_scheme_hex_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const { t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; - p8est_quadrant_t *q = &phex_w_sub->p8q; + p8est_quadrant_t *q = &phex_w_sub->p8q; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -1110,16 +995,13 @@ t8_subelement_scheme_hex_c::t8_element_set_linear_id (t8_element_t *elem, T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << P8EST_DIM * level); p8est_quadrant_set_morton (q, level, id); - } t8_linearidx_t - t8_subelement_scheme_hex_c::t8_element_get_linear_id (const t8_element_t - *elem, - int level) const +t8_subelement_scheme_hex_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const { t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; - p8est_quadrant_t *q = &phex_w_sub->p8q; + p8est_quadrant_t *q = &phex_w_sub->p8q; /* Note that the id of a subelement equals the id of its parent quadrant. * Therefore, the binary search (for example used in the leaf_face_neighbor function) @@ -1132,18 +1014,13 @@ t8_linearidx_t } void -t8_subelement_scheme_hex_c::t8_element_first_descendant (const t8_element_t - *elem, - t8_element_t *desc, - int level) const +t8_subelement_scheme_hex_c::t8_element_first_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const { - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements *phex_w_sub_desc = - (t8_hex_with_subelements *) desc; + const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_desc = (t8_hex_with_subelements *) desc; const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - p8est_quadrant_t *r = &phex_w_sub_desc->p8q; + p8est_quadrant_t *r = &phex_w_sub_desc->p8q; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (desc)); @@ -1157,22 +1034,16 @@ t8_subelement_scheme_hex_c::t8_element_first_descendant (const t8_element_t * hex element of the given subelement. Since the last descendant is not meant to be * a subelement, we reset the corresponding subelement values. */ t8_element_reset_subelement_values (desc); - } void -t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t - *elem, - t8_element_t *desc, - int level) const +t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const { - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements *phex_w_sub_desc = - (t8_hex_with_subelements *) desc; + const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_desc = (t8_hex_with_subelements *) desc; const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - p8est_quadrant_t *r = &phex_w_sub_desc->p8q; + p8est_quadrant_t *r = &phex_w_sub_desc->p8q; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (desc)); @@ -1180,7 +1051,6 @@ t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t // p8est_quadrant_last_descendant (q, r, level); p8est_quadrant_last_descendant ((p8est_quadrant_t *) elem, (p8est_quadrant_t *) desc, level); - /* We allow constructing a last descendant from a subelement. * Keep in mind, that transforming a hex element to a subelement does not change the * p8est quadrant. Therefore, we are constructing the last descendant of the parent @@ -1190,8 +1060,7 @@ t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t } void -t8_subelement_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, - t8_element_t *elem2) const +t8_subelement_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem1)); @@ -1199,25 +1068,20 @@ t8_subelement_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); T8_ASSERT (0 <= t8_element_level (elem1) && t8_element_level (elem1) <= P8EST_OLD_QMAXLEVEL); - p8est_quadrant_successor ((p8est_quadrant_t *) elem1, - (p8est_quadrant_t *) elem2); + p8est_quadrant_successor ((p8est_quadrant_t *) elem1, (p8est_quadrant_t *) elem2); } void -t8_subelement_scheme_hex_c::t8_element_nca (const t8_element_t *elem1, - const t8_element_t *elem2, - t8_element_t *nca) const +t8_subelement_scheme_hex_c::t8_element_nca (const t8_element_t *elem1, const t8_element_t *elem2, + t8_element_t *nca) const { - const t8_hex_with_subelements *phex_w_sub_elem1 = - (const t8_hex_with_subelements *) elem1; - const t8_hex_with_subelements *phex_w_sub_elem2 = - (const t8_hex_with_subelements *) elem2; - t8_hex_with_subelements *phex_w_sub_nca = - (t8_hex_with_subelements *) nca; + const t8_hex_with_subelements *phex_w_sub_elem1 = (const t8_hex_with_subelements *) elem1; + const t8_hex_with_subelements *phex_w_sub_elem2 = (const t8_hex_with_subelements *) elem2; + t8_hex_with_subelements *phex_w_sub_nca = (t8_hex_with_subelements *) nca; const p8est_quadrant_t *q1 = &phex_w_sub_elem1->p8q; const p8est_quadrant_t *q2 = &phex_w_sub_elem2->p8q; - p8est_quadrant_t *r = &phex_w_sub_nca->p8q; + p8est_quadrant_t *r = &phex_w_sub_nca->p8q; T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); @@ -1227,37 +1091,28 @@ t8_subelement_scheme_hex_c::t8_element_nca (const t8_element_t *elem1, p8est_nearest_common_ancestor (q1, q2, r); } - t8_element_shape_t -t8_subelement_scheme_hex_c::t8_element_face_shape (const t8_element_t *elem, - int face) const +t8_subelement_scheme_hex_c::t8_element_face_shape (const t8_element_t *elem, int face) const { T8_ASSERT (t8_element_is_valid (elem)); - if( t8_element_is_subelement (elem)){ - if(face == 4){ - return T8_ECLASS_QUAD; - } - else{ - return T8_ECLASS_TRIANGLE; - } - - } - else{ - return T8_ECLASS_QUAD; - } + if (t8_element_is_subelement (elem)) { + if (face == 4) { + return T8_ECLASS_QUAD; + } + else { + return T8_ECLASS_TRIANGLE; + } + } + else { + return T8_ECLASS_QUAD; + } } - void -t8_subelement_scheme_hex_c::t8_element_children_at_face (const t8_element_t - *elem, int face, - t8_element_t - *children[], - int num_children, - int *child_indices) - const +t8_subelement_scheme_hex_c::t8_element_children_at_face (const t8_element_t *elem, int face, t8_element_t *children[], + int num_children, int *child_indices) const { - int child_ids_local[4], i, *child_ids; + int child_ids_local[4], i, *child_ids; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (!t8_element_is_subelement (elem)); @@ -1265,7 +1120,7 @@ t8_subelement_scheme_hex_c::t8_element_children_at_face (const t8_element_t #ifdef T8_ENABLE_DEBUG { - int j; + int j; for (j = 0; j < P4EST_CHILDREN; j++) { T8_ASSERT (t8_element_is_valid (children[j])); } @@ -1307,15 +1162,12 @@ t8_subelement_scheme_hex_c::t8_element_children_at_face (const t8_element_t } } - int -t8_subelement_scheme_hex_c::t8_element_face_child_face (const t8_element_t - *elem, int face, - int face_child) const +t8_subelement_scheme_hex_c::t8_element_face_child_face (const t8_element_t *elem, int face, int face_child) const { T8_ASSERT (t8_element_is_valid (elem)); /* For octants the face enumeration of children is the same as for the parent. */ - if (t8_element_is_subelement (elem)) { + if (t8_element_is_subelement (elem)) { T8_ASSERT (face == 4); return t8_element_face_parent_face (elem, face); } @@ -1323,22 +1175,18 @@ t8_subelement_scheme_hex_c::t8_element_face_child_face (const t8_element_t /* For quadrants the face enumeration of children is the same as for the parent. */ return face; } - } int -t8_subelement_scheme_hex_c::t8_element_face_parent_face (const t8_element_t - *elem, - int face) const +t8_subelement_scheme_hex_c::t8_element_face_parent_face (const t8_element_t *elem, int face) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (face >= -1 && face < P8EST_FACES); - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; const p8est_quadrant_t *q = &phex_w_sub->p8q; - int child_id; + int child_id; if (face == -1) { return -1; } @@ -1349,9 +1197,9 @@ t8_subelement_scheme_hex_c::t8_element_face_parent_face (const t8_element_t if (face == 4) { /* In this case the face is a subface of the parent. We use the location function in order * to determine which of the parents faces intersects the subelements face. */ - int location[3] = { }; + int location[3] = {}; t8_element_get_location_of_subelement (elem, location); - + return subelement_location_to_parent_face[location[0]]; } else { @@ -1365,42 +1213,30 @@ t8_subelement_scheme_hex_c::t8_element_face_parent_face (const t8_element_t /* Determine whether face is a subface of the parent. * This is the case if the child_id matches one of the faces corners */ child_id = p8est_quadrant_child_id (q); - if (child_id == p8est_face_corners[face][0] - || child_id == p8est_face_corners[face][1] - || child_id == p8est_face_corners[face][2] - || child_id == p8est_face_corners[face][3]) { + if (child_id == p8est_face_corners[face][0] || child_id == p8est_face_corners[face][1] + || child_id == p8est_face_corners[face][2] || child_id == p8est_face_corners[face][3]) { return face; - } + } return -1; - } void -t8_subelement_scheme_hex_c::t8_element_transform_face (const t8_element_t - *elem1, - t8_element_t *elem2, - int orientation, - int sign, - int is_smaller_face) - const +t8_subelement_scheme_hex_c::t8_element_transform_face (const t8_element_t *elem1, t8_element_t *elem2, int orientation, + int sign, int is_smaller_face) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem1)); SC_ABORT ("This function is not implemented yet.\n"); - return; + return; } int -t8_subelement_scheme_hex_c::t8_element_extrude_face (const t8_element_t - *face, - const t8_eclass_scheme_c - *face_scheme, - t8_element_t *elem, - int root_face) const +t8_subelement_scheme_hex_c::t8_element_extrude_face (const t8_element_t *face, const t8_eclass_scheme_c *face_scheme, + t8_element_t *elem, int root_face) const { /* build (extrude) elem from a given face element */ t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; - p8est_quadrant_t *q = &phex_w_sub->p8q; + p8est_quadrant_t *q = &phex_w_sub->p8q; const p4est_quadrant_t *b = (const p4est_quadrant_t *) face; @@ -1464,8 +1300,7 @@ t8_subelement_scheme_hex_c::t8_element_extrude_face (const t8_element_t } int -t8_subelement_scheme_hex_c::t8_element_tree_face (const t8_element_t *elem, - int face) const +t8_subelement_scheme_hex_c::t8_element_tree_face (const t8_element_t *elem, int face) const { T8_ASSERT (t8_element_is_valid (elem)); @@ -1485,14 +1320,8 @@ t8_subelement_scheme_hex_c::t8_element_tree_face (const t8_element_t *elem, /** Construct the first descendant of an element that touches a given face. */ void -t8_subelement_scheme_hex_c::t8_element_first_descendant_face (const - t8_element_t - *elem, - int face, - t8_element_t - *first_desc, - int level) - const +t8_subelement_scheme_hex_c::t8_element_first_descendant_face (const t8_element_t *elem, int face, + t8_element_t *first_desc, int level) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -1510,15 +1339,10 @@ t8_subelement_scheme_hex_c::t8_element_first_descendant_face (const p8est_quadrant_corner_descendant (q, desc, first_face_corner, level); } - /** Construct the last descendant of an element that touches a given face. */ void -t8_subelement_scheme_hex_c::t8_element_last_descendant_face (const - t8_element_t - *elem, int face, - t8_element_t - *last_desc, - int level) const +t8_subelement_scheme_hex_c::t8_element_last_descendant_face (const t8_element_t *elem, int face, + t8_element_t *last_desc, int level) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -1538,18 +1362,13 @@ t8_subelement_scheme_hex_c::t8_element_last_descendant_face (const } void -t8_subelement_scheme_hex_c::t8_element_boundary_face (const t8_element_t - *elem, int face, - t8_element_t *boundary, - const - t8_eclass_scheme_c - *boundary_scheme) const -{ - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; +t8_subelement_scheme_hex_c::t8_element_boundary_face (const t8_element_t *elem, int face, t8_element_t *boundary, + const t8_eclass_scheme_c *boundary_scheme) const +{ + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; const p8est_quadrant_t *q = &phex_w_sub->p8q; - p4est_quadrant_t *b = (p4est_quadrant_t *) boundary; + p4est_quadrant_t *b = (p4est_quadrant_t *) boundary; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (boundary_scheme->eclass == T8_ECLASS_QUAD); @@ -1578,10 +1397,9 @@ t8_subelement_scheme_hex_c::t8_element_boundary_face (const t8_element_t * We have to scale the coordinates since a root quadrant may have * different length than a root hex. */ - b->x = (face >> 1 ? q->x : q->y) * ((t8_linearidx_t) P4EST_ROOT_LEN / P8EST_ROOT_LEN); /* true if face >= 2 */ - b->y = (face >> 2 ? q->y : q->z) * ((t8_linearidx_t) P4EST_ROOT_LEN / P8EST_ROOT_LEN); /* true if face >= 4 */ - T8_ASSERT (!p8est_quadrant_is_extended (q) - || p4est_quadrant_is_extended (b)); + b->x = (face >> 1 ? q->x : q->y) * ((t8_linearidx_t) P4EST_ROOT_LEN / P8EST_ROOT_LEN); /* true if face >= 2 */ + b->y = (face >> 2 ? q->y : q->z) * ((t8_linearidx_t) P4EST_ROOT_LEN / P8EST_ROOT_LEN); /* true if face >= 4 */ + T8_ASSERT (!p8est_quadrant_is_extended (q) || p4est_quadrant_is_extended (b)); } else { /* face number 4 is the only face of a subelement that points outward of the transition cell */ @@ -1590,50 +1408,46 @@ t8_subelement_scheme_hex_c::t8_element_boundary_face (const t8_element_t * for a split subelement, the boundary face has a higher level * for a non split element, the boundary face has the same level. */ - /* location = {location of subelement (face number of transition cell), split, subelement type (left/right, front/back, bottom/up)} */ - int location[3] = { }; + /* location = {location of subelement (face number of transition cell), split, subelement type (left/right, front/back, bottom/up)} */ + int location[3] = {}; t8_element_get_location_of_subelement (elem, location); - int split = location[1]; - int subelement_type = location[2]; + int split = location[1]; + int subelement_type = location[2]; - if (split) { /* if the subelement lies at a split face */ + if (split) { /* if the subelement lies at a split face */ b->level = q->level + 1; - int len = - P8EST_QUADRANT_LEN (phex_w_sub->p8q.level + 1); - if ((location[0] == 0) || (location[0] == 1)) { /* left or right face */ - if( (subelement_type & 2) != 0){ //back - b->x = q->y + len; - } - else if((subelement_type & 1) != 0){ //up - b->y = q->z + len; - } - } - else if ((location[0] == 2) || (location[0] == 3)) { /* front or back face */ - if((subelement_type & 4) != 0){ //right - b->x = q->x + len; - } - else if ((subelement_type & 1) != 0) { // up - b->y = q->z + len; + int len = P8EST_QUADRANT_LEN (phex_w_sub->p8q.level + 1); + if ((location[0] == 0) || (location[0] == 1)) { /* left or right face */ + if ((subelement_type & 2) != 0) { //back + b->x = q->y + len; } + else if ((subelement_type & 1) != 0) { //up + b->y = q->z + len; } - else if ((location[0] == 2) || (location[0] == 3)) { /* bottom or up face */ - if((subelement_type & 4) != 0){ //right - b->x = q->x + len; - } - else if ((subelement_type & 2) != 0) { // back - b->y = q->y + len; + } + else if ((location[0] == 2) || (location[0] == 3)) { /* front or back face */ + if ((subelement_type & 4) != 0) { //right + b->x = q->x + len; + } + else if ((subelement_type & 1) != 0) { // up + b->y = q->z + len; + } + } + else if ((location[0] == 2) || (location[0] == 3)) { /* bottom or up face */ + if ((subelement_type & 4) != 0) { //right + b->x = q->x + len; + } + else if ((subelement_type & 2) != 0) { // back + b->y = q->y + len; } } } - } } void -t8_subelement_scheme_hex_c::t8_element_boundary (const t8_element_t *elem, - int min_dim, int length, - t8_element_t **boundary) - const +t8_subelement_scheme_hex_c::t8_element_boundary (const t8_element_t *elem, int min_dim, int length, + t8_element_t **boundary) const { SC_ABORT ("Not implemented\n"); #if 0 @@ -1653,17 +1467,14 @@ t8_subelement_scheme_hex_c::t8_element_boundary (const t8_element_t *elem, } int -t8_subelement_scheme_hex_c::t8_element_is_root_boundary (const t8_element_t - *elem, - int face) const +t8_subelement_scheme_hex_c::t8_element_is_root_boundary (const t8_element_t *elem, int face) const { T8_ASSERT (t8_element_is_valid (elem)); - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; const p8est_quadrant_t *q = &phex_w_sub->p8q; - p4est_qcoord_t coord; + p4est_qcoord_t coord; /* In case of a subelement, we need to change its face number to the face number of the parent hex */ if (t8_element_is_subelement (elem)) { @@ -1671,7 +1482,7 @@ t8_subelement_scheme_hex_c::t8_element_is_root_boundary (const t8_element_t /* adjust face of subelement to face of parent */ face = t8_element_face_parent_face (elem, face); } - else { /* in case of a subelement and face 0 or 2 the face is no subface of the root boundary */ + else { /* in case of a subelement and face 0 or 2 the face is no subface of the root boundary */ return 0; } } @@ -1686,57 +1497,45 @@ t8_subelement_scheme_hex_c::t8_element_is_root_boundary (const t8_element_t * If face is 1,3 or 5 check against LAST_OFFSET */ // t8_debugf("t8 element is root boundary %i\n", coord == (face & 1 ? P8EST_LAST_OFFSET (q->level) : 0)); return coord == (face & 1 ? P8EST_LAST_OFFSET (q->level) : 0); - - } int -t8_subelement_scheme_hex_c::t8_element_face_neighbor_inside (const - t8_element_t - *elem, - t8_element_t - *neigh, - int face, - int *neigh_face) - const +t8_subelement_scheme_hex_c::t8_element_face_neighbor_inside (const t8_element_t *elem, t8_element_t *neigh, int face, + int *neigh_face) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (neigh)); T8_ASSERT (0 <= face && face < P8EST_FACES); - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements *phex_w_sub_neigh = - (t8_hex_with_subelements *) neigh; + const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements *phex_w_sub_neigh = (t8_hex_with_subelements *) neigh; const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; - p8est_quadrant_t *n = &phex_w_sub_neigh->p8q; + p8est_quadrant_t *n = &phex_w_sub_neigh->p8q; // /* In case of a subelement one should construct the face neighbor of the face-corresponding child quadrant // * of the subelements parent quadrant. Therefore we might want to adjust the level and adapt the // * anchor node. */ - if (t8_element_is_subelement (elem)) { /* if elem is a subelement */ + if (t8_element_is_subelement (elem)) { /* if elem is a subelement */ T8_ASSERT (0 <= face && face < T8_HEX_SUBELEMENT_FACES); -int location[3] = { }; - t8_element_get_location_of_subelement (elem, location); - if (face < 4) { /* in this case the face neighbor of the subelement is a sibling */ + int location[3] = {}; + t8_element_get_location_of_subelement (elem, location); + if (face < 4) { /* in this case the face neighbor of the subelement is a sibling */ /* level and anchor stay the same */ n->x = q->x; n->y = q->y; n->z = q->z; n->level = q->level; - + T8_ASSERT (face != 4); - SC_ABORT_NOT_REACHED(); + SC_ABORT_NOT_REACHED (); /* return dual face with resprect to neighboring sibling subelement (note that the constructed neigh is NOT a subelement but the parent hex) */ /* Compute the face number as seen from q. * 0 -> 2 2 -> 0 */ *neigh_face = subelement_face_dual[location[0]][face]; - - } - else { /* in this case the face neighbor is no sibling */ + else { /* in this case the face neighbor is no sibling */ /* setting the anchor node of the neighbor element */ n->x = q->x; @@ -1746,71 +1545,71 @@ int location[3] = { }; /* half the side length of the transition cell of the subelement */ const p4est_qcoord_t shift = P8EST_QUADRANT_LEN (q->level + 1); - int split = location[1]; - int subelement_type = location[2]; - + int split = location[1]; + int subelement_type = location[2]; + /* we need to take into account whether the subelement is split or not */ - if (split) { /* split */ + if (split) { /* split */ /* increase the level by one */ n->level = q->level + 1; /* adjust the anchor node of the neighbor of the subelement depending on its location */ if (location[0] == 0) { /* left face */ n->x = q->x - shift; - if ((subelement_type & 2) != 0 ) { //back + if ((subelement_type & 2) != 0) { //back n->y = q->y + shift; } - if ((subelement_type & 1) != 0 ){ //up + if ((subelement_type & 1) != 0) { //up n->z = q->z + shift; } } - else if (location[0] == 1) { /* right face */ + else if (location[0] == 1) { /* right face */ n->x = q->x + 2 * shift; - if ((subelement_type & 2) != 0) { //back + if ((subelement_type & 2) != 0) { //back n->y = q->y + shift; } - if ((subelement_type & 1) != 0 ){ //up + if ((subelement_type & 1) != 0) { //up n->z = q->z + shift; } } - else if (location[0] == 2) { /* front face */ + else if (location[0] == 2) { /* front face */ n->y = q->y - shift; - if ((subelement_type & 4) != 0) { //right + if ((subelement_type & 4) != 0) { //right n->x = q->x + shift; } - if ((subelement_type & 1) != 0 ) {//up + if ((subelement_type & 1) != 0) { //up n->z = q->z + shift; } } - else if (location[0] == 3){ //back face + else if (location[0] == 3) { //back face n->y = q->y + 2 * shift; - if ((subelement_type & 4) != 0) { //right + if ((subelement_type & 4) != 0) { //right n->x = q->x + shift; } - if((subelement_type & 1) != 0 ) {//up + if ((subelement_type & 1) != 0) { //up n->z = q->z + shift; } } - else if (location[0] == 4){ //bottom face - if ((subelement_type & 4) != 0) { //right + else if (location[0] == 4) { //bottom face + if ((subelement_type & 4) != 0) { //right n->x = q->x + shift; } - if ((subelement_type & 2) != 0 ) {//back + if ((subelement_type & 2) != 0) { //back n->z = q->z + shift; } } - else if (location[0] == 5){ //upper face - n->z = q->z + 2 * shift; - if ((subelement_type & 4) != 0) { //right + else if (location[0] == 5) { //upper face + n->z = q->z + 2 * shift; + if ((subelement_type & 4) != 0) { //right n->x = q->x + shift; } - if ((subelement_type & 2) != 0 ) {//back + if ((subelement_type & 2) != 0) { //back n->z = q->z + shift; } - } + } } - else { /* not split */ + else { /* not split */ /* level stays the same */ n->level = q->level; @@ -1818,33 +1617,31 @@ int location[3] = { }; if (location[0] == 0) { /* left face */ n->x = q->x - 2 * shift; } - else if (location[0] == 1) { /* right face */ + else if (location[0] == 1) { /* right face */ n->x = q->x + 2 * shift; } - else if (location[0] == 2) { /* front face */ + else if (location[0] == 2) { /* front face */ n->y = q->y - 2 * shift; } - else if (location[0] == 3) { /* back face */ + else if (location[0] == 3) { /* back face */ n->y = q->y + 2 * shift; } - else if (location[0] == 4) { /* bottom face */ + else if (location[0] == 4) { /* bottom face */ n->z = q->z - 2 * shift; } - else if (location[0] == 5) { /* upper face */ + else if (location[0] == 5) { /* upper face */ n->z = q->z + 2 * shift; } } - + *neigh_face = subelement_location_to_parent_dual_face[location[0]]; } - - } - else { /* if elem is no subelement */ + else { /* if elem is no subelement */ - /* Compute the face neighbor */ - p8est_quadrant_face_neighbor (q, face, n); - /* Compute the face of q that coincides with face. + /* Compute the face neighbor */ + p8est_quadrant_face_neighbor (q, face, n); + /* Compute the face of q that coincides with face. * face neigh_face face neigh_face * 0 1 4 5 * 1 0 5 4 @@ -1852,28 +1649,23 @@ int location[3] = { }; * 3 2 */ - T8_ASSERT (neigh_face != NULL); - *neigh_face = p8est_face_dual[face]; - + T8_ASSERT (neigh_face != NULL); + *neigh_face = p8est_face_dual[face]; } t8_element_reset_subelement_values (neigh); - - if ( p8est_quadrant_is_inside_root(n) == 0){ + if (p8est_quadrant_is_inside_root (n) == 0) { } - /* return true if neigh is inside the root */ - return p8est_quadrant_is_inside_root (n); - + return p8est_quadrant_is_inside_root (n); } void -t8_subelement_scheme_hex_c::t8_element_anchor (const t8_element_t *elem, - int coord[3]) const +t8_subelement_scheme_hex_c::t8_element_anchor (const t8_element_t *elem, int coord[3]) const { t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; - p8est_quadrant_t *q = &phex_w_sub->p8q; + p8est_quadrant_t *q = &phex_w_sub->p8q; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -1883,7 +1675,6 @@ t8_subelement_scheme_hex_c::t8_element_anchor (const t8_element_t *elem, coord[0] = q->x; coord[1] = q->y; coord[2] = q->z; - } int @@ -1900,261 +1691,240 @@ t8_subelement_scheme_hex_c::t8_element_refines_irregular () const } void - t8_subelement_scheme_hex_c::t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const - { +t8_subelement_scheme_hex_c::t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const +{ SC_ABORT ("This function is not implemented for the given scheme.\n"); } void -t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) - const +t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, + const size_t num_coords, double *out_coords) const { T8_ASSERT (ref_coords != NULL); T8_ASSERT (t8_element_is_valid (elem)); - - if(!t8_element_is_subelement(elem)){ + + if (!t8_element_is_subelement (elem)) { const p8est_quadrant_t *q1 = (const p8est_quadrant_t *) elem; - /* Get the length of the quadrant */ - const p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); + /* Get the length of the quadrant */ + const p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); - for (size_t coord = 0; coord < num_coords; ++coord) { - const size_t offset = 3 * coord; - /* Compute the x, y and z coordinates of the point depending on the + for (size_t coord = 0; coord < num_coords; ++coord) { + const size_t offset = 3 * coord; + /* Compute the x, y and z coordinates of the point depending on the * reference coordinates */ - out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; - out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; - out_coords[offset + 2] = q1->z + ref_coords[offset + 2] * len; + out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; + out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; + out_coords[offset + 2] = q1->z + ref_coords[offset + 2] * len; - /* We divide the integer coordinates by the root length of the hex + /* We divide the integer coordinates by the root length of the hex * to obtain the reference coordinates. */ - out_coords[offset + 0] /= (double) P8EST_ROOT_LEN; - out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; - out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 0] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; + } } + else { + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; + p8est_quadrant_t *q1 = &phex_w_sub->p8q; + p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); + /* get location information of the given subelement */ + int location[3] = {}; + t8_element_get_location_of_subelement (elem, location); - } - else{ - t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; - p8est_quadrant_t *q1 = &phex_w_sub->p8q; - p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); - /* get location information of the given subelement */ - int location[3] = { }; - t8_element_get_location_of_subelement (elem, location); - - for (int coord = 0; coord < num_coords; ++coord) { - const size_t offset = coord * 3; - out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; - out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; - out_coords[offset + 2] = q1->z + ref_coords[offset + 2] * len; - - - //Set the apex to the center of the transition cell - if(ref_coords[0] == 1 && ref_coords[1] == 1 && ref_coords[2] == 1){ - out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); - out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); - out_coords[offset + 2] -= ref_coords[offset + 2] * (len/2); + for (int coord = 0; coord < num_coords; ++coord) { + const size_t offset = coord * 3; + out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; + out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; + out_coords[offset + 2] = q1->z + ref_coords[offset + 2] * len; + + //Set the apex to the center of the transition cell + if (ref_coords[0] == 1 && ref_coords[1] == 1 && ref_coords[2] == 1) { + out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); + out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); + out_coords[offset + 2] -= ref_coords[offset + 2] * (len / 2); } - else{ - if(location[0] == 0){ + else { + if (location[0] == 0) { //face 0 //Add the x-coordinate to the z-coordinate in order to flip the base side of the pyramid to face f0 out_coords[offset + 2] += ref_coords[offset + 0] * len; //set x-coordinate to zero out_coords[offset + 0] -= ref_coords[offset + 0] * len; } - if(location[0] == 1){ - //Add one to the z-coordinate if the x-coordinate equals zero - out_coords[offset + 2] += (1 - 1*ref_coords[offset + 0]) * len; + if (location[0] == 1) { + //Add one to the z-coordinate if the x-coordinate equals zero + out_coords[offset + 2] += (1 - 1 * ref_coords[offset + 0]) * len; //set x-coordinate to one - out_coords[offset + 0] += (1 - 1*ref_coords[offset + 0]) * len; + out_coords[offset + 0] += (1 - 1 * ref_coords[offset + 0]) * len; } - if(location[0] == 2){ - //Add one to the z-coordinate if the y-coordinate equals one + if (location[0] == 2) { + //Add one to the z-coordinate if the y-coordinate equals one out_coords[offset + 2] += (ref_coords[offset + 1]) * len; //set y-coordinate to zero - out_coords[offset + 1] -= (ref_coords[offset + 1]) * len; + out_coords[offset + 1] -= (ref_coords[offset + 1]) * len; } - if(location[0] == 3){ - //Add one to the z-coordinate if the y-coordinate equals zero - out_coords[offset + 2] += ( 1 - ref_coords[offset + 1]) * len; + if (location[0] == 3) { + //Add one to the z-coordinate if the y-coordinate equals zero + out_coords[offset + 2] += (1 - ref_coords[offset + 1]) * len; //set y-coordinate to one - out_coords[offset + 1] += (1 - 1*ref_coords[offset + 1]) * len; + out_coords[offset + 1] += (1 - 1 * ref_coords[offset + 1]) * len; } //Nothing more to do for face 4 - if(location[0] == 5){ - //Add one to the z-coordinate - out_coords[offset + 2] += len; - } - //split - if(location[1] == 1){ - if(location[0] == 0 ){ - if((location[2] & 2) == 0){ - //front - //scale the y coordinate if not zero - out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + if (location[0] == 5) { + //Add one to the z-coordinate + out_coords[offset + 2] += len; + } + //split + if (location[1] == 1) { + if (location[0] == 0) { + if ((location[2] & 2) == 0) { + //front + //scale the y coordinate if not zero + out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); } - else{ + else { //back - //scale the y coordinate if zero - out_coords[offset + 1] += (1 - ref_coords[offset + 1]) * (len/2); + //scale the y coordinate if zero + out_coords[offset + 1] += (1 - ref_coords[offset + 1]) * (len / 2); } - if((location[2] & 1) == 0){ - //bottom - //scale the z coordinate if not zero and z is not zero if the x-coordinate of ref_coords is not zero. - out_coords[offset + 2] -= (ref_coords[offset + 0]) * (len/2); + if ((location[2] & 1) == 0) { + //bottom + //scale the z coordinate if not zero and z is not zero if the x-coordinate of ref_coords is not zero. + out_coords[offset + 2] -= (ref_coords[offset + 0]) * (len / 2); } - else{ + else { //up - //scale the z coordinate if zero - out_coords[offset + 2] += (1 - 1*ref_coords[offset + 0]) * (len/2); + //scale the z coordinate if zero + out_coords[offset + 2] += (1 - 1 * ref_coords[offset + 0]) * (len / 2); } } - if(location[0] == 1 ){ - if((location[2] & 2) == 0){ - //front - //scale the y coordinate if not zero - out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + if (location[0] == 1) { + if ((location[2] & 2) == 0) { + //front + //scale the y coordinate if not zero + out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); } - else{ + else { //back - //scale the y coordinate if zero - out_coords[offset + 1] += (1 - ref_coords[offset + 1]) * (len/2); + //scale the y coordinate if zero + out_coords[offset + 1] += (1 - ref_coords[offset + 1]) * (len / 2); } - if((location[2] & 1) == 0){ - //bottom - //scale the z coordinate if not zero and z is not zero if the x-coordinate of ref_coords is zero. - out_coords[offset + 2] -= (1 - ref_coords[offset + 0]) * (len/2); + if ((location[2] & 1) == 0) { + //bottom + //scale the z coordinate if not zero and z is not zero if the x-coordinate of ref_coords is zero. + out_coords[offset + 2] -= (1 - ref_coords[offset + 0]) * (len / 2); } - else{ + else { //up - //scale the z coordinate if zero - out_coords[offset + 2] += (ref_coords[offset + 0]) * (len/2); + //scale the z coordinate if zero + out_coords[offset + 2] += (ref_coords[offset + 0]) * (len / 2); } } - if(location[0] == 2 ){ - if((location[2] & 4) == 0){ - //left - //scale the x coordinate if not zero - out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + if (location[0] == 2) { + if ((location[2] & 4) == 0) { + //left + //scale the x coordinate if not zero + out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); } - else{ - //right - //scale the x coordinate if zero - out_coords[offset + 0] += (1 - ref_coords[offset + 0] )* (len/2); + else { + //right + //scale the x coordinate if zero + out_coords[offset + 0] += (1 - ref_coords[offset + 0]) * (len / 2); } - if((location[2] & 1) == 0){ - //bottom - //scale the z coordinate if not zero - out_coords[offset + 2] -= ref_coords[offset + 1] * (len/2); + if ((location[2] & 1) == 0) { + //bottom + //scale the z coordinate if not zero + out_coords[offset + 2] -= ref_coords[offset + 1] * (len / 2); } - else{ + else { //up - //scale the z coordinate if zero - out_coords[offset + 2] += (1 - ref_coords[offset + 1] )* (len/2); - + //scale the z coordinate if zero + out_coords[offset + 2] += (1 - ref_coords[offset + 1]) * (len / 2); } } - if(location[0] == 3){ - if((location[2] & 4) == 0){ - //left - //scale the x coordinate if not zero - out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + if (location[0] == 3) { + if ((location[2] & 4) == 0) { + //left + //scale the x coordinate if not zero + out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); } - else{ - //right - //scale the x coordinate if zero - out_coords[offset + 0] += (1 - ref_coords[offset + 0] )* (len/2); + else { + //right + //scale the x coordinate if zero + out_coords[offset + 0] += (1 - ref_coords[offset + 0]) * (len / 2); } - if((location[2] & 1) == 0){ - //bottom - //scale the z coordinate if not zero - out_coords[offset + 2] -= (1 - ref_coords[offset + 1]) * (len/2); + if ((location[2] & 1) == 0) { + //bottom + //scale the z coordinate if not zero + out_coords[offset + 2] -= (1 - ref_coords[offset + 1]) * (len / 2); } - else{ + else { //up - //scale the z coordinate if zero - out_coords[offset + 2] += (ref_coords[offset + 1] )* (len/2); + //scale the z coordinate if zero + out_coords[offset + 2] += (ref_coords[offset + 1]) * (len / 2); } } - if(location[0] == 4){ - if((location[2] & 4) == 0){ - //left - //scale the x coordinate if not zero - out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + if (location[0] == 4) { + if ((location[2] & 4) == 0) { + //left + //scale the x coordinate if not zero + out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); } - else{ - //right - //scale the x coordinate if zero - out_coords[offset + 0] += (1 - ref_coords[offset + 0] )* (len/2); + else { + //right + //scale the x coordinate if zero + out_coords[offset + 0] += (1 - ref_coords[offset + 0]) * (len / 2); } - if((location[2] & 2) == 0){ - //front - //scale the y coordinate if not zero - out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + if ((location[2] & 2) == 0) { + //front + //scale the y coordinate if not zero + out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); } - else{ + else { //back - //scale the y coordinate if zero - out_coords[offset + 1] += (1 - 1*ref_coords[offset + 1]) * (len/2); + //scale the y coordinate if zero + out_coords[offset + 1] += (1 - 1 * ref_coords[offset + 1]) * (len / 2); } - } - if(location[0] == 5){ - if((location[2] & 4) == 0){ - //left - //scale the x coordinate if not zero - out_coords[offset + 0] -= ref_coords[offset + 0] * (len/2); + if (location[0] == 5) { + if ((location[2] & 4) == 0) { + //left + //scale the x coordinate if not zero + out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); } - else{ - //right - //scale the x coordinate if zero - out_coords[offset + 0] += (1 - ref_coords[offset + 0] )* (len/2); + else { + //right + //scale the x coordinate if zero + out_coords[offset + 0] += (1 - ref_coords[offset + 0]) * (len / 2); } - if((location[2] & 2) == 0){ - //front - //scale the y coordinate if not zero - out_coords[offset + 1] -= ref_coords[offset + 1] * (len/2); + if ((location[2] & 2) == 0) { + //front + //scale the y coordinate if not zero + out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); } - else{ + else { //back - //scale the y coordinate if zero - out_coords[offset + 1] += (1 - 1*ref_coords[offset + 1]) * (len/2); + //scale the y coordinate if zero + out_coords[offset + 1] += (1 - 1 * ref_coords[offset + 1]) * (len / 2); } - } -} } - - - out_coords[offset + 0] /= (double) P8EST_ROOT_LEN; - out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; - out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; - } - - - } - - - - + out_coords[offset + 0] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; + out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; + } } - - +} void -t8_subelement_scheme_hex_c::t8_element_vertex_reference_coords (const - t8_element_t - *t, - int vertex, - double - coords[]) - const -{ - int coords_int[3] = { }; +t8_subelement_scheme_hex_c::t8_element_vertex_reference_coords (const t8_element_t *t, int vertex, + double coords[]) const +{ + int coords_int[3] = {}; t8_element_vertex_coords (t, vertex, coords_int); /* We divide the integer coordinates by the root length of the hex @@ -2165,18 +1935,15 @@ t8_subelement_scheme_hex_c::t8_element_vertex_reference_coords (const } void -t8_subelement_scheme_hex_c::t8_element_vertex_coords (const t8_element_t - *elem, int vertex, - int coords[]) const +t8_subelement_scheme_hex_c::t8_element_vertex_coords (const t8_element_t *elem, int vertex, int coords[]) const { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; const p8est_quadrant_t *q1 = &phex_w_sub->p8q; T8_ASSERT (t8_element_is_valid (elem)); if (!t8_element_is_subelement (elem)) { - int len; + int len; //T8_ASSERT (0 <= vertex && vertex < 8); /* Get the length of the quadrant */ @@ -2185,332 +1952,318 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords (const t8_element_t * vertex number */ coords[0] = q1->x + (vertex & 1 ? 1 : 0) * len; coords[1] = q1->y + (vertex & 2 ? 1 : 0) * len; - coords[2] = q1->z + (vertex & 4 ? 1 : 0) * len; + coords[2] = q1->z + (vertex & 4 ? 1 : 0) * len; } else { t8_element_vertex_coords_of_subelement (elem, vertex, coords); } - } void -t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const - t8_element_t - *elem, - int - vertex, - int - coords[]) - const -{ - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; +t8_subelement_scheme_hex_c::t8_element_vertex_coords_of_subelement (const t8_element_t *elem, int vertex, + int coords[]) const +{ + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; const p8est_quadrant_t *q1 = &phex_w_sub->p8q; - - int len; + + int len; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_subelement (elem)); - T8_ASSERT (vertex >= 0 && vertex < T8_HEX_SUBELEMENT_FACES); /* all subelements are pyramids so T8_HEX_SUBELEMENT_FACES = 5 */ + T8_ASSERT (vertex >= 0 + && vertex < T8_HEX_SUBELEMENT_FACES); /* all subelements are pyramids so T8_HEX_SUBELEMENT_FACES = 5 */ /* get the length of the current quadrant */ len = P8EST_QUADRANT_LEN (q1->level); - /* get location information of the given subelement */ - int location[3] = { }; + int location[3] = {}; t8_element_get_location_of_subelement (elem, location); /* the face number, the subelement is adjacent to */ - int face_number = location[0]; + int face_number = location[0]; /* = 1, if the adjacent face is split and = 0, if not */ - int split = location[1]; + int split = location[1]; /* subelement_id type. First bit (left) = 1 if right, = 0 if left, second bit( middle) = 1 if back , = 0 if front, third bit (right) = 0 if up and is = 1 if down * second bit front = 0, back = 1, third bit 0 = bottom 1 = up. For example: 110 stands for right and back (so only hex face f_4 and f_5 are possible.) */ - int sub_face_id = location[2]; + int sub_face_id = location[2]; /* Check, whether the get_location function provides meaningful location data */ - T8_ASSERT ((face_number >=0) && face_number <= 5); + T8_ASSERT ((face_number >= 0) && face_number <= 5); coords[0] = q1->x; coords[1] = q1->y; coords[2] = q1->z; - - switch(vertex){ - - case 4: //vertex 4 always equals the center of the hexahedron - coords[0] += (len / 2); - coords[1] += (len / 2); - coords[2] += (len / 2); + switch (vertex) { + + case 4: //vertex 4 always equals the center of the hexahedron + coords[0] += (len / 2); + coords[1] += (len / 2); + coords[2] += (len / 2); break; - case 0: - if(split == 0){ //not split - //for face numbers 0,2 and 4 nothing happens - if(face_number == 1){ + case 0: + if (split == 0) { //not split + //for face numbers 0,2 and 4 nothing happens + if (face_number == 1) { + coords[0] += len; + } + if (face_number == 3) { + coords[1] += len; + } + if (face_number == 5) { + coords[2] += len; + } + } + /* ----------- face 0 + 1 (split) --------------------*/ + else { + if ((face_number == 0) || (face_number == 1)) { + if ((sub_face_id & 1) != 0) { // up + coords[2] += (len / 2); + } + if ((sub_face_id & 2) != 0) { // back + coords[1] += (len / 2); + } + + if (face_number == 1) { coords[0] += len; } - if(face_number == 3){ + } + /* ----------- face 2 + 3 (split) --------------------*/ + if ((face_number == 2) || (face_number == 3)) { + if ((sub_face_id & 1) != 0) { // up + coords[2] += (len / 2); + } + if ((sub_face_id & 4) != 0) { // right + coords[0] += (len / 2); + } + if (face_number == 3) { coords[1] += len; } - if(face_number == 5){ + } + /* ----------- face 4 + 5 (split) --------------------*/ + if ((face_number == 4) || (face_number == 5)) { + if ((sub_face_id & 2) != 0) { // back + coords[1] += len / 2; + } + if ((sub_face_id & 4) != 0) { // right + coords[0] += len / 2; + } + if (face_number == 5) { coords[2] += len; } } -/* ----------- face 0 + 1 (split) --------------------*/ - else{ - if((face_number == 0) || (face_number == 1)){ - if((sub_face_id & 1)!= 0){ // up - coords[2] += (len / 2); - } - if((sub_face_id & 2) != 0 ){ // back - coords[1] += (len / 2); - } - - if(face_number == 1){ + } + break; + + case 1: + if (split == 0) { + if ((face_number == 0) || (face_number == 1 || (face_number == 3))) { + coords[1] += len; + } + if (face_number > 0) { + coords[0] += len; + } + if (face_number == 5) { + coords[2] += len; + } + } + /* ----------- face 0 + 1 (split) --------------------*/ + else { + if ((face_number == 0) || (face_number == 1)) { + if ((sub_face_id & 1) != 0) { // up + coords[2] += len / 2; + } + if ((sub_face_id & 2) != 0) { // back + coords[1] += len; + } + else if ((sub_face_id & 2) == 0) { //front + coords[1] += len / 2; + } + + if (face_number == 1) { coords[0] += len; } + } + /* ----------- face 2 + 3 (split) --------------------*/ + if ((face_number == 2) || (face_number == 3)) { + if ((sub_face_id & 1) != 0) { // up + coords[2] += len / 2; } -/* ----------- face 2 + 3 (split) --------------------*/ - if((face_number == 2) || (face_number == 3)){ - if((sub_face_id & 1) != 0){ // up - coords[2] += (len / 2); - } - if((sub_face_id & 4) != 0 ){ // right - coords[0] += (len / 2); - } - if(face_number == 3){ - coords[1] += len; - } + if ((sub_face_id & 4) != 0) { // right + coords[0] += len; } -/* ----------- face 4 + 5 (split) --------------------*/ - if((face_number == 4) || (face_number == 5)){ - if((sub_face_id & 2) != 0){ // back - coords[1] += len / 2; - } - if((sub_face_id & 4) != 0 ){ // right - coords[0] += len / 2; - } - if(face_number == 5){ - coords[2] += len; - } + else if ((sub_face_id & 4) == 0) { //left + coords[0] += len / 2; + } + if (face_number == 3) { + coords[1] += len; } } - break; - case 1: - if(split == 0){ - if((face_number == 0) || (face_number == 1 || (face_number == 3))){ - coords[1] += len; + /* ----------- face 4 + 5 (split) --------------------*/ + if ((face_number == 4) || (face_number == 5)) { + if ((sub_face_id & 2) != 0) { // back + coords[1] += (len / 2); } - if(face_number > 0){ + if ((sub_face_id & 4) != 0) { // right coords[0] += len; } - if(face_number == 5){ + else if ((sub_face_id & 4) == 0) { //left + coords[0] += (len / 2); + } + if (face_number == 5) { coords[2] += len; } } -/* ----------- face 0 + 1 (split) --------------------*/ - else{ - if((face_number == 0) || (face_number == 1)){ - if((sub_face_id & 1) != 0){ // up - coords[2] += len / 2; - } - if((sub_face_id & 2) != 0 ){ // back - coords[1] += len; - - } - else if((sub_face_id & 2) == 0) { //front - coords[1] += len / 2; - } - - if(face_number == 1){ - coords[0] += len; - } + } + break; + case 2: + if (split == 0) { + if (face_number != 4) { + coords[2] += len; + } + if (face_number == 1) { + coords[0] += len; + } + if (face_number > 2) { + coords[1] += len; + } + } + /* ----------- face 0 + 1 (split) --------------------*/ + else { + if ((face_number == 0) || (face_number == 1)) { + if ((sub_face_id & 2) != 0) { // back + coords[1] += len / 2; } -/* ----------- face 2 + 3 (split) --------------------*/ - if((face_number == 2) || (face_number == 3)){ - if((sub_face_id & 1) != 0){ // up - coords[2] += len / 2; - } - if((sub_face_id & 4) != 0 ){ // right - coords[0] += len; - } - else if((sub_face_id & 4) == 0){ //left - coords[0] += len / 2; - } - if(face_number == 3){ - coords[1] += len; - } - } - -/* ----------- face 4 + 5 (split) --------------------*/ - if((face_number == 4) || (face_number == 5)){ - if((sub_face_id & 2) != 0){ // back - coords[1] += (len / 2); - } - if((sub_face_id & 4) != 0){ // right - coords[0] += len; - } - else if ((sub_face_id & 4) == 0){ //left - coords[0] += (len / 2); - } - if(face_number == 5){ - coords[2] += len; - } + if ((sub_face_id & 1) != 0) { // up + coords[2] += len; + } + else if ((sub_face_id & 1) == 0) { //bottom + coords[2] += len / 2; + } + if (face_number == 1) { + coords[0] += len; } } - break; - case 2: - if(split == 0){ - if(face_number != 4){ + + /* ----------- face 2 + 3 (split) --------------------*/ + if ((face_number == 2) || (face_number == 3)) { + if ((sub_face_id & 1) != 0) { // up coords[2] += len; } - if(face_number == 1){ - coords[0] += len; + else if ((sub_face_id & 1) == 0) { + coords[2] += len / 2; } - if(face_number > 2){ + if ((sub_face_id & 4) != 0) { // right + coords[0] += len / 2; + } + if (face_number == 3) { coords[1] += len; } } -/* ----------- face 0 + 1 (split) --------------------*/ - else{ - if((face_number == 0) || (face_number == 1)){ - if((sub_face_id & 2) != 0){ // back - coords[1] += len / 2; - } - if((sub_face_id & 1) != 0 ){ // up - coords[2] += len; - } - else if((sub_face_id & 1) == 0){ //bottom - coords[2] += len / 2; - } - if(face_number == 1){ - coords[0] += len; - } - } - -/* ----------- face 2 + 3 (split) --------------------*/ - if((face_number == 2) || (face_number == 3)){ - if((sub_face_id & 1) != 0){ // up - coords[2] += len; - } - else if((sub_face_id & 1) == 0){ - coords[2] += len / 2; - } - if((sub_face_id & 4) != 0 ){ // right - coords[0] += len / 2; - } - if(face_number == 3){ - coords[1] += len; - } - } -/* ----------- face 4 + 5 (split) --------------------*/ + /* ----------- face 4 + 5 (split) --------------------*/ - if((face_number == 4) || (face_number == 5)){ - if((sub_face_id & 2) != 0){ // back - coords[1] += len; - } - else if((sub_face_id & 2) == 0){ //front - coords[1] += len / 2; - } - if((sub_face_id & 4) != 0){ // right - coords[0] += len / 2; - } - if(face_number == 5){ - coords[2] += len; - } + if ((face_number == 4) || (face_number == 5)) { + if ((sub_face_id & 2) != 0) { // back + coords[1] += len; + } + else if ((sub_face_id & 2) == 0) { //front + coords[1] += len / 2; + } + if ((sub_face_id & 4) != 0) { // right + coords[0] += len / 2; + } + if (face_number == 5) { + coords[2] += len; } } + } - break; - case 3: - if(split == 0){ - if(face_number != 2){ + break; + case 3: + if (split == 0) { + if (face_number != 2) { + coords[1] += len; + } + if (face_number != 4) { + coords[2] += len; + } + if (face_number > 0) { + coords[0] += len; + } + } + /* ----------- face 0 + 1 (split) --------------------*/ + else { + if ((face_number == 0) || (face_number == 1)) { + if ((sub_face_id & 2) != 0) { // back coords[1] += len; } - if(face_number != 4){ + else if ((sub_face_id & 2) == 0) { //front + coords[1] += len / 2; + } + if ((sub_face_id & 1) != 0) { // up coords[2] += len; } - if(face_number > 0){ + else if ((sub_face_id & 1) == 0) { // bottom + coords[2] += len / 2; + } + if (face_number == 1) { coords[0] += len; } - } - /* ----------- face 0 + 1 (split) --------------------*/ - else{ - if((face_number == 0) || (face_number == 1)){ - if((sub_face_id & 2) != 0){ // back - coords[1] += len; - } - else if((sub_face_id & 2) == 0){ //front - coords[1] += len / 2; - } - if((sub_face_id & 1) != 0 ){ // up - coords[2] += len; - } - else if((sub_face_id & 1) == 0 ){ // bottom - coords[2] += len / 2; - } - if( face_number == 1){ - coords[0] += len; - } + } + /* ----------- face 2 + 3 (split) --------------------*/ + if ((face_number == 2) || (face_number == 3)) { + if ((sub_face_id & 1) != 0) { // up + coords[2] += len; } -/* ----------- face 2 + 3 (split) --------------------*/ - if((face_number == 2) || (face_number == 3)){ - if((sub_face_id & 1) != 0){ // up - coords[2] += len; - } - else if((sub_face_id & 1) == 0){ - coords[2] += len / 2; - } - if((sub_face_id & 4) != 0 ){ // right - coords[0] += len; - } - else if((sub_face_id & 4) == 0 ){ // left - coords[0] += len / 2; - } - if(face_number == 3){ - coords[1] += len; - } + else if ((sub_face_id & 1) == 0) { + coords[2] += len / 2; } + if ((sub_face_id & 4) != 0) { // right + coords[0] += len; + } + else if ((sub_face_id & 4) == 0) { // left + coords[0] += len / 2; + } + if (face_number == 3) { + coords[1] += len; + } + } -/* ----------- face 4 + 5 (split) --------------------*/ - if((face_number == 4) || (face_number == 5)){ - if((sub_face_id & 2) != 0){ // back + /* ----------- face 4 + 5 (split) --------------------*/ + if ((face_number == 4) || (face_number == 5)) { + if ((sub_face_id & 2) != 0) { // back - coords[1] += len; - } - else if((sub_face_id & 2) == 0){ //front - coords[1] += len / 2; - } - if((sub_face_id & 4) != 0 ){ // right - coords[0] += len; - } - else if((sub_face_id & 4) == 0){ // left - coords[0] += len / 2; - } - if( face_number == 5){ - coords[2] += len; - } + coords[1] += len; + } + else if ((sub_face_id & 2) == 0) { //front + coords[1] += len / 2; + } + if ((sub_face_id & 4) != 0) { // right + coords[0] += len; + } + else if ((sub_face_id & 4) == 0) { // left + coords[0] += len / 2; + } + if (face_number == 5) { + coords[2] += len; } } + } - break; - } - -} + break; + } +} void -t8_subelement_scheme_hex_c::t8_element_to_transition_cell (const t8_element_t - *elem, int transition_type, - t8_element_t *c[]) +t8_subelement_scheme_hex_c::t8_element_to_transition_cell (const t8_element_t *elem, int transition_type, + t8_element_t *c[]) { - const t8_hex_with_subelements *phex_w_sub_elem = - (const t8_hex_with_subelements *) elem; - t8_hex_with_subelements **phex_w_sub_subelement = - (t8_hex_with_subelements **) c; + const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + t8_hex_with_subelements **phex_w_sub_subelement = (t8_hex_with_subelements **) c; const p8est_quadrant_t *q = &phex_w_sub_elem->p8q; @@ -2519,12 +2272,11 @@ t8_subelement_scheme_hex_c::t8_element_to_transition_cell (const t8_element_t T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (transition_type >= 0 && transition_type <= T8_SUB_HEX_MAX_TRANSITION_TYPE); - int num_subelements = - t8_element_get_number_of_subelements (transition_type); + int num_subelements = t8_element_get_number_of_subelements (transition_type); #ifdef T8_ENABLE_DEBUG { - int j; + int j; for (j = 0; j < num_subelements; j++) { T8_ASSERT (t8_element_is_valid (c[j])); } @@ -2532,12 +2284,12 @@ t8_subelement_scheme_hex_c::t8_element_to_transition_cell (const t8_element_t #endif /* get the length of a children-quadrant */ - const int8_t level = (int8_t) (q->level); + const int8_t level = (int8_t) (q->level); T8_ASSERT (p8est_quadrant_is_extended (q)); T8_ASSERT (q->level < P8EST_OLD_QMAXLEVEL); - int sub_id_counter = 0; + int sub_id_counter = 0; for (sub_id_counter = 0; sub_id_counter < num_subelements; sub_id_counter++) { phex_w_sub_subelement[sub_id_counter]->p8q.x = q->x; phex_w_sub_subelement[sub_id_counter]->p8q.y = q->y; @@ -2548,40 +2300,33 @@ t8_subelement_scheme_hex_c::t8_element_to_transition_cell (const t8_element_t phex_w_sub_subelement[sub_id_counter]->subelement_id = sub_id_counter; T8_ASSERT (t8_element_is_valid (c[sub_id_counter])); - } } int -t8_subelement_scheme_hex_c::t8_element_get_number_of_subelements (int - transition_type) - const +t8_subelement_scheme_hex_c::t8_element_get_number_of_subelements (int transition_type) const { /* we could return 0 for transition type 0 but we will assert this case for safety reasons */ T8_ASSERT (transition_type != 0); /* consider transition_type 16 = 010000 in base two -> there are 6 + (1)*3 = 9 subelements */ - int num_hanging_faces = 0; - int ichild; - for (ichild = 0; ichild < P8EST_FACES; ichild++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ + int num_hanging_faces = 0; + int ichild; + for ( + ichild = 0; ichild < P8EST_FACES; + ichild++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ num_hanging_faces += (transition_type & (1 << ichild)) >> ichild; } /* The number of subelements equals the number of neighbours: */ //t8_productionf("number subs %i\n",P8EST_FACES + num_hanging_faces*3); - return P8EST_FACES + num_hanging_faces*3; + return P8EST_FACES + num_hanging_faces * 3; } void -t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const - t8_element_t - *elem, - int - location - []) const +t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const t8_element_t *elem, int location[]) const { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; /* this function only works for subelements */ T8_ASSERT (t8_element_is_subelement (elem)); @@ -2612,41 +2357,39 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const * /* 1) convert the transition type from a decimal to a binary representation */ - int type = phex_w_sub->transition_type; - int binary_array[P8EST_FACES] = { }; + int type = phex_w_sub->transition_type; + int binary_array[P8EST_FACES] = {}; - int iface; + int iface; - /* We need an array with 6 elements to store all subelement types of the hex scheme from 1 to 63 ({0, 0, 0, 0, 0, 1} to {1, 1, 1, 1, 1, 1}) */ - for (iface = 0; iface < P8EST_FACES; iface++) { + /* We need an array with 6 elements to store all subelement types of the hex scheme from 1 to 63 ({0, 0, 0, 0, 0, 1} to {1, 1, 1, 1, 1, 1}) */ + for (iface = 0; iface < P8EST_FACES; iface++) { binary_array[(P8EST_FACES - 1) - iface] = (type & (1 << iface)) >> iface; - } /* we now got a binary representation of the transition type, bitwise stored in an array */ + } /* we now got a binary representation of the transition type, bitwise stored in an array */ /* 3) use the rearranged binary representation, and the sub_id to determine the location of the subelement and store these information in an array */ /* 3.1) location[0] -> the face_number, the subelement is adjacent to */ /* 3.2) location[1] -> if the face is split or not */ /* 3.3) location[2] -> if the subelement is the left/right, front/back or bottom/up Same idea as with the transition type: first bit 0 = left, 1 = right, * second bit front = 0, back = 1, third bit 0 = bottom 1 = up. For example: 110 stands for right and back (so only hex face f_4 and f_5 are possible.) */ - T8_ASSERT (phex_w_sub->subelement_id < - t8_element_get_number_of_subelements - (phex_w_sub->transition_type)); + T8_ASSERT (phex_w_sub->subelement_id < t8_element_get_number_of_subelements (phex_w_sub->transition_type)); - int sub_id = phex_w_sub->subelement_id; + int sub_id = phex_w_sub->subelement_id; - int sub_face_id_array[3] = {0,0,0}; - int sub_face_id = 0; - int face_number = -1; - int split; + int sub_face_id_array[3] = { 0, 0, 0 }; + int sub_face_id = 0; + int face_number = -1; + int split; - int cum_neigh_array[P8EST_FACES] = { }; + int cum_neigh_array[P8EST_FACES] = {}; /* construct a cumulative array of the number of neighbors from face 0 to face 5 */ - cum_neigh_array[0] = binary_array[0]*3 + 1; - cum_neigh_array[1] = cum_neigh_array[0] + binary_array[1]*3 + 1; - cum_neigh_array[2] = cum_neigh_array[1] + binary_array[2]*3 + 1; - cum_neigh_array[3] = cum_neigh_array[2] + binary_array[3]*3 + 1; - cum_neigh_array[4] = cum_neigh_array[3] + binary_array[4]*3 + 1; - cum_neigh_array[5] = cum_neigh_array[4] + binary_array[5]*3 + 1; + cum_neigh_array[0] = binary_array[0] * 3 + 1; + cum_neigh_array[1] = cum_neigh_array[0] + binary_array[1] * 3 + 1; + cum_neigh_array[2] = cum_neigh_array[1] + binary_array[2] * 3 + 1; + cum_neigh_array[3] = cum_neigh_array[2] + binary_array[3] * 3 + 1; + cum_neigh_array[4] = cum_neigh_array[3] + binary_array[4] * 3 + 1; + cum_neigh_array[5] = cum_neigh_array[4] + binary_array[5] * 3 + 1; /* 3.1) we can use the cumulative array to determine the face number of the given subelement */ if (sub_id < cum_neigh_array[0]) { @@ -2654,80 +2397,76 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const } else { for (iface = 0; iface < P8EST_FACES - 1; ++iface) { - if (sub_id >= cum_neigh_array[iface] - && sub_id < cum_neigh_array[iface + 1]) { + if (sub_id >= cum_neigh_array[iface] && sub_id < cum_neigh_array[iface + 1]) { face_number = iface + 1; break; } } } - + /* make sure that a face_number has been found */ T8_ASSERT (face_number >= 0); /* 3.2) determine, whether the face is split or not */ if (binary_array[face_number] == 0) { - split = 0; /* the face is not split */ + split = 0; /* the face is not split */ } else { - split = 1; /* the face is split */ + split = 1; /* the face is split */ } - if(split == 1){ + if (split == 1) { /* 3.3) determine, whether the subelement is the left/right, front/back or bottom/up subelement at the face */ - //First left/ right (only for face number 2, 3, 4, 5) - if( face_number > 1){ - if (((sub_id + 1) == cum_neigh_array[face_number] ) || ((sub_id + 3) == cum_neigh_array[face_number])) { - sub_face_id_array[0] = 1; /* right*/ + //First left/ right (only for face number 2, 3, 4, 5) + if (face_number > 1) { + if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 3) == cum_neigh_array[face_number])) { + sub_face_id_array[0] = 1; /* right*/ + } + else if (((sub_id + 2) == cum_neigh_array[face_number]) || ((sub_id + 4) == cum_neigh_array[face_number])) { + sub_face_id_array[0] = 0; /* left */ + } } - else if (((sub_id + 2) == cum_neigh_array[face_number] ) || ((sub_id + 4) == cum_neigh_array[face_number])){ - sub_face_id_array[0] = 0; /* left */ - } - } - //Second check front or back (only for face numbers 0, 1, 4, 5) - if( face_number <= 1 ){ - if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 3) == cum_neigh_array[face_number])) { - sub_face_id_array[1] = 1; /* back subelement */ + //Second check front or back (only for face numbers 0, 1, 4, 5) + if (face_number <= 1) { + if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 3) == cum_neigh_array[face_number])) { + sub_face_id_array[1] = 1; /* back subelement */ + } + else if (((sub_id + 2) == cum_neigh_array[face_number]) || ((sub_id + 4) == cum_neigh_array[face_number])) { + sub_face_id_array[1] = 0; /* front subelement */ + } } - else if (((sub_id + 2) == cum_neigh_array[face_number]) || ((sub_id + 4) == cum_neigh_array[face_number])){ - sub_face_id_array[1] = 0; /* front subelement */ - } - } - else if( face_number >= 4 ){ - if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 2) == cum_neigh_array[face_number])) { - sub_face_id_array[1] = 1; /* back subelement */ + else if (face_number >= 4) { + if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 2) == cum_neigh_array[face_number])) { + sub_face_id_array[1] = 1; /* back subelement */ + } + else if (((sub_id + 3) == cum_neigh_array[face_number]) || ((sub_id + 4) == cum_neigh_array[face_number])) { + sub_face_id_array[1] = 0; /* front subelement */ + } } - else if(((sub_id + 3) == cum_neigh_array[face_number]) || ((sub_id + 4) == cum_neigh_array[face_number])){ - sub_face_id_array[1] = 0; /* front subelement */ - } - } - //Third check up or down (only for face numbers 0, 1, 2, 3) - if( face_number < 4 ){ - if (((sub_id + 2) == cum_neigh_array[face_number] ) || ((sub_id + 1) == cum_neigh_array[face_number] )) { - sub_face_id_array[2] = 1; /* up subelement */ + //Third check up or down (only for face numbers 0, 1, 2, 3) + if (face_number < 4) { + if (((sub_id + 2) == cum_neigh_array[face_number]) || ((sub_id + 1) == cum_neigh_array[face_number])) { + sub_face_id_array[2] = 1; /* up subelement */ + } + else if (((sub_id + 3) == cum_neigh_array[face_number]) || ((sub_id + 4) == cum_neigh_array[face_number])) { + sub_face_id_array[2] = 0; /* bottom subelement */ + } } - else if (((sub_id + 3) == cum_neigh_array[face_number] ) || ((sub_id + 4) == cum_neigh_array[face_number] )){ - sub_face_id_array[2] = 0; /* bottom subelement */ - } - } - //Calculate the sub_face_id out of the sub_face_id_array - for(int i = 0; i < 3; i++ ){ - if( sub_face_id_array[i] == 1){ - sub_face_id += std::pow(2, 2-i); + //Calculate the sub_face_id out of the sub_face_id_array + for (int i = 0; i < 3; i++) { + if (sub_face_id_array[i] == 1) { + sub_face_id += std::pow (2, 2 - i); + } } } - } location[0] = face_number; location[1] = split; location[2] = sub_face_id; - - } void -t8_subelement_scheme_hex_c::t8_element_reset_subelement_values (t8_element * - elem) const +t8_subelement_scheme_hex_c::t8_element_reset_subelement_values (t8_element *elem) const { t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; @@ -2736,28 +2475,19 @@ t8_subelement_scheme_hex_c::t8_element_reset_subelement_values (t8_element * } void -t8_subelement_scheme_hex_c::t8_element_copy_subelement_values (const - t8_element * - source, - t8_element * - dest) const -{ - const t8_hex_with_subelements *phex_w_sub_source = - (const t8_hex_with_subelements *) source; - t8_hex_with_subelements *phex_w_sub_dest = - (t8_hex_with_subelements *) dest; - // phex_w_sub_dest->transition_type = phex_w_sub_source->transition_type; +t8_subelement_scheme_hex_c::t8_element_copy_subelement_values (const t8_element *source, t8_element *dest) const +{ + const t8_hex_with_subelements *phex_w_sub_source = (const t8_hex_with_subelements *) source; + t8_hex_with_subelements *phex_w_sub_dest = (t8_hex_with_subelements *) dest; + // phex_w_sub_dest->transition_type = phex_w_sub_source->transition_type; phex_w_sub_dest->transition_type = phex_w_sub_source->transition_type; phex_w_sub_dest->subelement_id = phex_w_sub_source->subelement_id; } int -t8_subelement_scheme_hex_c::t8_element_is_subelement (const - t8_element * - elem) const +t8_subelement_scheme_hex_c::t8_element_is_subelement (const t8_element *elem) const { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; T8_ASSERT (phex_w_sub->transition_type >= 0); @@ -2768,22 +2498,18 @@ t8_subelement_scheme_hex_c::t8_element_is_subelement (const } int -t8_subelement_scheme_hex_c::t8_element_get_transition_type (const - t8_element * - elem) +t8_subelement_scheme_hex_c::t8_element_get_transition_type (const t8_element *elem) { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; return phex_w_sub->transition_type; } int -t8_subelement_scheme_hex_c::t8_element_get_subelement_id (const t8_element * elem) const +t8_subelement_scheme_hex_c::t8_element_get_subelement_id (const t8_element *elem) const { T8_ASSERT (t8_element_is_valid (elem)); - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; return phex_w_sub->subelement_id; } @@ -2792,8 +2518,7 @@ t8_element_shape_t t8_subelement_scheme_hex_c::t8_element_shape (const t8_element_t *elem) const { T8_ASSERT (t8_element_is_valid (elem)); - return (t8_element_is_subelement (elem) ? T8_ECLASS_PYRAMID : - T8_ECLASS_HEX); + return (t8_element_is_subelement (elem) ? T8_ECLASS_PYRAMID : T8_ECLASS_HEX); } int @@ -2801,13 +2526,13 @@ t8_subelement_scheme_hex_c::t8_element_num_corners (const t8_element_t *elem) co { T8_ASSERT (t8_element_is_valid (elem)); - return (t8_element_is_subelement (elem) ? T8_HEX_SUBELEMENT_FACES : - 8); + return (t8_element_is_subelement (elem) ? T8_HEX_SUBELEMENT_FACES : 8); } int -t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell - (const t8_element_t *elem, const t8_element_t *pseudo_neigh, int elem_face) +t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, + const t8_element_t *pseudo_neigh, + int elem_face) { /* In this function, we assume pseudo_neigh to be a random subelement of a transition cell that includes * the real neighbor of elem at face elem_face. This function will output the subelement_id of the real neighbor of elem. */ @@ -2815,30 +2540,24 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell T8_ASSERT (t8_element_is_valid (pseudo_neigh)); /* we expect neigh to be a element in a transition cell, thus to be a subelement */ T8_ASSERT (t8_element_is_subelement (pseudo_neigh)); -//Case 1: the neighbor is ab sibling of elem --> function t8_element_get_sibling_neighbor_in_transition_cell -//Thus, we expect elem_face = 4 + //Case 1: the neighbor is ab sibling of elem --> function t8_element_get_sibling_neighbor_in_transition_cell + //Thus, we expect elem_face = 4 T8_ASSERT (elem_face == 4); - const t8_hex_with_subelements * - phex_w_sub_elem = (const t8_hex_with_subelements *) elem; - const t8_hex_with_subelements * - phex_w_sub_pseudo_neigh = - (const t8_hex_with_subelements *) pseudo_neigh; + const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub_pseudo_neigh = (const t8_hex_with_subelements *) pseudo_neigh; // t8_debugf("\n~~~~~~~~~~~Into find neighbor in transition cell ~~~~~~~~~~~~~~~\n"); /* In the following, all possible neighbor configurations are defined, such that subelement neighbors can be * identified in LFN_transitioned. */ - - /* Below are the cases in which the neighbor is no sibling. * The idea is to fill a location array with the desired properties of the real neighbor. * Together with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ /* get the location of elem */ - int - location_elem[3] = { }; /* {face, is_split, number of subelement at face} */ - t8_element_get_location_of_subelement (elem, location_elem); - //Case 2: The element is a subelement and we are looking for a face neighbor at face 4. - if (t8_element_is_subelement(elem)) { + int location_elem[3] = {}; /* {face, is_split, number of subelement at face} */ + t8_element_get_location_of_subelement (elem, location_elem); + //Case 2: The element is a subelement and we are looking for a face neighbor at face 4. + if (t8_element_is_subelement (elem)) { /* In this case, we have the following examplary situation in the 2D quad case: * @@ -2856,68 +2575,63 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell * We are searching for the subelement id of the real neighbor neigh. * Note that both transition cells can have different levels. */ - /* Initialize the location array of the real neighbor. */ - int - location_neigh[3] = { -1, -1, 0 }; + int location_neigh[3] = { -1, -1, 0 }; //Check if the neighbor has a lower level than the element if (phex_w_sub_pseudo_neigh->p8q.level < phex_w_sub_elem->p8q.level) { location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; - /* the pseudo_neigh transition cell has a lower level than the elem transition cell, so the second entry + /* the pseudo_neigh transition cell has a lower level than the elem transition cell, so the second entry of the location array has to be 1 (= split) */ - location_neigh[1] = 1; /* split */ + location_neigh[1] = 1; /* split */ /* First, check left/right face of transition cell */ - if ((location_elem[0] == 0) || (location_elem[0] == 1)) { - //If the y-coordinates differ, we can deviate that the neighbor lies in the back. + if ((location_elem[0] == 0) || (location_elem[0] == 1)) { + //If the y-coordinates differ, we can deviate that the neighbor lies in the back. //Thus, we need to increment the subelement_type by 2^1 - if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { - location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back*/ + if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { + location_neigh[2] = location_neigh[2] + (int) pow (2, 1); /* back*/ } - //Analogously: if the z-coordinates differ, we can deviate that the neighbor lies up. + //Analogously: if the z-coordinates differ, we can deviate that the neighbor lies up. //Thus, we need to increment the subelement_type by 2^0 if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { - location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ + location_neigh[2] = location_neigh[2] + (int) pow (2, 0); /* up */ } } /* Second, check front/back face of transition cell */ - if ((location_elem[0] == 2) || (location_elem[0] == 3)){ - if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { - location_neigh[2] = location_neigh[2] + (int) pow(2,2); /* right */ + if ((location_elem[0] == 2) || (location_elem[0] == 3)) { + if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { + location_neigh[2] = location_neigh[2] + (int) pow (2, 2); /* right */ } if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { - location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ + location_neigh[2] = location_neigh[2] + (int) pow (2, 0); /* up */ } } /*Third, check lower/up face of transition cell */ - if ((location_elem[0] == 4) || (location_elem[0] == 5)) { + if ((location_elem[0] == 4) || (location_elem[0] == 5)) { if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { - location_neigh[2] = location_neigh[2] + (int) pow(2,2); /* right */ + location_neigh[2] = location_neigh[2] + (int) pow (2, 2); /* right */ } if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { - location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back */ + location_neigh[2] = location_neigh[2] + (int) pow (2, 1); /* back */ } } } /* the pseudo_neigh transition cell has not a lower level than the elem transition cell, so it's face is not split */ else { location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; - location_neigh[1] = 0; /* not split */ + location_neigh[1] = 0; /* not split */ } /* check, that a neighbor is found and the location array is adjusted */ - T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 - && location_neigh[2] >= 0); + T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 && location_neigh[2] >= 0); /* Depending on the location of elem, we have filled location_neigh with the data of the real neighbor. * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ - return - t8_element_get_id_from_location (t8_element_get_transition_type - (pseudo_neigh), location_neigh); + return t8_element_get_id_from_location (t8_element_get_transition_type (pseudo_neigh), location_neigh); } //Elem is no subelement. - else{ + else { /* In this case, we have the following examplary situation for the 2D quad case: * * x - - - - - - - x - - - - - - - x @@ -2935,36 +2649,36 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell * Note that the transition cell of pseudo_neigh and elem can have different levels. */ /* Initialize the location array of the real neighbor. */ - int - location_neigh[3] = { 0, 0, 0 }; + int location_neigh[3] = { 0, 0, 0 }; /* the pseudo_neigh transition cell has a lower level than elem */ - if (phex_w_sub_pseudo_neigh->p8q.level < phex_w_sub_elem->p8q.level) { //actually same case as case 2 just without location array of elem + if (phex_w_sub_pseudo_neigh->p8q.level + < phex_w_sub_elem->p8q.level) { //actually same case as case 2 just without location array of elem location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; - location_neigh[1] = 1; /* split */ - if ((elem_face == 0) || (elem_face == 1)) { /* left/right face of transition cell */ - if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { - location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back*/ + location_neigh[1] = 1; /* split */ + if ((elem_face == 0) || (elem_face == 1)) { /* left/right face of transition cell */ + if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { + location_neigh[2] = location_neigh[2] + (int) pow (2, 1); /* back*/ } if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { - location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ + location_neigh[2] = location_neigh[2] + (int) pow (2, 0); /* up */ } } - if ((elem_face == 2) || (elem_face == 3) ){ /* front/back face of transition cell */ + if ((elem_face == 2) || (elem_face == 3)) { /* front/back face of transition cell */ if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { - - location_neigh[2] = location_neigh[2] + (int) pow(2,2); /* right */ + + location_neigh[2] = location_neigh[2] + (int) pow (2, 2); /* right */ } if (phex_w_sub_pseudo_neigh->p8q.z != phex_w_sub_elem->p8q.z) { - location_neigh[2] = location_neigh[2] + (int) pow(2,0); /* up */ + location_neigh[2] = location_neigh[2] + (int) pow (2, 0); /* up */ } } - if ((elem_face == 4) || (elem_face == 5)) { /* lower/up face of transition cell */ + if ((elem_face == 4) || (elem_face == 5)) { /* lower/up face of transition cell */ if (phex_w_sub_pseudo_neigh->p8q.x != phex_w_sub_elem->p8q.x) { - location_neigh[2] = location_neigh[2] + (int) pow(2,2); /* right */ + location_neigh[2] = location_neigh[2] + (int) pow (2, 2); /* right */ } if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { - location_neigh[2] = location_neigh[2] + (int) pow(2,1); /* back */ + location_neigh[2] = location_neigh[2] + (int) pow (2, 1); /* back */ } } } @@ -2972,37 +2686,32 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell * Note that the level of the transition cell can not be higher as the level of elem in this case, * since elem would then be a subelement in a transition cell. */ if (phex_w_sub_pseudo_neigh->p8q.level == phex_w_sub_elem->p8q.level) { - location_neigh[1] = 0; /* not split */ + location_neigh[1] = 0; /* not split */ location_neigh[2] = 0; /* default value */ location_neigh[0] = subelement_location_to_parent_dual_face[elem_face]; } /* check, that a neighbor is found and the location array is adjusted */ - T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 - && location_neigh[2] >= 0); + T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 && location_neigh[2] >= 0); /* Depending on the location of elem, we have filled location_neigh with the data of the real neighbor. * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ - return - t8_element_get_id_from_location (t8_element_get_transition_type - (pseudo_neigh), location_neigh); + return t8_element_get_id_from_location (t8_element_get_transition_type (pseudo_neigh), location_neigh); } - return -1; /* return negative if no neighbor element could be found */ - + return -1; /* return negative if no neighbor element could be found */ } int -t8_subelement_scheme_hex_c::t8_element_get_id_from_location (int type, - int location[]) +t8_subelement_scheme_hex_c::t8_element_get_id_from_location (int type, int location[]) { T8_ASSERT (type >= 0 && type <= T8_SUB_HEX_MAX_TRANSITION_TYPE); - int sub_id, subelements_count = 0; - double type_temp = double (type); // would work for ints but we use libc pow(double, double) - int binary_type[P8EST_FACES] = { }; + int sub_id, subelements_count = 0; + double type_temp = double (type); // would work for ints but we use libc pow(double, double) + int binary_type[P8EST_FACES] = {}; /* get the type as a binary array */ - int iface; + int iface; for (iface = 0; iface < P8EST_FACES; iface++) { if (type_temp >= pow (2.0, 6 - (iface + 1))) { binary_type[iface] = 1; @@ -3013,54 +2722,52 @@ t8_subelement_scheme_hex_c::t8_element_get_id_from_location (int type, } } - /* count the number of elements up to the given location */ - int element_count; + int element_count; for (element_count = 0; element_count <= location[0]; element_count++) { if (element_count == location[0]) { if (location[1] == 0) { subelements_count += 1; } - else { - subelements_count += 4; - if( location[0] == 0 || location[0] == 1){ - - if ( (location[2] & 2) == 0 ) { // front + else { + subelements_count += 4; + if (location[0] == 0 || location[0] == 1) { + + if ((location[2] & 2) == 0) { // front subelements_count -= 1; } - if( (location[2] & 1) == 0 ) { //bottom + if ((location[2] & 1) == 0) { //bottom subelements_count -= 2; } - } - if( location[0] == 2 || location[0] == 3){ - - if ( (location[2] & 4) == 0 ) { // left + } + if (location[0] == 2 || location[0] == 3) { + + if ((location[2] & 4) == 0) { // left subelements_count -= 1; } - if( (location[2] & 1) == 0 ) { //bottom + if ((location[2] & 1) == 0) { //bottom subelements_count -= 2; } - } - if( location[0] == 4 || location[0] == 5){ - if ( (location[2] & 4) == 0 ) { // left + } + if (location[0] == 4 || location[0] == 5) { + if ((location[2] & 4) == 0) { // left subelements_count -= 1; } - if( (location[2] & 2) == 0 ) { //front + if ((location[2] & 2) == 0) { //front subelements_count -= 2; } - } } } - - else { - if(binary_type[element_count] == 1){ - subelements_count += 4; - } - else{ - subelements_count += 1; } + + else { + if (binary_type[element_count] == 1) { + subelements_count += 4; + } + else { + subelements_count += 1; + } } - } /* get the sub_id */ sub_id = subelements_count - 1; @@ -3068,7 +2775,6 @@ t8_subelement_scheme_hex_c::t8_element_get_id_from_location (int type, return sub_id; } - void t8_subelement_scheme_hex_c::t8_element_new (int length, t8_element_t **elem) const { @@ -3076,10 +2782,9 @@ t8_subelement_scheme_hex_c::t8_element_new (int length, t8_element_t **elem) con t8_default_scheme_common_c::t8_element_new (length, elem); for (int i = 0; i < length; i++) { - t8_hex_with_subelements *phex_w_sub = - (t8_hex_with_subelements *) elem[i]; + t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem[i]; t8_element_init (1, elem[i]); - T8_QUAD_SET_TDIM ( (p8est_quadrant_t *) & phex_w_sub->p8q, 3); + T8_QUAD_SET_TDIM ((p8est_quadrant_t *) &phex_w_sub->p8q, 3); } } @@ -3095,11 +2800,11 @@ t8_subelement_scheme_hex_c::t8_element_init (int length, t8_element_t *elem) con #ifdef T8_ENABLE_DEBUG /* In debugging mode we iterate over all length many elements and * set their hex to the level 0 hex with ID 0. */ - p8est_quadrant_t *hex = &phex_w_sub[i].p8q; - p8est_quadrant_set_morton (hex, 0, 0); - T8_QUAD_SET_TDIM (hex, 3); - T8_ASSERT (p8est_quadrant_is_extended (hex)); - + p8est_quadrant_t *hex = &phex_w_sub[i].p8q; + p8est_quadrant_set_morton (hex, 0, 0); + T8_QUAD_SET_TDIM (hex, 3); + T8_ASSERT (p8est_quadrant_is_extended (hex)); + #endif } } @@ -3111,61 +2816,56 @@ t8_subelement_scheme_hex_c::t8_element_scheme_supports_transitioning (void) } int -t8_subelement_scheme_hex_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const{ +t8_subelement_scheme_hex_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const +{ - return (p8est_quadrant_is_equal ((const p8est_quadrant_t *) elem1, (const p8est_quadrant_t *) elem2)) && (t8_element_get_subelement_id((const t8_element * ) elem1) == t8_element_get_subelement_id((const t8_element * ) elem2)); + return (p8est_quadrant_is_equal ((const p8est_quadrant_t *) elem1, (const p8est_quadrant_t *) elem2)) + && (t8_element_get_subelement_id ((const t8_element *) elem1) + == t8_element_get_subelement_id ((const t8_element *) elem2)); } void -t8_subelement_scheme_hex_c::t8_element_root (t8_element_t *elem) const{ +t8_subelement_scheme_hex_c::t8_element_root (t8_element_t *elem) const +{ p8est_quadrant_t *hex = (p8est_quadrant_t *) elem; p8est_quadrant_set_morton (hex, 0, 0); T8_ASSERT (p8est_quadrant_is_extended (hex)); - } - +} #ifdef T8_ENABLE_DEBUG - /* *INDENT-OFF* */ /* indent bug, indent adds a second "const" modifier */ int -t8_subelement_scheme_hex_c::t8_element_is_valid (const t8_element_t * elem) const +t8_subelement_scheme_hex_c::t8_element_is_valid (const t8_element_t *elem) const /* *INDENT-ON* */ { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; const p8est_quadrant_t *q = &phex_w_sub->p8q; /* the p8est quadrant AND the subelement values must be valid such that the whole element is valid */ - return (p8est_quadrant_is_extended (q) - && t8_element_subelement_values_are_valid (elem)); + return (p8est_quadrant_is_extended (q) && t8_element_subelement_values_are_valid (elem)); } - /* *INDENT-OFF* */ /* indent bug, indent adds a second "const" modifier */ int -t8_subelement_scheme_hex_c::t8_element_subelement_values_are_valid (const - t8_element_t * - elem) const +t8_subelement_scheme_hex_c::t8_element_subelement_values_are_valid (const t8_element_t *elem) const /* *INDENT-ON* */ { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; - return ((phex_w_sub->transition_type >= 0 && - phex_w_sub->transition_type <= T8_SUB_HEX_MAX_TRANSITION_TYPE) - && - (phex_w_sub->subelement_id >= 0 && - phex_w_sub->subelement_id <= T8_SUB_HEX_MAX_SUBELEMENT_ID)); + return ((phex_w_sub->transition_type >= 0 && phex_w_sub->transition_type <= T8_SUB_HEX_MAX_TRANSITION_TYPE) + && (phex_w_sub->subelement_id >= 0 && phex_w_sub->subelement_id <= T8_SUB_HEX_MAX_SUBELEMENT_ID)); } void -t8_subelement_scheme_hex_c::t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const{ - T8_ASSERT (!t8_element_is_subelement(elem)); +t8_subelement_scheme_hex_c::t8_element_to_string (const t8_element_t *elem, char *debug_string, + const int string_size) const +{ + T8_ASSERT (!t8_element_is_subelement (elem)); T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (debug_string != NULL); t8_hex_with_subelements *hex_with_sub = (t8_hex_with_subelements *) elem; @@ -3177,8 +2877,7 @@ t8_subelement_scheme_hex_c::t8_element_to_string (const t8_element_t *elem, char void t8_subelement_scheme_hex_c::t8_element_debug_print (const t8_element_t *elem) const { - const t8_hex_with_subelements *phex_w_sub = - (const t8_hex_with_subelements *) elem; + const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; t8_productionf ("\n|------------ t8_element_debug_print: ------------|" "\n| Transition Type: %i" @@ -3187,26 +2886,22 @@ t8_subelement_scheme_hex_c::t8_element_debug_print (const t8_element_t *elem) co "\n| Anchor (ref coords): (%lf,%lf,%lf)" "\n| Level: %i" "\n|-------------------------------------------------|\n", - phex_w_sub->transition_type, phex_w_sub->subelement_id, - phex_w_sub->p8q.x, phex_w_sub->p8q.y,phex_w_sub->p8q.z, - (double) phex_w_sub->p8q.x / (double) P8EST_ROOT_LEN, + phex_w_sub->transition_type, phex_w_sub->subelement_id, phex_w_sub->p8q.x, phex_w_sub->p8q.y, + phex_w_sub->p8q.z, (double) phex_w_sub->p8q.x / (double) P8EST_ROOT_LEN, (double) phex_w_sub->p8q.y / (double) P8EST_ROOT_LEN, - (double) phex_w_sub->p8q.z / (double) P8EST_ROOT_LEN, - phex_w_sub->p8q.level); + (double) phex_w_sub->p8q.z / (double) P8EST_ROOT_LEN, phex_w_sub->p8q.level); /* if the element is not valid, abort, but after printing */ T8_ASSERT (t8_element_is_valid (elem)); - } - #endif /* each hex is packed as x,y,z coordinates, the subelement ID, transition type and the level */ void t8_subelement_scheme_hex_c::t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, - void *send_buffer, const int buffer_size, int *position, - sc_MPI_Comm comm) const + void *send_buffer, const int buffer_size, int *position, + sc_MPI_Comm comm) const { int mpiret; p8est_quadrant_t **quads = (p8est_quadrant_t **) elements; @@ -3218,9 +2913,11 @@ t8_subelement_scheme_hex_c::t8_element_MPI_Pack (t8_element_t **const elements, SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Pack (&(quads[ielem]->z), 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&quads_with_sub[ielem]->subelement_id, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + mpiret + = sc_MPI_Pack (&quads_with_sub[ielem]->subelement_id, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&quads_with_sub[ielem]->transition_type, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); + mpiret + = sc_MPI_Pack (&quads_with_sub[ielem]->transition_type, 1, sc_MPI_INT, send_buffer, buffer_size, position, comm); SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Pack (&(quads[ielem]->level), 1, sc_MPI_INT8_T, send_buffer, buffer_size, position, comm); SC_CHECK_MPI (mpiret); @@ -3251,8 +2948,8 @@ t8_subelement_scheme_hex_c::t8_element_MPI_Pack_size (const unsigned int count, /* each hex is packed as x,y,z coordinates and the level */ void t8_subelement_scheme_hex_c::t8_element_MPI_Unpack (void *recvbuf, const int buffer_size, int *position, - t8_element_t **elements, const unsigned int count, - sc_MPI_Comm comm) const + t8_element_t **elements, const unsigned int count, + sc_MPI_Comm comm) const { int mpiret; p8est_quadrant_t **quads = (p8est_quadrant_t **) elements; @@ -3265,9 +2962,11 @@ t8_subelement_scheme_hex_c::t8_element_MPI_Unpack (void *recvbuf, const int buff SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->z), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads_with_sub[ielem]->subelement_id), 1, sc_MPI_INT, comm); + mpiret + = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads_with_sub[ielem]->subelement_id), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads_with_sub[ielem]->transition_type), 1, sc_MPI_INT, comm); + mpiret + = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads_with_sub[ielem]->transition_type), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Unpack (recvbuf, buffer_size, position, &(quads[ielem]->level), 1, sc_MPI_INT8_T, comm); SC_CHECK_MPI (mpiret); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 2f211099f3..971c3a249f 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -67,11 +67,11 @@ typedef struct { /* p8est quadrant */ - p8est_quadrant_t p8q; + p8est_quadrant_t p8q; /* stores transition cell information (default for non-subelements is 0 and for subelements it is != 0 - is therefore used as a is_subelement check) */ int transition_type; /* stores subelement information (default for non-subelements is 0) */ - int subelement_id; + int subelement_id; } t8_hex_with_subelements; @@ -126,10 +126,9 @@ typedef t8_hex_with_subelements t8_phex_sub_t; t8_eclass_scheme_t *t8_subelement_scheme_new_hex (void); #endif - -struct t8_subelement_scheme_hex_c:public t8_default_scheme_common_c +struct t8_subelement_scheme_hex_c: public t8_default_scheme_common_c { -public: + public: /** The virtual table for a particular implementation of an element class. */ /** Constructor. */ @@ -163,38 +162,33 @@ public: virtual int t8_element_maxlevel (void) const; -/** Return the type of each child in the ordering of the implementation. */ + /** Return the type of each child in the ordering of the implementation. */ virtual t8_eclass_t t8_element_child_eclass (int childid) const; -/** Return the refinement level of an element. */ + /** Return the refinement level of an element. */ virtual int t8_element_level (const t8_element_t *elem) const; -/** Copy one element to another */ + /** Copy one element to another */ virtual void - t8_element_copy (const t8_element_t *source, - t8_element_t *dest) const; + t8_element_copy (const t8_element_t *source, t8_element_t *dest) const; -/** Compare to elements. returns negative if elem1 < elem2, zero if elem1 equals elem2 + /** Compare to elements. returns negative if elem1 < elem2, zero if elem1 equals elem2 * and positive if elem1 > elem2. * If elem2 is a copy of elem1 then the elements are equal. * If both elements are sibling subelements, return 0 if they are identical (same sub_id) and 1 otherwise. */ virtual int - t8_element_compare (const t8_element_t *elem1, - const t8_element_t *elem2) const; + t8_element_compare (const t8_element_t *elem1, const t8_element_t *elem2) const; -/** Construct the parent of a given element. */ + /** Construct the parent of a given element. */ virtual void - t8_element_parent (const t8_element_t *elem, - t8_element_t *parent) const; + t8_element_parent (const t8_element_t *elem, t8_element_t *parent) const; -/** Construct a same-size sibling of a given element. */ + /** Construct a same-size sibling of a given element. */ virtual void - t8_element_sibling (const t8_element_t *elem, - int sibid, - t8_element_t *sibling) const; + t8_element_sibling (const t8_element_t *elem, int sibid, t8_element_t *sibling) const; /** Compute the number of face of a given element. */ virtual int @@ -227,7 +221,7 @@ public: * \return True if the neighbor of elems' face is a sibling * */ - virtual int + virtual int t8_element_neighbor_is_sibling (const t8_element_t *elem, int face) const; /** @@ -238,32 +232,29 @@ public: * */ virtual int - t8_element_get_num_sibling_neighbors_at_face (const t8_element_t *elem, - int face) const; + t8_element_get_num_sibling_neighbors_at_face (const t8_element_t *elem, int face) const; /** \return zero refine value for schemes that do not have a transition implementation. */ virtual int t8_element_get_transition_refine_identifier (void) const; - /** Return the corner number of an element's face corner. + /** Return the corner number of an element's face corner. * \param [in] element The element. * \param [in] face A face index for \a element. * \param [in] corner A corner index for the face 0 <= \a corner < num_face_corners. * \return The corner number of the \a corner-th vertex of \a face. */ virtual int - t8_element_get_face_corner (const t8_element_t *element, - int face, int corner) const; + t8_element_get_face_corner (const t8_element_t *element, int face, int corner) const; - /** Return the face numbers of the faces sharing an element's corner. + /** Return the face numbers of the faces sharing an element's corner. * \param [in] element The element. * \param [in] corner A corner index for the face. * \param [in] face A face index for \a corner. * \return The face number of the \a face-th face at \a corner. */ virtual int - t8_element_get_corner_face (const t8_element_t *element, - int corner, int face) const; + t8_element_get_corner_face (const t8_element_t *element, int corner, int face) const; /** Construct the child element of a given number. * \param [in] elem This must be a valid element, bigger than maxlevel. @@ -274,120 +265,90 @@ public: * It is valid to call this function with elem = child. */ virtual void - t8_element_child (const t8_element_t *elem, - int childid, - t8_element_t *child) const; + t8_element_child (const t8_element_t *elem, int childid, t8_element_t *child) const; /** Construct all sibling neighbors of elem at face - it is required that sibling neighbors of elem at face exist */ virtual void - t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t - *elem, - const int face, - const int - num_neighbors, - t8_element_t - *neighbor_at_face[], - int *neigh_face); - -/** Construct all children of a given element. */ + t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t *elem, const int face, + const int num_neighbors, t8_element_t *neighbor_at_face[], + int *neigh_face); + + /** Construct all children of a given element. */ virtual void - t8_element_children (const t8_element_t *elem, - int length, - t8_element_t *c[]) const; + t8_element_children (const t8_element_t *elem, int length, t8_element_t *c[]) const; -/** Return the child id of an element */ + /** Return the child id of an element */ virtual int t8_element_child_id (const t8_element_t *elem) const; /** Compute the ancestor id of an element */ virtual int - t8_element_ancestor_id (const t8_element_t *elem, - int level) const; + t8_element_ancestor_id (const t8_element_t *elem, int level) const; -/** Return nonzero if collection of elements is a family */ + /** Return nonzero if collection of elements is a family */ virtual int t8_element_is_family (t8_element_t *const *fam) const; -/** Construct the nearest common ancestor of two elements in the same tree. */ + /** Construct the nearest common ancestor of two elements in the same tree. */ virtual void - t8_element_nca (const t8_element_t *elem1, - const t8_element_t *elem2, - t8_element_t *nca) const; + t8_element_nca (const t8_element_t *elem1, const t8_element_t *elem2, t8_element_t *nca) const; /** Compute the element shape of the face of an element. */ virtual t8_element_shape_t - t8_element_face_shape (const t8_element_t *elem, - int face) const; + t8_element_face_shape (const t8_element_t *elem, int face) const; /** Given an element and a face of the element, compute all children of * the element that touch the face. */ /** Given an element and a face of the element, compute all children of * the element that touch the face. */ virtual void - t8_element_children_at_face (const t8_element_t *elem, - int face, - t8_element_t *children[], - int num_children, + t8_element_children_at_face (const t8_element_t *elem, int face, t8_element_t *children[], int num_children, int *child_indices) const; /** Given a face of an element and a child number of a child of that face, return the face number * of the child of the element that matches the child face. */ virtual int - t8_element_face_child_face (const t8_element_t *elem, - int face, int face_child) const; + t8_element_face_child_face (const t8_element_t *elem, int face, int face_child) const; /** Given a face of an element return the face number * of the parent of the element that matches the element's face. Or return -1 if * no face of the parent matches the face. */ virtual int - t8_element_face_parent_face (const t8_element_t *elem, - int face) const; + t8_element_face_parent_face (const t8_element_t *elem, int face) const; /** Transform the coordinates of a hexaliteral considered as boundary element * in a tree-tree connection. */ virtual void - t8_element_transform_face (const t8_element_t *elem1, - t8_element_t *elem2, - int orientation, int sign, + t8_element_transform_face (const t8_element_t *elem1, t8_element_t *elem2, int orientation, int sign, int is_smaller_face) const; /** Given a boundary face inside a root tree's face construct * the element inside the root tree that has the given face as a * face. */ virtual int - t8_element_extrude_face (const t8_element_t *face, - const t8_eclass_scheme_c *face_scheme, - t8_element_t *elem, + t8_element_extrude_face (const t8_element_t *face, const t8_eclass_scheme_c *face_scheme, t8_element_t *elem, int root_face) const; /** Return the tree face id given a boundary face. */ virtual int - t8_element_tree_face (const t8_element_t *elem, - int face) const; + t8_element_tree_face (const t8_element_t *elem, int face) const; /** Construct the first descendant of an element that touches a given face. */ virtual void - t8_element_first_descendant_face (const t8_element_t *elem, int face, - t8_element_t *first_desc, - int level) const; + t8_element_first_descendant_face (const t8_element_t *elem, int face, t8_element_t *first_desc, int level) const; /** Construct the last descendant of an element that touches a given face. */ virtual void - t8_element_last_descendant_face (const t8_element_t *elem, int face, - t8_element_t *last_desc, - int level) const; + t8_element_last_descendant_face (const t8_element_t *elem, int face, t8_element_t *last_desc, int level) const; /** Construct the boundary element at a specific face. */ virtual void - t8_element_boundary_face (const t8_element_t *elem, - int face, t8_element_t *boundary, + t8_element_boundary_face (const t8_element_t *elem, int face, t8_element_t *boundary, const t8_eclass_scheme_c *boundary_scheme) const; -/** Construct all codimension-one boundary elements of a given element. */ + /** Construct all codimension-one boundary elements of a given element. */ virtual void - t8_element_boundary (const t8_element_t *elem, - int min_dim, int length, - t8_element_t **boundary) const; + t8_element_boundary (const t8_element_t *elem, int min_dim, int length, t8_element_t **boundary) const; /** Compute whether a given element shares a given face with its root tree. * \param [in] elem The input element. @@ -395,64 +356,50 @@ public: * \return True if \a face is a subface of the element's root element. */ virtual int - t8_element_is_root_boundary (const t8_element_t *elem, - int face) const; + t8_element_is_root_boundary (const t8_element_t *elem, int face) const; /** Construct the face neighbor of a given element if this face neighbor * is inside the root tree. Return 0 otherwise. */ virtual int - t8_element_face_neighbor_inside (const t8_element_t *elem, - t8_element_t *neigh, - int face, - int *neigh_face) const; + t8_element_face_neighbor_inside (const t8_element_t *elem, t8_element_t *neigh, int face, int *neigh_face) const; -/** Initialize an element according to a given linear id */ + /** Initialize an element according to a given linear id */ virtual void - t8_element_set_linear_id (t8_element_t *elem, - int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; -/** Calculate the linear id of an element */ - virtual t8_linearidx_t - t8_element_get_linear_id (constt8_element_t *elem, - int level) const; + /** Calculate the linear id of an element */ + virtual t8_linearidx_t + t8_element_get_linear_id (constt8_element_t *elem, int level) const; -/** Calculate the first descendant of a given element e. That is, the + /** Calculate the first descendant of a given element e. That is, the * first element in a uniform refinement of e of the maximal possible level. */ virtual void - t8_element_first_descendant (const t8_element_t *elem, - t8_element_t *desc, - int level) const; + t8_element_first_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; -/** Calculate the last descendant of a given element e. That is, the + /** Calculate the last descendant of a given element e. That is, the * last element in a uniform refinement of e of the maximal possible level. */ virtual void - t8_element_last_descendant (const t8_element_t *elem, - t8_element_t *desc, - int level) const; + t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; -/** Compute s as a successor of t*/ + /** Compute s as a successor of t*/ virtual void t8_element_successor (const t8_element_t *t, t8_element_t *s) const; -/** Get the integer coordinates of the anchor node of an element */ + /** Get the integer coordinates of the anchor node of an element */ virtual void - t8_element_anchor (const t8_element_t *elem, - int anchor[3]) const; + t8_element_anchor (const t8_element_t *elem, int anchor[3]) const; -/** Get the integer root length of an element, that is the length of + /** Get the integer root length of an element, that is the length of * the level 0 ancestor. */ virtual int t8_element_root_len (const t8_element_t *elem) const; -/** Compute the integer coordinates of a given element vertex. */ + /** Compute the integer coordinates of a given element vertex. */ virtual void - t8_element_vertex_coords (const t8_element_t *t, - int vertex, - int coords[]) const; - + t8_element_vertex_coords (const t8_element_t *t, int vertex, int coords[]) const; /** Compute the integer coordinates of a given element vertex. * The default scheme implements the Morton type SFCs. In these SFCs the @@ -467,8 +414,7 @@ public: virtual void t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const; - -/** Convert a point in the reference space of an element to a point in the + /** Convert a point in the reference space of an element to a point in the * reference space of the tree. * * \param [in] elem The element. @@ -476,20 +422,20 @@ public: * \param [in] user_data User data. * \param [out] out_coords The coordinates of the point in the reference space of the tree. */ - virtual void + virtual void t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) const; -/** Construct a transition cell of type type + /** Construct a transition cell of type type * * \param [in] elem The element. * \param [in] type The transition type * \param [out] out_coords The coordinates of the point in the reference space of the tree. */ - virtual void + virtual void t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *c[]); -/** Determine the number of sibling subelements, of a transition cell of a specific type + /** Determine the number of sibling subelements, of a transition cell of a specific type * * \param [in] type The transition type. * \return The number of sibling subelements, of a transition cell with the given transition type. @@ -497,35 +443,33 @@ public: virtual int t8_element_get_number_of_subelements (int transition_type) const; -/** Test whether a given element is a subelement or not + /** Test whether a given element is a subelement or not * * \param [in] elem The element. * \return true if elem is a subelement, otherwise false. */ - virtual int - t8_element_is_subelement (const t8_element * elem) const; - + virtual int + t8_element_is_subelement (const t8_element *elem) const; -/** Get the subelement type of an element + /** Get the subelement type of an element * * \param [in] elem The element. * \return Transition type of elem. */ virtual int - t8_element_get_transition_type (const t8_element * elem); - + t8_element_get_transition_type (const t8_element *elem); -/** Get the subelement ID of an element + /** Get the subelement ID of an element * * \param [in] elem The element. * \return Subelement ID of \a elem. */ - virtual int - t8_element_get_subelement_id (const t8_element * elem) const; + virtual int + t8_element_get_subelement_id (const t8_element *elem) const; -/** + /** */ - /** Get the subelement ID of the neighbor subelement of elem at face elem_face + /** Get the subelement ID of the neighbor subelement of elem at face elem_face * that is a sibling of the subelement neigh (That means: lives in the same transition cell) * * \param [in] elem The element. @@ -534,25 +478,22 @@ public: * \return Subelement ID of \a neigh which is a neighbor of \a elem at face \a elem_face. */ virtual int - t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, - const t8_element_t *neigh, - int elem_face); - + t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, const t8_element_t *neigh, int elem_face); - /** Check if the eclass scheme has an implementation for subelements. + /** Check if the eclass scheme has an implementation for subelements. * \return True if the scheme has an implementation for subelements, otherwise return false. */ - virtual int + virtual int t8_element_scheme_supports_transitioning (void); -/** Checks if there is one element in the tree, that does not refine into 2^dim children. + /** Checks if there is one element in the tree, that does not refine into 2^dim children. * * \return True, if there is one element in the tree that does not refine into 2^dim children, return false otherwise. */ virtual int t8_element_refines_irregular (void) const; -/** Get the shape of a given element. Subelements of the hexahedral transition scheme are pyramids. + /** Get the shape of a given element. Subelements of the hexahedral transition scheme are pyramids. * * \param [in] elem The element. * \return Shape of \a elem. @@ -560,7 +501,7 @@ public: virtual t8_element_shape_t t8_element_shape (const t8_element_t *elem) const; -/** Return the number of vertices of an element. A subelement in the hexahedral transition scheme has five vertices. + /** Return the number of vertices of an element. A subelement in the hexahedral transition scheme has five vertices. * * \param [in] elem The element. * \return Number of vertices of \a elem. @@ -568,7 +509,7 @@ public: virtual int t8_element_num_corners (const t8_element_t *elem) const; -/** Compute the coordinates of a given element vertex inside a reference tree + /** Compute the coordinates of a given element vertex inside a reference tree * that is embedded into [0,1]^d (d = dimension). * \param [in] t The element to be considered. * \param [in] vertex The id of the vertex whose coordinates shall be computed. @@ -576,18 +517,19 @@ public: * whose entries will be filled with the coordinates of \a vertex. */ virtual void - t8_element_vertex_reference_coords (const t8_element_t *t, int vertex, - double coords[]) const; + t8_element_vertex_reference_coords (const t8_element_t *t, int vertex, double coords[]) const; #ifdef T8_ENABLE_DEBUG -/** TODO: this should be the new element_print_element function */ - virtual void t8_element_debug_print (const t8_element_t *elem) const; + /** TODO: this should be the new element_print_element function */ + virtual void + t8_element_debug_print (const t8_element_t *elem) const; -/** Query whether an element is valid */ - virtual int t8_element_is_valid (const t8_element_t *t) const; + /** Query whether an element is valid */ + virtual int + t8_element_is_valid (const t8_element_t *t) const; #endif -protected: + protected: /** This function determines the vertex coordinates of subelements. * \param [in] elem A valid subelement * \param [in] vertex the number of the vertex whose coordinates should be determined @@ -598,9 +540,7 @@ protected: * are triangles with 3 instead of 4 vertices. */ void - t8_element_vertex_coords_of_subelement (const t8_element_t *t, - int vertex, - int coords[]) const; + t8_element_vertex_coords_of_subelement (const t8_element_t *t, int vertex, int coords[]) const; /** This function will determine the location of a specific subelement in the parent element. * Since different subelement types are possible, it is a priori not known where for example the @@ -616,10 +556,9 @@ protected: * Since this function is only used to determine the vertices of subelements, it can be declared as a private/protected function. */ void - t8_element_get_location_of_subelement (const t8_element_t *elem, - int location[]) const; + t8_element_get_location_of_subelement (const t8_element_t *elem, int location[]) const; - /** This help function returns the subelement ID of an element whose location and transition type is known. + /** This help function returns the subelement ID of an element whose location and transition type is known. * \param [in] type Transition type * \param [in] location The location array of a subelement. * \param [out] subelement_ID The subelement ID of the subelement with transition type \a type and location array \a location[] @@ -632,8 +571,7 @@ protected: * \param [in,out] dest A valid element, whose subelement values are equal to those of source */ void - t8_element_copy_subelement_values (const t8_element_t *source, - t8_element_t *dest) const; + t8_element_copy_subelement_values (const t8_element_t *source, t8_element_t *dest) const; /** This function resets the subelement values of an element to the default value 0. * \param [in,out] elem A valid element, whose subelement values have been reset. @@ -650,13 +588,13 @@ protected: virtual int t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const; - /** Fills an element with the root element. + /** Fills an element with the root element. * \param [in,out] elem The element to be filled with root. */ void t8_element_root (t8_element_t *elem) const; - /** Initialize an array of allocated hexahedra/subelements. + /** Initialize an array of allocated hexahedra/subelements. * \param [in] length The number of hex to be initialized. * \param [in,out] elems On input an array of \b length many allocated * elements. @@ -716,7 +654,7 @@ protected: int t8_element_subelement_values_are_valid (const t8_element_t *elem) const; - /** + /** * Print a given element. For a example for a triangle print the coordinates * and the level of the triangle. This function is only available in the * debugging configuration. @@ -724,9 +662,8 @@ protected: * \param [in] elem The element to print */ virtual void - t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const; - - + t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const; + #endif }; diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx index 3b1c8f1985..709983ac65 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx @@ -32,19 +32,21 @@ /* We want to export the whole implementation to be callable from "C" */ T8_EXTERN_C_BEGIN (); -t8_scheme_cxx_t * +t8_scheme_cxx_t * t8_scheme_new_transition_quad_cxx (void) { - t8_scheme_cxx_t *s; + t8_scheme_cxx_t *s; s = T8_ALLOC_ZERO (t8_scheme_cxx_t, 1); t8_refcount_init (&s->rc); s->eclass_schemes[T8_ECLASS_VERTEX] = NULL; - s->eclass_schemes[T8_ECLASS_LINE] = new t8_default_scheme_line_c (); /* Standard T8_ECLASS_LINE is used by the quad scheme */ + s->eclass_schemes[T8_ECLASS_LINE] + = new t8_default_scheme_line_c (); /* Standard T8_ECLASS_LINE is used by the quad scheme */ s->eclass_schemes[T8_ECLASS_QUAD] = new t8_subelement_scheme_quad_c (); s->eclass_schemes[T8_ECLASS_HEX] = NULL; - s->eclass_schemes[T8_ECLASS_TRIANGLE] = new t8_default_scheme_tri_c (); /* can be used for hybrid meshes - not conformal as long as no conformal transition tri class exists */ + s->eclass_schemes[T8_ECLASS_TRIANGLE] + = new t8_default_scheme_tri_c (); /* can be used for hybrid meshes - not conformal as long as no conformal transition tri class exists */ s->eclass_schemes[T8_ECLASS_TET] = NULL; s->eclass_schemes[T8_ECLASS_PRISM] = NULL; s->eclass_schemes[T8_ECLASS_PYRAMID] = NULL; @@ -52,7 +54,4 @@ t8_scheme_new_transition_quad_cxx (void) return s; } - - - T8_EXTERN_C_END (); diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index 9bf74f063f..c7eb009d5e 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -34,7 +34,7 @@ * f_0 <-> f_2 * f_1 <-> f_1 (assuming a neighboring transition cell) * f_2 <-> f_0 */ -const int subelement_face_dual[3] = { 2, 1, 0}; +const int subelement_face_dual[3] = { 2, 1, 0 }; /* Connectivity of a subelements location within a transition cell * and the parent quads faces: @@ -42,7 +42,7 @@ const int subelement_face_dual[3] = { 2, 1, 0}; * location[0] = 1 -> parents face = 2 * location[0] = 2 -> parents face = 0 * location[0] = 3 -> parents face = 3 */ -const int subelement_location_to_parent_dual_face[4] = {1, 2, 0, 3}; +const int subelement_location_to_parent_dual_face[4] = { 1, 2, 0, 3 }; /* Connectivity of a subelements location within a transition cell * and the parent quads faces: @@ -50,7 +50,7 @@ const int subelement_location_to_parent_dual_face[4] = {1, 2, 0, 3}; * location[0] = 1 (clockwise) -> parents face = 3 * location[0] = 2 (clockwise) -> parents face = 1 * location[0] = 3 (clockwise) -> parents face = 2 */ -const int subelement_location_to_parent_face[4] = {0, 3, 1, 2}; +const int subelement_location_to_parent_face[4] = { 0, 3, 1, 2 }; /* *INDENT-ON* */ /* We want to export the whole implementation to be callable from "C" */ @@ -58,8 +58,8 @@ T8_EXTERN_C_BEGIN (); /* This function is used by other element functions and we thus need to * declare it up here */ -t8_linearidx_t t8_element_get_linear_id (const t8_element_t *elem, - int level); +t8_linearidx_t +t8_element_get_linear_id (const t8_element_t *elem, int level); int t8_subelement_scheme_quad_c::t8_element_maxlevel (void) const @@ -81,14 +81,13 @@ t8_subelement_scheme_quad_c::t8_element_child_eclass (int childid) const int t8_subelement_scheme_quad_c::t8_element_level (const t8_element_t *elem) const { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; T8_ASSERT (t8_element_is_valid (elem)); return (int) ((const t8_quad_with_subelements *) pquad_w_sub)->p4q.level; } static void -t8_element_copy_surround (const p4est_quadrant_t * q, p4est_quadrant_t * r) +t8_element_copy_surround (const p4est_quadrant_t *q, p4est_quadrant_t *r) { T8_QUAD_SET_TDIM (r, T8_QUAD_GET_TDIM (q)); if (T8_QUAD_GET_TDIM (q) == 3) { @@ -98,23 +97,18 @@ t8_element_copy_surround (const p4est_quadrant_t * q, p4est_quadrant_t * r) } void -t8_subelement_scheme_quad_c::t8_element_copy (const t8_element_t *source, - t8_element_t *dest) const +t8_subelement_scheme_quad_c::t8_element_copy (const t8_element_t *source, t8_element_t *dest) const { - const t8_quad_with_subelements *pquad_w_sub_source = - (const t8_quad_with_subelements *) source; - t8_quad_with_subelements *pquad_w_sub_dest = - (t8_quad_with_subelements *) dest; + const t8_quad_with_subelements *pquad_w_sub_source = (const t8_quad_with_subelements *) source; + t8_quad_with_subelements *pquad_w_sub_dest = (t8_quad_with_subelements *) dest; const p4est_quadrant_t *q = &pquad_w_sub_source->p4q; - p4est_quadrant_t *r = &pquad_w_sub_dest->p4q; + p4est_quadrant_t *r = &pquad_w_sub_dest->p4q; T8_ASSERT (t8_element_is_valid (source)); T8_ASSERT (t8_element_is_valid (dest)); - if (q == r && - pquad_w_sub_source->transition_type == - pquad_w_sub_dest->transition_type && - pquad_w_sub_source->subelement_id == pquad_w_sub_dest->subelement_id) { + if (q == r && pquad_w_sub_source->transition_type == pquad_w_sub_dest->transition_type + && pquad_w_sub_source->subelement_id == pquad_w_sub_dest->subelement_id) { /* Do nothing if they are already the same quadrant. */ return; } @@ -125,14 +119,10 @@ t8_subelement_scheme_quad_c::t8_element_copy (const t8_element_t *source, } int -t8_subelement_scheme_quad_c::t8_element_compare (const t8_element_t *elem1, - const t8_element_t *elem2) - const +t8_subelement_scheme_quad_c::t8_element_compare (const t8_element_t *elem1, const t8_element_t *elem2) const { - const t8_quad_with_subelements *pquad_w_sub_elem1 = - (const t8_quad_with_subelements *) elem1; - const t8_quad_with_subelements *pquad_w_sub_elem2 = - (const t8_quad_with_subelements *) elem2; + const t8_quad_with_subelements *pquad_w_sub_elem1 = (const t8_quad_with_subelements *) elem1; + const t8_quad_with_subelements *pquad_w_sub_elem2 = (const t8_quad_with_subelements *) elem2; const p4est_quadrant_t *q = &pquad_w_sub_elem1->p4q; const p4est_quadrant_t *r = &pquad_w_sub_elem2->p4q; @@ -140,19 +130,15 @@ t8_subelement_scheme_quad_c::t8_element_compare (const t8_element_t *elem1, T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); - int compare = p4est_quadrant_compare (q, r); + int compare = p4est_quadrant_compare (q, r); - if (compare == 0 && (t8_element_is_subelement (elem1) - || t8_element_is_subelement (elem2))) { + if (compare == 0 && (t8_element_is_subelement (elem1) || t8_element_is_subelement (elem2))) { t8_debugf ("Caution, t8_element_compare is used with subelements.\n"); - if (t8_element_is_subelement (elem1) - && t8_element_is_subelement (elem2)) { + if (t8_element_is_subelement (elem1) && t8_element_is_subelement (elem2)) { /* Caution: The compare function is used for two subelements. */ - if (pquad_w_sub_elem1->transition_type == - pquad_w_sub_elem2->transition_type - && pquad_w_sub_elem1->subelement_id == - pquad_w_sub_elem2->subelement_id) { + if (pquad_w_sub_elem1->transition_type == pquad_w_sub_elem2->transition_type + && pquad_w_sub_elem1->subelement_id == pquad_w_sub_elem2->subelement_id) { /* both subelements are identical */ return 0; } @@ -160,10 +146,10 @@ t8_subelement_scheme_quad_c::t8_element_compare (const t8_element_t *elem1, return 1; } else if (t8_element_is_subelement (elem1)) { - return -1; /* elem1 is subelement and therefore smaller */ + return -1; /* elem1 is subelement and therefore smaller */ } else if (t8_element_is_subelement (elem2)) { - return 1; /* elem2 is subelement and therefore smaller */ + return 1; /* elem2 is subelement and therefore smaller */ } } @@ -172,16 +158,13 @@ t8_subelement_scheme_quad_c::t8_element_compare (const t8_element_t *elem1, } void -t8_subelement_scheme_quad_c::t8_element_parent (const t8_element_t *elem, - t8_element_t *parent) const +t8_subelement_scheme_quad_c::t8_element_parent (const t8_element_t *elem, t8_element_t *parent) const { - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements *pquad_w_sub_parent = - (t8_quad_with_subelements *) parent; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_parent = (t8_quad_with_subelements *) parent; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - p4est_quadrant_t *r = &pquad_w_sub_parent->p4q; + p4est_quadrant_t *r = &pquad_w_sub_parent->p4q; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (parent)); @@ -200,17 +183,13 @@ t8_subelement_scheme_quad_c::t8_element_parent (const t8_element_t *elem, } void -t8_subelement_scheme_quad_c::t8_element_sibling (const t8_element_t *elem, - int sibid, - t8_element_t *sibling) const +t8_subelement_scheme_quad_c::t8_element_sibling (const t8_element_t *elem, int sibid, t8_element_t *sibling) const { - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements *pquad_w_sub_sibling = - (t8_quad_with_subelements *) sibling; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_sibling = (t8_quad_with_subelements *) sibling; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - p4est_quadrant_t *r = &pquad_w_sub_sibling->p4q; + p4est_quadrant_t *r = &pquad_w_sub_sibling->p4q; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -227,13 +206,11 @@ t8_subelement_scheme_quad_c::t8_element_num_faces (const t8_element_t *elem) con { T8_ASSERT (t8_element_is_valid (elem)); - return (t8_element_is_subelement (elem) ? T8_QUAD_SUBELEMENT_FACES : - P4EST_FACES); + return (t8_element_is_subelement (elem) ? T8_QUAD_SUBELEMENT_FACES : P4EST_FACES); } int -t8_subelement_scheme_quad_c::t8_element_max_num_faces (const t8_element_t - *elem) const +t8_subelement_scheme_quad_c::t8_element_max_num_faces (const t8_element_t *elem) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -242,8 +219,7 @@ t8_subelement_scheme_quad_c::t8_element_max_num_faces (const t8_element_t } int -t8_subelement_scheme_quad_c::t8_element_num_children (const t8_element_t - *elem) const +t8_subelement_scheme_quad_c::t8_element_num_children (const t8_element_t *elem) const { /* Note that children of subelements equal the children of the parent quadrant. * Therefore, the number of children of a subelement equals P4EST_CHILDREN */ @@ -253,32 +229,29 @@ t8_subelement_scheme_quad_c::t8_element_num_children (const t8_element_t /* *INDENT-OFF* */ /* indent bug, indent adds a second "const" modifier */ -int -t8_subelement_scheme_quad_c::t8_element_num_siblings (const t8_element_t * - elem) const +int +t8_subelement_scheme_quad_c::t8_element_num_siblings (const t8_element_t *elem) const /* *INDENT-ON* */ { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; if (pquad_w_sub->transition_type == 0) return P4EST_FACES; - int num_hanging_faces = 0; - int iface; - for (iface = 0; iface < P4EST_FACES; iface++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ - num_hanging_faces += - (pquad_w_sub->transition_type & (1 << iface)) >> iface; + int num_hanging_faces = 0; + int iface; + for ( + iface = 0; iface < P4EST_FACES; + iface++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ + num_hanging_faces += (pquad_w_sub->transition_type & (1 << iface)) >> iface; } return P4EST_CHILDREN + num_hanging_faces; } int -t8_subelement_scheme_quad_c::t8_element_num_face_children (const t8_element_t - *elem, - int face) const +t8_subelement_scheme_quad_c::t8_element_num_face_children (const t8_element_t *elem, int face) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -289,11 +262,7 @@ t8_subelement_scheme_quad_c::t8_element_num_face_children (const t8_element_t } int -t8_subelement_scheme_quad_c::t8_element_neighbor_is_sibling (const - t8_element_t - *elem, - const int face) - const +t8_subelement_scheme_quad_c::t8_element_neighbor_is_sibling (const t8_element_t *elem, const int face) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_subelement (elem)); @@ -313,7 +282,7 @@ t8_subelement_scheme_quad_c::t8_element_get_num_sibling_neighbors_at_face (const T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_subelement (elem)); T8_ASSERT (face == 0 || face == 2); - + return 1; } @@ -325,9 +294,7 @@ t8_subelement_scheme_quad_c::t8_element_get_transition_refine_identifier () cons /* *INDENT-ON* */ int -t8_subelement_scheme_quad_c::t8_element_get_face_corner (const t8_element_t - *elem, int face, - int corner) const +t8_subelement_scheme_quad_c::t8_element_get_face_corner (const t8_element_t *elem, int face, int corner) const { T8_ASSERT (t8_element_is_valid (elem)); @@ -348,11 +315,7 @@ t8_subelement_scheme_quad_c::t8_element_get_face_corner (const t8_element_t return p4est_face_corners[face][corner]; } else { - int t8_face_corners_subelement[3][2] = { - {0, 1}, - {1, 2}, - {2, 0} - }; + int t8_face_corners_subelement[3][2] = { { 0, 1 }, { 1, 2 }, { 2, 0 } }; /* * * x - - - - - x 1 @@ -374,9 +337,7 @@ t8_subelement_scheme_quad_c::t8_element_get_face_corner (const t8_element_t } int -t8_subelement_scheme_quad_c::t8_element_get_corner_face (const t8_element_t - *elem, int corner, - int face) const +t8_subelement_scheme_quad_c::t8_element_get_corner_face (const t8_element_t *elem, int corner, int face) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -388,9 +349,7 @@ t8_subelement_scheme_quad_c::t8_element_get_corner_face (const t8_element_t } void -t8_subelement_scheme_quad_c::t8_element_child (const t8_element_t *elem, - int childid, - t8_element_t *child) const +t8_subelement_scheme_quad_c::t8_element_child (const t8_element_t *elem, int childid, t8_element_t *child) const { /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -405,13 +364,11 @@ t8_subelement_scheme_quad_c::t8_element_child (const t8_element_t *elem, * x - - - - - x x - - x - - x * */ - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements *pquad_w_sub_child = - (t8_quad_with_subelements *) child; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_child = (t8_quad_with_subelements *) child; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - p4est_quadrant_t *r = &pquad_w_sub_child->p4q; + p4est_quadrant_t *r = &pquad_w_sub_child->p4q; const p4est_qcoord_t shift = P4EST_QUADRANT_LEN (q->level + 1); @@ -438,11 +395,10 @@ t8_subelement_scheme_quad_c::t8_element_child (const t8_element_t *elem, /* *INDENT-OFF* */ void -t8_subelement_scheme_quad_c::t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t - *elem, const int face, +t8_subelement_scheme_quad_c::t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t *elem, + const int face, const int num_neighbors, - t8_element_t - *neighbor_at_face[], + t8_element_t *neighbor_at_face[], int *neigh_face[]) { T8_ASSERT (t8_element_is_subelement (elem)); @@ -454,12 +410,9 @@ t8_subelement_scheme_quad_c::t8_element_get_sibling_neighbor_in_transition_cell * if face = 2, then it is the sibling subelement neighbor in clockwise enumeration. */ t8_element_copy (elem, neighbor_at_face[0]); - t8_quad_with_subelements * - pquad_w_sub_neighbor_at_face = - (t8_quad_with_subelements *) neighbor_at_face[0]; + t8_quad_with_subelements *pquad_w_sub_neighbor_at_face = (t8_quad_with_subelements *) neighbor_at_face[0]; - int - num_siblings = t8_element_num_siblings (elem); + int num_siblings = t8_element_num_siblings (elem); if (face == 0) { /* adjust subelement id counter clockwise */ @@ -489,26 +442,22 @@ t8_subelement_scheme_quad_c::t8_element_get_sibling_neighbor_in_transition_cell /* *INDENT-ON* */ void -t8_subelement_scheme_quad_c::t8_element_children (const t8_element_t *elem, - int length, - t8_element_t *c[]) const +t8_subelement_scheme_quad_c::t8_element_children (const t8_element_t *elem, int length, t8_element_t *c[]) const { /* if elem is a subelement, then this function will construct the children of its parent p4est quadrant */ - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements **pquad_w_sub_children = - (t8_quad_with_subelements **) c; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements **pquad_w_sub_children = (t8_quad_with_subelements **) c; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - int ichild; + int ichild; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (length == P4EST_CHILDREN); #ifdef T8_ENABLE_DEBUG { - int i; + int i; for (i = 0; i < P4EST_CHILDREN; i++) { T8_ASSERT (t8_element_is_valid (c[i])); } @@ -516,10 +465,8 @@ t8_subelement_scheme_quad_c::t8_element_children (const t8_element_t *elem, #endif /* set coordinates and levels of the children */ - p4est_quadrant_children (q, &pquad_w_sub_children[0]->p4q, - &pquad_w_sub_children[1]->p4q, - &pquad_w_sub_children[2]->p4q, - &pquad_w_sub_children[3]->p4q); + p4est_quadrant_children (q, &pquad_w_sub_children[0]->p4q, &pquad_w_sub_children[1]->p4q, + &pquad_w_sub_children[2]->p4q, &pquad_w_sub_children[3]->p4q); for (ichild = 0; ichild < P4EST_CHILDREN; ++ichild) { t8_element_reset_subelement_values (c[ichild]); @@ -530,22 +477,18 @@ t8_subelement_scheme_quad_c::t8_element_children (const t8_element_t *elem, int t8_subelement_scheme_quad_c::t8_element_child_id (const t8_element_t *elem) const { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q = &pquad_w_sub->p4q; T8_ASSERT (t8_element_is_valid (elem)); - return (t8_element_is_subelement (elem) ? pquad_w_sub->subelement_id : - p4est_quadrant_child_id (q)); + return (t8_element_is_subelement (elem) ? pquad_w_sub->subelement_id : p4est_quadrant_child_id (q)); } int -t8_subelement_scheme_quad_c::t8_element_ancestor_id (const t8_element_t *elem, - int level) const +t8_subelement_scheme_quad_c::t8_element_ancestor_id (const t8_element_t *elem, int level) const { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q = &pquad_w_sub->p4q; /* this function is not implemented for subelements */ @@ -558,13 +501,12 @@ int t8_subelement_scheme_quad_c::t8_element_is_family (t8_element_t *const *fam) const { /* Note that this test is very rudimentary, especially when there subelements are in fam */ - t8_quad_with_subelements **pquad_w_sub_family = - (t8_quad_with_subelements **) fam; + t8_quad_with_subelements **pquad_w_sub_family = (t8_quad_with_subelements **) fam; #ifdef T8_ENABLE_DEBUG { - int i; - int num_siblings = t8_element_num_siblings (fam[0]); + int i; + int num_siblings = t8_element_num_siblings (fam[0]); for (i = 0; i < num_siblings; i++) { T8_ASSERT (t8_element_is_valid (fam[i])); } @@ -580,29 +522,23 @@ t8_subelement_scheme_quad_c::t8_element_is_family (t8_element_t *const *fam) con /* If the first element of fam is no subelement we check the following elements of fam */ else { /* If any of the following elements is a subelement, then they can not form a family */ - if (pquad_w_sub_family[1]->transition_type != 0 || - pquad_w_sub_family[2]->transition_type != 0 || - pquad_w_sub_family[3]->transition_type != 0) { + if (pquad_w_sub_family[1]->transition_type != 0 || pquad_w_sub_family[2]->transition_type != 0 + || pquad_w_sub_family[3]->transition_type != 0) { return 0; } /* If all elements of fam are no subelements, then we can use the p4est check is_family */ else { - return p4est_quadrant_is_family (&pquad_w_sub_family[0]->p4q, - &pquad_w_sub_family[1]->p4q, - &pquad_w_sub_family[2]->p4q, - &pquad_w_sub_family[3]->p4q); + return p4est_quadrant_is_family (&pquad_w_sub_family[0]->p4q, &pquad_w_sub_family[1]->p4q, + &pquad_w_sub_family[2]->p4q, &pquad_w_sub_family[3]->p4q); } } } void -t8_subelement_scheme_quad_c::t8_element_set_linear_id (t8_element_t *elem, - int level, - t8_linearidx_t id) - const +t8_subelement_scheme_quad_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const { t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; - p4est_quadrant_t *q = &pquad_w_sub->p4q; + p4est_quadrant_t *q = &pquad_w_sub->p4q; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -616,12 +552,10 @@ t8_subelement_scheme_quad_c::t8_element_set_linear_id (t8_element_t *elem, } t8_linearidx_t - t8_subelement_scheme_quad_c::t8_element_get_linear_id (const t8_element_t - *elem, - int level) const +t8_subelement_scheme_quad_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const { t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; - p4est_quadrant_t *q = &pquad_w_sub->p4q; + p4est_quadrant_t *q = &pquad_w_sub->p4q; /* Note that the id of a subelement equals the id of its parent quadrant. * Therefore, the binary search (for example used in the leaf_face_neighbor function) @@ -634,18 +568,13 @@ t8_linearidx_t } void -t8_subelement_scheme_quad_c::t8_element_first_descendant (const t8_element_t - *elem, - t8_element_t *desc, - int level) const +t8_subelement_scheme_quad_c::t8_element_first_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const { - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements *pquad_w_sub_desc = - (t8_quad_with_subelements *) desc; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_desc = (t8_quad_with_subelements *) desc; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - p4est_quadrant_t *r = &pquad_w_sub_desc->p4q; + p4est_quadrant_t *r = &pquad_w_sub_desc->p4q; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (desc)); @@ -663,18 +592,13 @@ t8_subelement_scheme_quad_c::t8_element_first_descendant (const t8_element_t } void -t8_subelement_scheme_quad_c::t8_element_last_descendant (const t8_element_t - *elem, - t8_element_t *desc, - int level) const +t8_subelement_scheme_quad_c::t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const { - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements *pquad_w_sub_desc = - (t8_quad_with_subelements *) desc; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_desc = (t8_quad_with_subelements *) desc; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - p4est_quadrant_t *r = &pquad_w_sub_desc->p4q; + p4est_quadrant_t *r = &pquad_w_sub_desc->p4q; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (desc)); @@ -692,18 +616,15 @@ t8_subelement_scheme_quad_c::t8_element_last_descendant (const t8_element_t } void -t8_subelement_scheme_quad_c::t8_element_successor (const t8_element_t *elem1, - t8_element_t *elem2) const +t8_subelement_scheme_quad_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2) const { - const t8_quad_with_subelements *pquad_w_sub_elem1 = - (const t8_quad_with_subelements *) elem1; - t8_quad_with_subelements *pquad_w_sub_elem2 = - (t8_quad_with_subelements *) elem2; + const t8_quad_with_subelements *pquad_w_sub_elem1 = (const t8_quad_with_subelements *) elem1; + t8_quad_with_subelements *pquad_w_sub_elem2 = (t8_quad_with_subelements *) elem2; const p4est_quadrant_t *q = &pquad_w_sub_elem1->p4q; - p4est_quadrant_t *r = &pquad_w_sub_elem2->p4q; + p4est_quadrant_t *r = &pquad_w_sub_elem2->p4q; - t8_linearidx_t id; + t8_linearidx_t id; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem1)); @@ -720,20 +641,16 @@ t8_subelement_scheme_quad_c::t8_element_successor (const t8_element_t *elem1, } void -t8_subelement_scheme_quad_c::t8_element_nca (const t8_element_t *elem1, - const t8_element_t *elem2, +t8_subelement_scheme_quad_c::t8_element_nca (const t8_element_t *elem1, const t8_element_t *elem2, t8_element_t *nca) const { - const t8_quad_with_subelements *pquad_w_sub_elem1 = - (const t8_quad_with_subelements *) elem1; - const t8_quad_with_subelements *pquad_w_sub_elem2 = - (const t8_quad_with_subelements *) elem2; - t8_quad_with_subelements *pquad_w_sub_nca = - (t8_quad_with_subelements *) nca; + const t8_quad_with_subelements *pquad_w_sub_elem1 = (const t8_quad_with_subelements *) elem1; + const t8_quad_with_subelements *pquad_w_sub_elem2 = (const t8_quad_with_subelements *) elem2; + t8_quad_with_subelements *pquad_w_sub_nca = (t8_quad_with_subelements *) nca; const p4est_quadrant_t *q1 = &pquad_w_sub_elem1->p4q; const p4est_quadrant_t *q2 = &pquad_w_sub_elem2->p4q; - p4est_quadrant_t *r = &pquad_w_sub_nca->p4q; + p4est_quadrant_t *r = &pquad_w_sub_nca->p4q; T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); @@ -750,25 +667,19 @@ t8_subelement_scheme_quad_c::t8_element_nca (const t8_element_t *elem1, } t8_element_shape_t -t8_subelement_scheme_quad_c::t8_element_face_shape (const t8_element_t *elem, - int face) const +t8_subelement_scheme_quad_c::t8_element_face_shape (const t8_element_t *elem, int face) const { T8_ASSERT (t8_element_is_valid (elem)); return T8_ECLASS_LINE; } void -t8_subelement_scheme_quad_c::t8_element_children_at_face (const t8_element_t - *elem, int face, - t8_element_t - *children[], - int num_children, - int *child_indices) - const +t8_subelement_scheme_quad_c::t8_element_children_at_face (const t8_element_t *elem, int face, t8_element_t *children[], + int num_children, int *child_indices) const { #ifdef T8_ENABLE_DEBUG { - int i; + int i; for (i = 0; i < num_children; i++) { T8_ASSERT (t8_element_is_valid (children[i])); } @@ -797,8 +708,8 @@ t8_subelement_scheme_quad_c::t8_element_children_at_face (const t8_element_t */ T8_ASSERT (num_children == 2); - int first_child; - int second_child; + int first_child; + int second_child; /* TODO: Think about a short and easy bitwise formula. */ switch (face) { case 0: @@ -834,9 +745,7 @@ t8_subelement_scheme_quad_c::t8_element_children_at_face (const t8_element_t } int -t8_subelement_scheme_quad_c::t8_element_face_child_face (const t8_element_t - *elem, int face, - int face_child) const +t8_subelement_scheme_quad_c::t8_element_face_child_face (const t8_element_t *elem, int face, int face_child) const { T8_ASSERT (t8_element_is_valid (elem)); @@ -851,18 +760,15 @@ t8_subelement_scheme_quad_c::t8_element_face_child_face (const t8_element_t } int -t8_subelement_scheme_quad_c::t8_element_face_parent_face (const t8_element_t - *elem, - int face) const +t8_subelement_scheme_quad_c::t8_element_face_parent_face (const t8_element_t *elem, int face) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (face >= -1 && face <= P4EST_FACES); - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q = &pquad_w_sub->p4q; - int child_id; + int child_id; if (face == -1) { return -1; @@ -874,7 +780,7 @@ t8_subelement_scheme_quad_c::t8_element_face_parent_face (const t8_element_t if (face == 1) { /* In this case the face is a subface of the parent. We use the location function in order * to determine which of the parents faces intersects the subelements face. */ - int location[3] = { }; + int location[3] = {}; t8_element_get_location_of_subelement (elem, location); /* subelements in location are enumerated clockwise (not as quadrant faces) */ @@ -891,33 +797,25 @@ t8_subelement_scheme_quad_c::t8_element_face_parent_face (const t8_element_t /* Determine whether face is a subface of the parent. * This is the case if the child_id matches one of the faces corners */ child_id = p4est_quadrant_child_id (q); - if (child_id == p4est_face_corners[face][0] - || child_id == p4est_face_corners[face][1]) { + if (child_id == p4est_face_corners[face][0] || child_id == p4est_face_corners[face][1]) { return face; } return -1; } void -t8_subelement_scheme_quad_c::t8_element_transform_face (const t8_element_t - *elem1, - t8_element_t *elem2, - int orientation, - int sign, - int is_smaller_face) - const -{ - const t8_quad_with_subelements *pquad_w_sub_elem1 = - (const t8_quad_with_subelements *) elem1; - t8_quad_with_subelements *pquad_w_sub_elem2 = - (t8_quad_with_subelements *) elem2; +t8_subelement_scheme_quad_c::t8_element_transform_face (const t8_element_t *elem1, t8_element_t *elem2, int orientation, + int sign, int is_smaller_face) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem1 = (const t8_quad_with_subelements *) elem1; + t8_quad_with_subelements *pquad_w_sub_elem2 = (t8_quad_with_subelements *) elem2; const p4est_quadrant_t *qin = &pquad_w_sub_elem1->p4q; - p4est_quadrant_t *p = &pquad_w_sub_elem2->p4q; + p4est_quadrant_t *p = &pquad_w_sub_elem2->p4q; const p4est_quadrant_t *q; - p4est_qcoord_t h = P4EST_QUADRANT_LEN (qin->level); - p4est_qcoord_t x = qin->x; /* temp storage for x coordinate in case elem1 = elem 2 */ + p4est_qcoord_t h = P4EST_QUADRANT_LEN (qin->level); + p4est_qcoord_t x = qin->x; /* temp storage for x coordinate in case elem1 = elem 2 */ /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem1)); @@ -934,7 +832,7 @@ t8_subelement_scheme_quad_c::t8_element_transform_face (const t8_element_t t8_element_copy_surround (qin, (p4est_quadrant_t *) q); ((p4est_quadrant_t *) q)->x = qin->y; ((p4est_quadrant_t *) q)->y = x; - x = q->x; /* temp storage in case elem1 = elem 2 */ + x = q->x; /* temp storage in case elem1 = elem 2 */ } else { q = qin; @@ -967,7 +865,7 @@ t8_subelement_scheme_quad_c::t8_element_transform_face (const t8_element_t } switch (orientation) { - case 0: /* Nothing to do */ + case 0: /* Nothing to do */ p->x = q->x; p->y = q->y; break; @@ -992,24 +890,19 @@ t8_subelement_scheme_quad_c::t8_element_transform_face (const t8_element_t } int -t8_subelement_scheme_quad_c::t8_element_extrude_face (const t8_element_t - *face, - const t8_eclass_scheme_c - *face_scheme, - t8_element_t *elem, - int root_face) const +t8_subelement_scheme_quad_c::t8_element_extrude_face (const t8_element_t *face, const t8_eclass_scheme_c *face_scheme, + t8_element_t *elem, int root_face) const { /* build (extrude) elem from a given face element */ t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; - p4est_quadrant_t *q = &pquad_w_sub->p4q; + p4est_quadrant_t *q = &pquad_w_sub->p4q; - const t8_dline_t *l = (const t8_dline_t *) face; + const t8_dline_t *l = (const t8_dline_t *) face; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); T8_ASSERT (t8_element_is_valid (elem)); - T8_ASSERT (T8_COMMON_IS_TYPE - (face_scheme, const t8_default_scheme_line_c *)); + T8_ASSERT (T8_COMMON_IS_TYPE (face_scheme, const t8_default_scheme_line_c *)); T8_ASSERT (face_scheme->eclass == T8_ECLASS_LINE); T8_ASSERT (face_scheme->t8_element_is_valid (elem)); T8_ASSERT (0 <= root_face && root_face < P4EST_FACES); @@ -1057,8 +950,7 @@ t8_subelement_scheme_quad_c::t8_element_extrude_face (const t8_element_t } int -t8_subelement_scheme_quad_c::t8_element_tree_face (const t8_element_t *elem, - int face) const +t8_subelement_scheme_quad_c::t8_element_tree_face (const t8_element_t *elem, int face) const { T8_ASSERT (t8_element_is_valid (elem)); @@ -1078,24 +970,16 @@ t8_subelement_scheme_quad_c::t8_element_tree_face (const t8_element_t *elem, /** Construct the first descendant of an element that touches a given face. */ void -t8_subelement_scheme_quad_c::t8_element_first_descendant_face (const - t8_element_t - *elem, - int face, - t8_element_t - *first_desc, - int level) - const -{ - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements *pquad_w_sub_first_desc = - (t8_quad_with_subelements *) first_desc; +t8_subelement_scheme_quad_c::t8_element_first_descendant_face (const t8_element_t *elem, int face, + t8_element_t *first_desc, int level) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_first_desc = (t8_quad_with_subelements *) first_desc; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - p4est_quadrant_t *desc = &pquad_w_sub_first_desc->p4q; + p4est_quadrant_t *desc = &pquad_w_sub_first_desc->p4q; - int first_face_corner; + int first_face_corner; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -1111,22 +995,16 @@ t8_subelement_scheme_quad_c::t8_element_first_descendant_face (const /** Construct the last descendant of an element that touches a given face. */ void -t8_subelement_scheme_quad_c::t8_element_last_descendant_face (const - t8_element_t - *elem, int face, - t8_element_t - *last_desc, - int level) const -{ - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements *pquad_w_sub_last_desc = - (t8_quad_with_subelements *) last_desc; +t8_subelement_scheme_quad_c::t8_element_last_descendant_face (const t8_element_t *elem, int face, + t8_element_t *last_desc, int level) const +{ + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_last_desc = (t8_quad_with_subelements *) last_desc; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - p4est_quadrant_t *desc = &pquad_w_sub_last_desc->p4q; + p4est_quadrant_t *desc = &pquad_w_sub_last_desc->p4q; - int last_face_corner; + int last_face_corner; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -1142,22 +1020,16 @@ t8_subelement_scheme_quad_c::t8_element_last_descendant_face (const } void -t8_subelement_scheme_quad_c::t8_element_boundary_face (const t8_element_t - *elem, int face, - t8_element_t *boundary, - const - t8_eclass_scheme_c - *boundary_scheme) const -{ - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; +t8_subelement_scheme_quad_c::t8_element_boundary_face (const t8_element_t *elem, int face, t8_element_t *boundary, + const t8_eclass_scheme_c *boundary_scheme) const +{ + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q = &pquad_w_sub->p4q; - t8_dline_t *l = (t8_dline_t *) boundary; + t8_dline_t *l = (t8_dline_t *) boundary; T8_ASSERT (t8_element_is_valid (elem)); - T8_ASSERT (T8_COMMON_IS_TYPE - (boundary_scheme, const t8_default_scheme_line_c *)); + T8_ASSERT (T8_COMMON_IS_TYPE (boundary_scheme, const t8_default_scheme_line_c *)); T8_ASSERT (boundary_scheme->eclass == T8_ECLASS_LINE); T8_ASSERT (boundary_scheme->t8_element_is_valid (boundary)); @@ -1177,8 +1049,7 @@ t8_subelement_scheme_quad_c::t8_element_boundary_face (const t8_element_t * If face = 0 or face = 1 then l->x = q->y * if face = 2 or face = 3 then l->x = q->x */ - l->x = ((face >> 1 ? q->x : q->y) * - ((int64_t) T8_DLINE_ROOT_LEN) / P4EST_ROOT_LEN); + l->x = ((face >> 1 ? q->x : q->y) * ((int64_t) T8_DLINE_ROOT_LEN) / P4EST_ROOT_LEN); } else { /* face number 1 is the only face of a subelement that points outward of the transition cell */ @@ -1197,26 +1068,26 @@ t8_subelement_scheme_quad_c::t8_element_boundary_face (const t8_element_t * for a non split element (e2), the boundary face has the same level. */ - int location[3] = { }; /* location = {location of subelement (face number of transition cell), split, first or second element if split} */ + int location[3] + = {}; /* location = {location of subelement (face number of transition cell), split, first or second element if split} */ t8_element_get_location_of_subelement (elem, location); - int split = location[1]; - int second = location[2]; + int split = location[1]; + int second = location[2]; - if (split) { /* if the subelement lies at a split face */ + if (split) { /* if the subelement lies at a split face */ l->level = q->level + 1; - int len = - P4EST_QUADRANT_LEN (pquad_w_sub->p4q.level + 1); + int len = P4EST_QUADRANT_LEN (pquad_w_sub->p4q.level + 1); if (second) { /* second subelement */ if (location[0] == 0) { /* left face */ l->x = q->y + len; } - else if (location[0] == 1) { /* upper face */ + else if (location[0] == 1) { /* upper face */ l->x = q->x + len; } - else if (location[0] == 2) { /* right face */ + else if (location[0] == 2) { /* right face */ l->x = q->y; } - else { /* lower face */ + else { /* lower face */ l->x = q->x; } } @@ -1224,29 +1095,29 @@ t8_subelement_scheme_quad_c::t8_element_boundary_face (const t8_element_t if (location[0] == 0) { /* left face */ l->x = q->y; } - else if (location[0] == 1) { /* upper face */ + else if (location[0] == 1) { /* upper face */ l->x = q->x; } - else if (location[0] == 2) { /* right face */ + else if (location[0] == 2) { /* right face */ l->x = q->y + len; } - else { /* lower face */ + else { /* lower face */ l->x = q->x + len; } } } - else { /* if the subelement is not split */ + else { /* if the subelement is not split */ l->level = q->level; - if (location[0] == 0) { /* left face */ + if (location[0] == 0) { /* left face */ l->x = q->y; } - else if (location[0] == 1) { /* upper face */ + else if (location[0] == 1) { /* upper face */ l->x = q->x; } - else if (location[0] == 2) { /* right face */ + else if (location[0] == 2) { /* right face */ l->x = q->y; } - else { /* lower face */ + else { /* lower face */ l->x = q->x; } } @@ -1254,10 +1125,8 @@ t8_subelement_scheme_quad_c::t8_element_boundary_face (const t8_element_t } void -t8_subelement_scheme_quad_c::t8_element_boundary (const t8_element_t *elem, - int min_dim, int length, - t8_element_t **boundary) - const +t8_subelement_scheme_quad_c::t8_element_boundary (const t8_element_t *elem, int min_dim, int length, + t8_element_t **boundary) const { SC_ABORT ("Not implemented\n"); #if 0 @@ -1277,17 +1146,14 @@ t8_subelement_scheme_quad_c::t8_element_boundary (const t8_element_t *elem, } int -t8_subelement_scheme_quad_c::t8_element_is_root_boundary (const t8_element_t - *elem, - int face) const +t8_subelement_scheme_quad_c::t8_element_is_root_boundary (const t8_element_t *elem, int face) const { T8_ASSERT (t8_element_is_valid (elem)); - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q = &pquad_w_sub->p4q; - p4est_qcoord_t coord; + p4est_qcoord_t coord; /* In case of a subelement, we need to change its face number to the face number of the parent quad */ if (t8_element_is_subelement (elem)) { @@ -1295,7 +1161,7 @@ t8_subelement_scheme_quad_c::t8_element_is_root_boundary (const t8_element_t /* adjust face of subelement to face of parent */ face = t8_element_face_parent_face (elem, face); } - else { /* in case of a subelement and face 0 or 2 the face is no subface of the root boundary */ + else { /* in case of a subelement and face 0 or 2 the face is no subface of the root boundary */ return 0; } } @@ -1312,48 +1178,40 @@ t8_subelement_scheme_quad_c::t8_element_is_root_boundary (const t8_element_t } int -t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const - t8_element_t - *elem, - t8_element_t - *neigh, - int face, - int *neigh_face) - const +t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const t8_element_t *elem, t8_element_t *neigh, int face, + int *neigh_face) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (neigh)); T8_ASSERT (0 <= face && face < P4EST_FACES); - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements *pquad_w_sub_neigh = - (t8_quad_with_subelements *) neigh; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements *pquad_w_sub_neigh = (t8_quad_with_subelements *) neigh; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; - p4est_quadrant_t *n = &pquad_w_sub_neigh->p4q; + p4est_quadrant_t *n = &pquad_w_sub_neigh->p4q; /* In case of a subelement one should construct the face neighbor of the face-corresponding child quadrant * of the subelements parent quadrant. Therefore we might want to adjust the level and adapt the * anchor node. */ - if (t8_element_is_subelement (elem)) { /* if elem is a subelement */ + if (t8_element_is_subelement (elem)) { /* if elem is a subelement */ T8_ASSERT (0 <= face && face < T8_QUAD_SUBELEMENT_FACES); - if (face == 0) { /* in this case the face neighbor of the subelement is a sibling */ + if (face == 0) { /* in this case the face neighbor of the subelement is a sibling */ /* level and anchor stay the same */ n->x = q->x; n->y = q->y; n->level = q->level; } - if (face == 2) { /* in this case the face neighbor of the subelement is a sibling */ + if (face == 2) { /* in this case the face neighbor of the subelement is a sibling */ /* level and anchor stay the same */ n->x = q->x; n->y = q->y; n->level = q->level; } - if (face == 1) { /* in this case the face neighbor is no sibling */ - int location[3] = { }; + if (face == 1) { /* in this case the face neighbor is no sibling */ + int location[3] = {}; t8_element_get_location_of_subelement (elem, location); /* setting the anchor node of the neighbor element */ @@ -1363,11 +1221,11 @@ t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const /* half the side length of the transition cell of the subelement */ const p4est_qcoord_t shift = P4EST_QUADRANT_LEN (q->level + 1); - int split = location[1]; - int second = location[2]; + int split = location[1]; + int second = location[2]; /* we need to take into account whether the subelement is split or not */ - if (split) { /* split */ + if (split) { /* split */ /* increase the level by one */ n->level = q->level + 1; @@ -1382,7 +1240,7 @@ t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const n->y = q->y + shift; } } - else if (location[0] == 2) { /* right face */ + else if (location[0] == 2) { /* right face */ if (!second) { n->x = q->x + 2 * shift; n->y = q->y + shift; @@ -1391,7 +1249,7 @@ t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const n->x = q->x + 2 * shift; } } - else if (location[0] == 3) { /* lower face */ + else if (location[0] == 3) { /* lower face */ if (!second) { n->x = q->x + shift; n->y = q->y - shift; @@ -1400,7 +1258,7 @@ t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const n->y = q->y - shift; } } - else { /* upper face */ + else { /* upper face */ if (!second) { n->y = q->y + 2 * shift; } @@ -1411,7 +1269,7 @@ t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const } } - else { /* not split */ + else { /* not split */ /* level stays the same */ n->level = q->level; @@ -1419,19 +1277,19 @@ t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const if (location[0] == 0) { /* left face */ n->x = q->x - 2 * shift; } - else if (location[0] == 2) { /* right face */ + else if (location[0] == 2) { /* right face */ n->x = q->x + 2 * shift; } - else if (location[0] == 3) { /* lower face */ + else if (location[0] == 3) { /* lower face */ n->y = q->y - 2 * shift; } - else { /* upper face */ + else { /* upper face */ n->y = q->y + 2 * shift; } } } } - else { /* if elem is no subelement */ + else { /* if elem is no subelement */ /* Directly construct the face neighbor */ p4est_quadrant_face_neighbor (q, face, n); } @@ -1444,7 +1302,7 @@ t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const if (t8_element_is_subelement (elem)) { if (face == 1) { /* return dual face with respect to neighboring quad element */ - int location[3] = { }; + int location[3] = {}; t8_element_get_location_of_subelement (elem, location); /* if the face is pointing outwards, then we set the face equal to the transition cell face and determine its dual face. * Compute the face number as seen from q. @@ -1474,11 +1332,10 @@ t8_subelement_scheme_quad_c::t8_element_face_neighbor_inside (const } void -t8_subelement_scheme_quad_c::t8_element_anchor (const t8_element_t *elem, - int coord[3]) const +t8_subelement_scheme_quad_c::t8_element_anchor (const t8_element_t *elem, int coord[3]) const { t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; - p4est_quadrant_t *q = &pquad_w_sub->p4q; + p4est_quadrant_t *q = &pquad_w_sub->p4q; /* this function is not implemented for subelements */ T8_ASSERT (!t8_element_is_subelement (elem)); @@ -1506,27 +1363,21 @@ t8_subelement_scheme_quad_c::t8_element_refines_irregular () const void t8_subelement_scheme_quad_c::t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const - { +{ SC_ABORT ("This function is not implemented for the given scheme.\n"); } void -t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, - double *out_coords) - const +t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, + const size_t num_coords, double *out_coords) const { SC_ABORT ("This function is not implemented for the given scheme.\n"); } void -t8_subelement_scheme_quad_c::t8_element_vertex_reference_coords (const - t8_element_t - *t, - int vertex, - double - coords[]) - const -{ - int coords_int[2] = { }; +t8_subelement_scheme_quad_c::t8_element_vertex_reference_coords (const t8_element_t *t, int vertex, + double coords[]) const +{ + int coords_int[2] = {}; t8_element_vertex_coords (t, vertex, coords_int); /* We divide the integer coordinates by the root length of the quad @@ -1536,18 +1387,15 @@ t8_subelement_scheme_quad_c::t8_element_vertex_reference_coords (const } void -t8_subelement_scheme_quad_c::t8_element_vertex_coords (const t8_element_t - *elem, int vertex, - int coords[]) const +t8_subelement_scheme_quad_c::t8_element_vertex_coords (const t8_element_t *elem, int vertex, int coords[]) const { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q1 = &pquad_w_sub->p4q; T8_ASSERT (t8_element_is_valid (elem)); if (!t8_element_is_subelement (elem)) { - int len; + int len; T8_ASSERT (0 <= vertex && vertex < 4); /* Get the length of the quadrant */ @@ -1564,24 +1412,17 @@ t8_subelement_scheme_quad_c::t8_element_vertex_coords (const t8_element_t } void -t8_subelement_scheme_quad_c::t8_element_vertex_coords_of_subelement (const - t8_element_t - *elem, - int - vertex, - int - coords[]) - const -{ - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; +t8_subelement_scheme_quad_c::t8_element_vertex_coords_of_subelement (const t8_element_t *elem, int vertex, + int coords[]) const +{ + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q1 = &pquad_w_sub->p4q; - int len; + int len; T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_subelement (elem)); - T8_ASSERT (vertex >= 0 && vertex < T8_QUAD_SUBELEMENT_FACES); /* all subelements are triangles */ + T8_ASSERT (vertex >= 0 && vertex < T8_QUAD_SUBELEMENT_FACES); /* all subelements are triangles */ /* get the length of the current quadrant */ len = P4EST_QUADRANT_LEN (q1->level); @@ -1603,31 +1444,29 @@ t8_subelement_scheme_quad_c::t8_element_vertex_coords_of_subelement (const * (second face, split, first subelement at this face) */ /* get location information of the given subelement */ - int location[3] = { }; + int location[3] = {}; t8_element_get_location_of_subelement (elem, location); /* the face number, the subelement is adjacent to */ - int face_number = location[0]; + int face_number = location[0]; /* = 1, if the adjacent face is split and = 0, if not */ - int split = location[1]; + int split = location[1]; /* = 0, if the subelement is the first (of two) subelements, at the adjacent face and = 1 if it is the second */ - int sub_face_id = location[2]; + int sub_face_id = location[2]; /* Check, whether the get_location function provides meaningful location data */ - T8_ASSERT (face_number == 0 || face_number == 1 || face_number == 2 - || face_number == 3); - T8_ASSERT ((split == 0 && sub_face_id == 0) - || (split == 1 && (sub_face_id == 0 || sub_face_id == 1))); + T8_ASSERT (face_number == 0 || face_number == 1 || face_number == 2 || face_number == 3); + T8_ASSERT ((split == 0 && sub_face_id == 0) || (split == 1 && (sub_face_id == 0 || sub_face_id == 1))); coords[0] = q1->x; coords[1] = q1->y; /* using the location data to determine vertex coordinates */ - if (vertex == 0) { /* vertex 0 (the first vertex always equals the center of the element) */ + if (vertex == 0) { /* vertex 0 (the first vertex always equals the center of the element) */ coords[0] += len / 2; coords[1] += len / 2; - } /* end of vertex == 0 */ - else if (vertex == 1) { /* vertex 1 */ + } /* end of vertex == 0 */ + else if (vertex == 1) { /* vertex 1 */ if (face_number == 0) { if (split && sub_face_id) { coords[1] += len / 2; @@ -1652,8 +1491,8 @@ t8_subelement_scheme_quad_c::t8_element_vertex_coords_of_subelement (const coords[0] -= len / 2; } } - } /* end of vertex == 1 */ - else { /* vertex 2 */ + } /* end of vertex == 1 */ + else { /* vertex 2 */ if (face_number == 0) { coords[1] += len; if (split && !sub_face_id) { @@ -1678,18 +1517,14 @@ t8_subelement_scheme_quad_c::t8_element_vertex_coords_of_subelement (const coords[0] += len / 2; } } - } /* end of vertex == 2 */ + } /* end of vertex == 2 */ } void -t8_subelement_scheme_quad_c::t8_element_to_transition_cell (const t8_element_t - *elem, int type, - t8_element_t *c[]) +t8_subelement_scheme_quad_c::t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *c[]) { - const t8_quad_with_subelements *pquad_w_sub_elem = - (const t8_quad_with_subelements *) elem; - t8_quad_with_subelements **pquad_w_sub_subelement = - (t8_quad_with_subelements **) c; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + t8_quad_with_subelements **pquad_w_sub_subelement = (t8_quad_with_subelements **) c; const p4est_quadrant_t *q = &pquad_w_sub_elem->p4q; @@ -1698,12 +1533,11 @@ t8_subelement_scheme_quad_c::t8_element_to_transition_cell (const t8_element_t T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (type >= 0 && type <= T8_SUB_QUAD_MAX_TRANSITION_TYPE); - int num_subelements = - t8_element_get_number_of_subelements (type); + int num_subelements = t8_element_get_number_of_subelements (type); #ifdef T8_ENABLE_DEBUG { - int j; + int j; for (j = 0; j < num_subelements; j++) { T8_ASSERT (t8_element_is_valid (c[j])); } @@ -1711,7 +1545,7 @@ t8_subelement_scheme_quad_c::t8_element_to_transition_cell (const t8_element_t #endif /* get the length of a children-quadrant */ - const int8_t level = (int8_t) (q->level); + const int8_t level = (int8_t) (q->level); T8_ASSERT (p4est_quadrant_is_extended (q)); T8_ASSERT (q->level < P4EST_QMAXLEVEL); @@ -1730,7 +1564,7 @@ t8_subelement_scheme_quad_c::t8_element_to_transition_cell (const t8_element_t * Sub_ids are counted clockwise, starting with the (lower) left subelement with id 0. * Note, that we do not change the p4est quadrant. */ - int sub_id_counter = 0; + int sub_id_counter = 0; for (sub_id_counter = 0; sub_id_counter < num_subelements; sub_id_counter++) { pquad_w_sub_subelement[sub_id_counter]->p4q.x = q->x; pquad_w_sub_subelement[sub_id_counter]->p4q.y = q->y; @@ -1740,23 +1574,22 @@ t8_subelement_scheme_quad_c::t8_element_to_transition_cell (const t8_element_t pquad_w_sub_subelement[sub_id_counter]->subelement_id = sub_id_counter; T8_ASSERT (t8_element_is_valid (c[sub_id_counter])); - t8_element_copy_surround (q, - &pquad_w_sub_subelement[sub_id_counter]->p4q); + t8_element_copy_surround (q, &pquad_w_sub_subelement[sub_id_counter]->p4q); } } int -t8_subelement_scheme_quad_c::t8_element_get_number_of_subelements (int - transition_type) - const +t8_subelement_scheme_quad_c::t8_element_get_number_of_subelements (int transition_type) const { /* we could return 0 for transition type 0 but we will assert this case for safety reasons */ T8_ASSERT (transition_type != 0); /* consider transition_type 13 = 1101 in base two -> there are 4 + (1+1+0+1) = 7 subelements */ - int num_hanging_faces = 0; - int ichild; - for (ichild = 0; ichild < P4EST_FACES; ichild++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ + int num_hanging_faces = 0; + int ichild; + for ( + ichild = 0; ichild < P4EST_FACES; + ichild++) { /* Count the number of ones of the binary transition type. This number equals the number of hanging faces. */ num_hanging_faces += (transition_type & (1 << ichild)) >> ichild; } @@ -1765,15 +1598,9 @@ t8_subelement_scheme_quad_c::t8_element_get_number_of_subelements (int } void -t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const - t8_element_t - *elem, - int - location - []) const +t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const t8_element_t *elem, int location[]) const { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; /* this function only works for subelements */ T8_ASSERT (t8_element_is_subelement (elem)); @@ -1805,41 +1632,40 @@ t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const * The location array for the above example would be {1,1,1} (upper face, split = true, second subelement at the upper face). */ /* 1) convert the transition type from a decimal to a binary representation */ - int type = pquad_w_sub->transition_type; - int binary_array[P4EST_FACES] = { }; + int type = pquad_w_sub->transition_type; + int binary_array[P4EST_FACES] = {}; - int iface; + int iface; - for (iface = 0; iface < P4EST_FACES; iface++) { /* need an array with 4 elements to store all subelement types of the quad scheme from 1 to 15 ({0,0,0,1} to {1,1,1,1}) */ + for ( + iface = 0; iface < P4EST_FACES; + iface++) { /* need an array with 4 elements to store all subelement types of the quad scheme from 1 to 15 ({0,0,0,1} to {1,1,1,1}) */ binary_array[(P4EST_FACES - 1) - iface] = (type & (1 << iface)) >> iface; - } /* we now got a binary representation of the transition type, bitwise stored in an array */ + } /* we now got a binary representation of the transition type, bitwise stored in an array */ /* 2) rearrange the binary representation to be in clockwise order */ - int binary_array_temp[P4EST_FACES] = { }; + int binary_array_temp[P4EST_FACES] = {}; - for (iface = 0; iface < P4EST_FACES; iface++) { /* copying the binary array */ + for (iface = 0; iface < P4EST_FACES; iface++) { /* copying the binary array */ binary_array_temp[iface] = binary_array[iface]; } - for (iface = 0; iface < P4EST_FACES; iface++) { /* bringing the entries of binary array into clockwise order */ - binary_array[iface] = - binary_array_temp[subelement_location_to_parent_face[iface]]; + for (iface = 0; iface < P4EST_FACES; iface++) { /* bringing the entries of binary array into clockwise order */ + binary_array[iface] = binary_array_temp[subelement_location_to_parent_face[iface]]; } /* 3) use the rearranged binary representation, and the sub_id to determine the location of the subelement and store these information in an array */ /* 3.1) location[0] -> the face_number, the subelement is adjacent to */ /* 3.2) location[1] -> if the face is split or not */ /* 3.3) location[2] -> if the subelement is the first or second subelement of the face (always the first, if the face is not split) */ - T8_ASSERT (pquad_w_sub->subelement_id < - t8_element_get_number_of_subelements - (pquad_w_sub->transition_type)); + T8_ASSERT (pquad_w_sub->subelement_id < t8_element_get_number_of_subelements (pquad_w_sub->transition_type)); - int sub_id = pquad_w_sub->subelement_id; - int sub_face_id; - int face_number = -1; - int split; + int sub_id = pquad_w_sub->subelement_id; + int sub_face_id; + int face_number = -1; + int split; - int cum_neigh_array[P4EST_FACES] = { }; + int cum_neigh_array[P4EST_FACES] = {}; /* construct a cumulative array of the number of neighbors from face 0 to face 3 */ cum_neigh_array[0] = binary_array[0] + 1; @@ -1853,8 +1679,7 @@ t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const } else { for (iface = 0; iface < P4EST_FACES - 1; ++iface) { - if (sub_id >= cum_neigh_array[iface] - && sub_id < cum_neigh_array[iface + 1]) { + if (sub_id >= cum_neigh_array[iface] && sub_id < cum_neigh_array[iface + 1]) { face_number = iface + 1; break; } @@ -1866,18 +1691,18 @@ t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const /* 3.2) determine, whether the face is split or not */ if (binary_array[face_number] == 0) { - split = 0; /* the face is not split */ + split = 0; /* the face is not split */ } else { - split = 1; /* the face is split */ + split = 1; /* the face is split */ } /* 3.3) determine, whether the subelement is the first or the second subelement at the face */ if (sub_id + 1 == cum_neigh_array[face_number] && split == 1) { - sub_face_id = 1; /* second subelement */ + sub_face_id = 1; /* second subelement */ } else { - sub_face_id = 0; /* first subelement */ + sub_face_id = 0; /* first subelement */ } location[0] = face_number; @@ -1886,8 +1711,7 @@ t8_subelement_scheme_quad_c::t8_element_get_location_of_subelement (const } void -t8_subelement_scheme_quad_c::t8_element_reset_subelement_values (t8_element * - elem) const +t8_subelement_scheme_quad_c::t8_element_reset_subelement_values (t8_element *elem) const { t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; @@ -1896,16 +1720,10 @@ t8_subelement_scheme_quad_c::t8_element_reset_subelement_values (t8_element * } void -t8_subelement_scheme_quad_c::t8_element_copy_subelement_values (const - t8_element * - source, - t8_element * - dest) const +t8_subelement_scheme_quad_c::t8_element_copy_subelement_values (const t8_element *source, t8_element *dest) const { - const t8_quad_with_subelements *pquad_w_sub_source = - (const t8_quad_with_subelements *) source; - t8_quad_with_subelements *pquad_w_sub_dest = - (t8_quad_with_subelements *) dest; + const t8_quad_with_subelements *pquad_w_sub_source = (const t8_quad_with_subelements *) source; + t8_quad_with_subelements *pquad_w_sub_dest = (t8_quad_with_subelements *) dest; pquad_w_sub_dest->transition_type = pquad_w_sub_source->transition_type; pquad_w_sub_dest->transition_type = pquad_w_sub_source->transition_type; @@ -1913,12 +1731,9 @@ t8_subelement_scheme_quad_c::t8_element_copy_subelement_values (const } int -t8_subelement_scheme_quad_c::t8_element_is_subelement (const - t8_element * - elem) const +t8_subelement_scheme_quad_c::t8_element_is_subelement (const t8_element *elem) const { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; T8_ASSERT (pquad_w_sub->transition_type >= 0); @@ -1929,23 +1744,19 @@ t8_subelement_scheme_quad_c::t8_element_is_subelement (const } int -t8_subelement_scheme_quad_c::t8_element_get_transition_type (const - t8_element * - elem) +t8_subelement_scheme_quad_c::t8_element_get_transition_type (const t8_element *elem) { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; return pquad_w_sub->transition_type; } int -t8_subelement_scheme_quad_c::t8_element_get_subelement_id (const t8_element * elem) const +t8_subelement_scheme_quad_c::t8_element_get_subelement_id (const t8_element *elem) const { T8_ASSERT (t8_element_is_valid (elem)); - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; return pquad_w_sub->subelement_id; } @@ -1955,8 +1766,7 @@ t8_subelement_scheme_quad_c::t8_element_shape (const t8_element_t *elem) const { T8_ASSERT (t8_element_is_valid (elem)); - return (t8_element_is_subelement (elem) ? T8_ECLASS_TRIANGLE : - T8_ECLASS_QUAD); + return (t8_element_is_subelement (elem) ? T8_ECLASS_TRIANGLE : T8_ECLASS_QUAD); } int @@ -1964,13 +1774,13 @@ t8_subelement_scheme_quad_c::t8_element_num_corners (const t8_element_t *elem) c { T8_ASSERT (t8_element_is_valid (elem)); - return (t8_element_is_subelement (elem) ? T8_QUAD_SUBELEMENT_FACES : - P4EST_FACES); + return (t8_element_is_subelement (elem) ? T8_QUAD_SUBELEMENT_FACES : P4EST_FACES); } int -t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell - (const t8_element_t *elem, const t8_element_t *pseudo_neigh, int elem_face) +t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, + const t8_element_t *pseudo_neigh, + int elem_face) { /* In this function, we assume pseudo_neigh to be a random subelement of a transition cell that includes * the real neighbor of elem at face elem_face. This function will output the subelement_id of the real neighbor of elem. */ @@ -1980,16 +1790,12 @@ t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell /* we expect neigh to be a element in a transition cell, thus to be a subelement */ T8_ASSERT (t8_element_is_subelement (pseudo_neigh)); - const t8_quad_with_subelements * - pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; - const t8_quad_with_subelements * - pquad_w_sub_pseudo_neigh = - (const t8_quad_with_subelements *) pseudo_neigh; + const t8_quad_with_subelements *pquad_w_sub_elem = (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub_pseudo_neigh = (const t8_quad_with_subelements *) pseudo_neigh; /* In the following, all possible neighbor configurations are defined, such that subelement neighbors can be * identified in LFN_transitioned. */ - if (pquad_w_sub_elem->transition_type != 0 - && (elem_face == 0 || elem_face == 2)) { + if (pquad_w_sub_elem->transition_type != 0 && (elem_face == 0 || elem_face == 2)) { /* In this case, we have the following situation: * * x - - - - - - - x @@ -2004,19 +1810,16 @@ t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell * * Elem and face 0 or face 2 is given and a random sibling subelement neigh is given, too. * We are searching for the subelement id of the real neighbor N_f0 or N_f2, depending on the face number. */ - int - shift; + int shift; if (elem_face == 0) { shift = -1; } if (elem_face == 2) { shift = 1; } - int - num_subelements = - t8_element_get_number_of_subelements - (pquad_w_sub_elem->transition_type); - return ((pquad_w_sub_elem->subelement_id + shift) + num_subelements) % num_subelements; /* the neighbor is directly before or after elem modulo the number of subelements in the transition cell */ + int num_subelements = t8_element_get_number_of_subelements (pquad_w_sub_elem->transition_type); + return ((pquad_w_sub_elem->subelement_id + shift) + num_subelements) + % num_subelements; /* the neighbor is directly before or after elem modulo the number of subelements in the transition cell */ } /* Below are the cases in which the neighbor can not be identified as simple as above. * The idea is to fill a location array with the desired properties of the real neighbor. @@ -2040,98 +1843,93 @@ t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell * Note that both transition cells can have different levels. */ /* get the location of elem */ - int - location_elem[3] = { }; /* {face, is_split, number of subelement at face} */ + int location_elem[3] = {}; /* {face, is_split, number of subelement at face} */ t8_element_get_location_of_subelement (elem, location_elem); /* Initialize the location array of the real neighbor. */ - int - location_neigh[3] = { -1, -1, -1 }; + int location_neigh[3] = { -1, -1, -1 }; /* the pseudo_neigh tranaition cell has a lower level than the elem transition cell */ if (pquad_w_sub_pseudo_neigh->p4q.level < pquad_w_sub_elem->p4q.level) { - if (location_elem[0] == 0) { /* left face of transition cell */ + if (location_elem[0] == 0) { /* left face of transition cell */ if (pquad_w_sub_pseudo_neigh->p4q.y == pquad_w_sub_elem->p4q.y) { - location_neigh[0] = 2; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 1; /* second subelement at face */ + location_neigh[0] = 2; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* second subelement at face */ } if (pquad_w_sub_pseudo_neigh->p4q.y != pquad_w_sub_elem->p4q.y) { - location_neigh[0] = 2; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 0; /* first subelement at face */ + location_neigh[0] = 2; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ } } - if (location_elem[0] == 1) { /* upper face of transition cell */ + if (location_elem[0] == 1) { /* upper face of transition cell */ if (pquad_w_sub_pseudo_neigh->p4q.x == pquad_w_sub_elem->p4q.x) { - location_neigh[0] = 3; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 1; /* first or second subelement at face */ + location_neigh[0] = 3; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* first or second subelement at face */ } if (pquad_w_sub_pseudo_neigh->p4q.x != pquad_w_sub_elem->p4q.x) { - location_neigh[0] = 3; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 0; /* first subelement at face */ + location_neigh[0] = 3; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ } } - if (location_elem[0] == 2) { /* right face of transition cell */ + if (location_elem[0] == 2) { /* right face of transition cell */ if (pquad_w_sub_pseudo_neigh->p4q.y == pquad_w_sub_elem->p4q.y) { - location_neigh[0] = 0; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 0; /* first subelement at face */ + location_neigh[0] = 0; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ } if (pquad_w_sub_pseudo_neigh->p4q.y != pquad_w_sub_elem->p4q.y) { - location_neigh[0] = 0; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 1; /* first or second subelement at face */ + location_neigh[0] = 0; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* first or second subelement at face */ } } - if (location_elem[0] == 3) { /* lower face of transition cell */ + if (location_elem[0] == 3) { /* lower face of transition cell */ if (pquad_w_sub_pseudo_neigh->p4q.x == pquad_w_sub_elem->p4q.x) { - location_neigh[0] = 1; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 0; /* first subelement at face */ + location_neigh[0] = 1; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ } if (pquad_w_sub_pseudo_neigh->p4q.x != pquad_w_sub_elem->p4q.x) { - location_neigh[0] = 1; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 1; /* second subelement at face */ + location_neigh[0] = 1; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* second subelement at face */ } } } /* the pseudo_neigh tranaition cell has not a lower level than the elem transition cell */ if (pquad_w_sub_pseudo_neigh->p4q.level >= pquad_w_sub_elem->p4q.level) { - if (location_elem[0] == 0) { /* left face of transition cell */ - location_neigh[0] = 2; /* face */ - location_neigh[1] = 0; /* not split */ - location_neigh[2] = 0; /* first (only) subelement at face */ + if (location_elem[0] == 0) { /* left face of transition cell */ + location_neigh[0] = 2; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ } - if (location_elem[0] == 1) { /* upper face of transition cell */ - location_neigh[0] = 3; /* face */ - location_neigh[1] = 0; /* not split */ - location_neigh[2] = 0; /* first (only) subelement at face */ + if (location_elem[0] == 1) { /* upper face of transition cell */ + location_neigh[0] = 3; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ } - if (location_elem[0] == 2) { /* right face of transition cell */ - location_neigh[0] = 0; /* face */ - location_neigh[1] = 0; /* not split */ - location_neigh[2] = 0; /* first (only) subelement at face */ + if (location_elem[0] == 2) { /* right face of transition cell */ + location_neigh[0] = 0; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ } - if (location_elem[0] == 3) { /* lower face of transition cell */ - location_neigh[0] = 1; /* face */ - location_neigh[1] = 0; /* not split */ - location_neigh[2] = 0; /* first (only) subelement at face */ + if (location_elem[0] == 3) { /* lower face of transition cell */ + location_neigh[0] = 1; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ } } /* check, that a neighbor is found and the location array is adjusted */ - T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 - && location_neigh[2] >= 0); + T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 && location_neigh[2] >= 0); /* Depending on the location of elem, we have filled location_neigh with the data of the real neighbor. * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ - return - t8_element_get_id_from_location (t8_element_get_transition_type - (pseudo_neigh), location_neigh); + return t8_element_get_id_from_location (t8_element_get_transition_type (pseudo_neigh), location_neigh); } if (!t8_element_is_subelement (elem)) { /* In this case, we have the following situation: @@ -2151,57 +1949,56 @@ t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell * Note that the transition cell of pseudo_neigh and elem can have different levels. */ /* Initialize the location array of the real neighbor. */ - int - location_neigh[3] = { -1, -1, -1 }; + int location_neigh[3] = { -1, -1, -1 }; /* the pseudo_neigh tranaition cell has a lower level than elem */ if (pquad_w_sub_pseudo_neigh->p4q.level < pquad_w_sub_elem->p4q.level) { - if (elem_face == 0) { /* left face */ + if (elem_face == 0) { /* left face */ if (pquad_w_sub_pseudo_neigh->p4q.y == pquad_w_sub_elem->p4q.y) { - location_neigh[0] = 2; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 1; /* second subelement at face */ + location_neigh[0] = 2; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* second subelement at face */ } if (pquad_w_sub_pseudo_neigh->p4q.y != pquad_w_sub_elem->p4q.y) { - location_neigh[0] = 2; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 0; /* first subelement at face */ + location_neigh[0] = 2; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ } } - if (elem_face == 1) { /* right face */ + if (elem_face == 1) { /* right face */ if (pquad_w_sub_pseudo_neigh->p4q.y == pquad_w_sub_elem->p4q.y) { - location_neigh[0] = 0; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 0; /* first subelement at face */ + location_neigh[0] = 0; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ } if (pquad_w_sub_pseudo_neigh->p4q.y != pquad_w_sub_elem->p4q.y) { - location_neigh[0] = 0; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 1; /* first or second subelement at face */ + location_neigh[0] = 0; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* first or second subelement at face */ } } - if (elem_face == 2) { /* lower face */ + if (elem_face == 2) { /* lower face */ if (pquad_w_sub_pseudo_neigh->p4q.x == pquad_w_sub_elem->p4q.x) { - location_neigh[0] = 1; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 0; /* first subelement at face */ + location_neigh[0] = 1; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ } if (pquad_w_sub_pseudo_neigh->p4q.x != pquad_w_sub_elem->p4q.x) { - location_neigh[0] = 1; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 1; /* second subelement at face */ + location_neigh[0] = 1; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* second subelement at face */ } } - if (elem_face == 3) { /* upper face */ + if (elem_face == 3) { /* upper face */ if (pquad_w_sub_pseudo_neigh->p4q.x == pquad_w_sub_elem->p4q.x) { - location_neigh[0] = 3; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 1; /* first or second subelement at face */ + location_neigh[0] = 3; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 1; /* first or second subelement at face */ } if (pquad_w_sub_pseudo_neigh->p4q.x != pquad_w_sub_elem->p4q.x) { - location_neigh[0] = 3; /* face */ - location_neigh[1] = 1; /* split */ - location_neigh[2] = 0; /* first subelement at face */ + location_neigh[0] = 3; /* face */ + location_neigh[1] = 1; /* split */ + location_neigh[2] = 0; /* first subelement at face */ } } } @@ -2209,54 +2006,50 @@ t8_subelement_scheme_quad_c::t8_element_find_neighbor_in_transition_cell * Note that the level of the trnasition cell can not be higher as the level of elem in this case, * since elem would then be a subelement in a transition cell. */ if (pquad_w_sub_pseudo_neigh->p4q.level == pquad_w_sub_elem->p4q.level) { - if (elem_face == 0) { /* left face */ - location_neigh[0] = 2; /* face */ - location_neigh[1] = 0; /* not split */ - location_neigh[2] = 0; /* first (only) subelement at face */ + if (elem_face == 0) { /* left face */ + location_neigh[0] = 2; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ } - if (elem_face == 1) { /* right face */ - location_neigh[0] = 0; /* face */ - location_neigh[1] = 0; /* not split */ - location_neigh[2] = 0; /* first (only) subelement at face */ + if (elem_face == 1) { /* right face */ + location_neigh[0] = 0; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ } - if (elem_face == 2) { /* lower face */ - location_neigh[0] = 1; /* face */ - location_neigh[1] = 0; /* not split */ - location_neigh[2] = 0; /* first (only) subelement at face */ + if (elem_face == 2) { /* lower face */ + location_neigh[0] = 1; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ } - if (elem_face == 3) { /* upper face */ - location_neigh[0] = 3; /* face */ - location_neigh[1] = 0; /* not split */ - location_neigh[2] = 0; /* first (only) subelement at face */ + if (elem_face == 3) { /* upper face */ + location_neigh[0] = 3; /* face */ + location_neigh[1] = 0; /* not split */ + location_neigh[2] = 0; /* first (only) subelement at face */ } } /* check, that a neighbor is found and the location array is adjusted */ - T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 - && location_neigh[2] >= 0); + T8_ASSERT (location_neigh[0] >= 0 && location_neigh[1] >= 0 && location_neigh[2] >= 0); /* Depending on the location of elem, we have filled location_neigh with the data of the real neighbor. * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ - return - t8_element_get_id_from_location (t8_element_get_transition_type - (pseudo_neigh), location_neigh); + return t8_element_get_id_from_location (t8_element_get_transition_type (pseudo_neigh), location_neigh); } - return -1; /* return negative if no neighbor element could be found */ + return -1; /* return negative if no neighbor element could be found */ } int -t8_subelement_scheme_quad_c::t8_element_get_id_from_location (int type, - int location[]) +t8_subelement_scheme_quad_c::t8_element_get_id_from_location (int type, int location[]) { T8_ASSERT (type >= 0 && type <= T8_SUB_QUAD_MAX_TRANSITION_TYPE); - int sub_id, subelements_count = 0; - double type_temp = double (type); // would work for ints but we use libc pow(double, double) - int binary_type[4] = { }; - int binary_type_clockwise[4] = { }; + int sub_id, subelements_count = 0; + double type_temp = double (type); // would work for ints but we use libc pow(double, double) + int binary_type[4] = {}; + int binary_type_clockwise[4] = {}; /* get the type as a binary array */ - int iface; + int iface; for (iface = 0; iface < P4EST_FACES; iface++) { if (type_temp >= pow (2.0, 4 - (iface + 1))) { binary_type[iface] = 1; @@ -2267,13 +2060,13 @@ t8_subelement_scheme_quad_c::t8_element_get_id_from_location (int type, } } - for (iface = 0; iface < P4EST_FACES; iface++) { /* rearrange the binary type to be in clockwise order of the faces, starting with the left face */ - binary_type_clockwise[iface] = - binary_type[subelement_location_to_parent_face[iface]]; + for (iface = 0; iface < P4EST_FACES; + iface++) { /* rearrange the binary type to be in clockwise order of the faces, starting with the left face */ + binary_type_clockwise[iface] = binary_type[subelement_location_to_parent_face[iface]]; } /* count the number of elements up to the given location */ - int element_count; + int element_count; for (element_count = 0; element_count <= location[0]; element_count++) { if (element_count == location[0]) { if (location[1] == 0) { @@ -2300,24 +2093,22 @@ t8_subelement_scheme_quad_c::t8_element_get_id_from_location (int type, } int -t8_subelement_scheme_quad_c::t8_element_get_face_number_of_hypotenuse (const - t8_element_t - *elem) +t8_subelement_scheme_quad_c::t8_element_get_face_number_of_hypotenuse (const t8_element_t *elem) { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_subelement (elem)); - int location[3] = { }; + int location[3] = {}; t8_element_get_location_of_subelement (elem, location); - int split = location[1]; - int second = location[2]; + int split = location[1]; + int second = location[2]; - if (!split) { /* if the face is not split, then the hypotenuse is always face number one */ + if (!split) { /* if the face is not split, then the hypotenuse is always face number one */ return 1; } else { - if (!second) { /* otherwise, the subelment is mirrored, depending on the value of 'second' */ + if (!second) { /* otherwise, the subelment is mirrored, depending on the value of 'second' */ return 0; } else { @@ -2332,13 +2123,12 @@ t8_subelement_scheme_quad_c::t8_element_new (int length, t8_element_t **elem) co /* allocate memory */ t8_default_scheme_common_c::t8_element_new (length, elem); - int elem_count; + int elem_count; for (elem_count = 0; elem_count < length; elem_count++) { - t8_quad_with_subelements *pquad_w_sub = - (t8_quad_with_subelements *) elem[elem_count]; + t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem[elem_count]; t8_element_init (1, elem[elem_count]); /* set dimension of quad to 2 */ - T8_QUAD_SET_TDIM ((p4est_quadrant_t *) & pquad_w_sub->p4q, 2); + T8_QUAD_SET_TDIM ((p4est_quadrant_t *) &pquad_w_sub->p4q, 2); } } @@ -2347,7 +2137,7 @@ t8_subelement_scheme_quad_c::t8_element_init (int length, t8_element_t *elem) co { t8_quad_with_subelements *pquad_w_sub = (t8_quad_with_subelements *) elem; - int elem_count; + int elem_count; for (elem_count = 0; elem_count < length; elem_count++) { /* initialize subelement parameters */ @@ -2357,8 +2147,8 @@ t8_subelement_scheme_quad_c::t8_element_init (int length, t8_element_t *elem) co #ifdef T8_ENABLE_DEBUG /* In debugging mode we iterate over all length many elements and * set their quad to the level 0 quad with ID 0. */ - p4est_quadrant_t *quad = &pquad_w_sub[elem_count].p4q; - /* Set all values to 0 */ + p4est_quadrant_t *quad = &pquad_w_sub[elem_count].p4q; + /* Set all values to 0 */ for (int i = 0; i < length; i++) { p4est_quadrant_set_morton (quad + i, 0, 0); T8_QUAD_SET_TDIM (quad + i, 2); @@ -2381,29 +2171,30 @@ t8_subelement_scheme_quad_c::t8_element_transition_scheme_is_conformal (void) } int -t8_subelement_scheme_quad_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const{ +t8_subelement_scheme_quad_c::t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const +{ - if(t8_element_get_subelement_id((const t8_element_t * ) elem1) == t8_element_get_subelement_id((const t8_element_t *) elem2)){ + if (t8_element_get_subelement_id ((const t8_element_t *) elem1) + == t8_element_get_subelement_id ((const t8_element_t *) elem2)) { return 1; } -else{ - return 0; -} + else { + return 0; + } } void -t8_subelement_scheme_quad_c::t8_element_root (t8_element_t *elem) const { - SC_ABORT_NOT_REACHED(); - } - - +t8_subelement_scheme_quad_c::t8_element_root (t8_element_t *elem) const +{ + SC_ABORT_NOT_REACHED (); +} void t8_subelement_scheme_quad_c::t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, - void *send_buffer, const int buffer_size, int *position, - sc_MPI_Comm comm) const + void *send_buffer, const int buffer_size, int *position, + sc_MPI_Comm comm) const { - SC_ABORT_NOT_REACHED(); + SC_ABORT_NOT_REACHED (); // int mpiret; // p4est_quadrant_t **quads = (p4est_quadrant_t **) elements; @@ -2421,7 +2212,7 @@ t8_subelement_scheme_quad_c::t8_element_MPI_Pack (t8_element_t **const elements, void t8_subelement_scheme_quad_c::t8_element_MPI_Pack_size (const unsigned int count, sc_MPI_Comm comm, int *pack_size) const { - SC_ABORT_NOT_REACHED(); + SC_ABORT_NOT_REACHED (); // int singlesize = 0; // int datasize = 0; // int mpiret; @@ -2442,10 +2233,10 @@ t8_subelement_scheme_quad_c::t8_element_MPI_Pack_size (const unsigned int count, /* each quad is packed as x,y coordinates and the level */ void t8_subelement_scheme_quad_c::t8_element_MPI_Unpack (void *recvbuf, const int buffer_size, int *position, - t8_element_t **elements, const unsigned int count, - sc_MPI_Comm comm) const + t8_element_t **elements, const unsigned int count, + sc_MPI_Comm comm) const { - SC_ABORT_NOT_REACHED(); + SC_ABORT_NOT_REACHED (); // int mpiret; // p4est_quadrant_t **quads = (p4est_quadrant_t **) elements; // for (unsigned int ielem = 0; ielem < count; ielem++) { @@ -2458,13 +2249,11 @@ t8_subelement_scheme_quad_c::t8_element_MPI_Unpack (void *recvbuf, const int buf // } } - #ifdef T8_ENABLE_DEBUG void t8_subelement_scheme_quad_c::t8_element_debug_print (const t8_element_t *elem) const { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; t8_productionf ("\n|------------ t8_element_debug_print: ------------|" "\n| Transition Type: %i" @@ -2473,11 +2262,9 @@ t8_subelement_scheme_quad_c::t8_element_debug_print (const t8_element_t *elem) c "\n| Anchor (ref coords): (%lf,%lf)" "\n| Level: %i" "\n|-------------------------------------------------|\n", - pquad_w_sub->transition_type, pquad_w_sub->subelement_id, - pquad_w_sub->p4q.x, pquad_w_sub->p4q.y, + pquad_w_sub->transition_type, pquad_w_sub->subelement_id, pquad_w_sub->p4q.x, pquad_w_sub->p4q.y, (double) pquad_w_sub->p4q.x / (double) P4EST_ROOT_LEN, - (double) pquad_w_sub->p4q.y / (double) P4EST_ROOT_LEN, - pquad_w_sub->p4q.level); + (double) pquad_w_sub->p4q.y / (double) P4EST_ROOT_LEN, pquad_w_sub->p4q.level); /* if the element is not valid, abort, but after printing */ T8_ASSERT (t8_element_is_valid (elem)); @@ -2486,42 +2273,37 @@ t8_subelement_scheme_quad_c::t8_element_debug_print (const t8_element_t *elem) c /* *INDENT-OFF* */ /* indent bug, indent adds a second "const" modifier */ int -t8_subelement_scheme_quad_c::t8_element_is_valid (const t8_element_t * elem) const +t8_subelement_scheme_quad_c::t8_element_is_valid (const t8_element_t *elem) const /* *INDENT-ON* */ { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q = &pquad_w_sub->p4q; /* the 4pest quadrant AND the subelement values must be valid such that the whole element is valid */ - return (p4est_quadrant_is_extended (q) - && t8_element_subelement_values_are_valid (elem)); + return (p4est_quadrant_is_extended (q) && t8_element_subelement_values_are_valid (elem)); } /* *INDENT-OFF* */ /* indent bug, indent adds a second "const" modifier */ int -t8_subelement_scheme_quad_c::t8_element_subelement_values_are_valid (const - t8_element_t * - elem) const +t8_subelement_scheme_quad_c::t8_element_subelement_values_are_valid (const t8_element_t *elem) const /* *INDENT-ON* */ { - const t8_quad_with_subelements *pquad_w_sub = - (const t8_quad_with_subelements *) elem; + const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; - return ((pquad_w_sub->transition_type >= 0 && - pquad_w_sub->transition_type <= T8_SUB_QUAD_MAX_TRANSITION_TYPE) - || pquad_w_sub->transition_type == 0) && - ((pquad_w_sub->subelement_id >= 0 && - pquad_w_sub->subelement_id <= T8_SUB_QUAD_MAX_SUBELEMENT_ID) - || pquad_w_sub->subelement_id == 0); + return ((pquad_w_sub->transition_type >= 0 && pquad_w_sub->transition_type <= T8_SUB_QUAD_MAX_TRANSITION_TYPE) + || pquad_w_sub->transition_type == 0) + && ((pquad_w_sub->subelement_id >= 0 && pquad_w_sub->subelement_id <= T8_SUB_QUAD_MAX_SUBELEMENT_ID) + || pquad_w_sub->subelement_id == 0); } void -t8_subelement_scheme_quad_c::t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const{ - SC_ABORT_NOT_REACHED(); +t8_subelement_scheme_quad_c::t8_element_to_string (const t8_element_t *elem, char *debug_string, + const int string_size) const +{ + SC_ABORT_NOT_REACHED (); } #endif diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index c8221e0854..36fea72c17 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -68,11 +68,11 @@ typedef struct { /* p4est quadrant */ - p4est_quadrant_t p4q; + p4est_quadrant_t p4q; /* stores transition cell information (default for non-subelements is 0 and for subelements it is != 0 - is therefore used as a is_subelement check) */ - int transition_type; + int transition_type; /* stores subelement information (default for non-subelements is 0) */ - int subelement_id; + int subelement_id; } t8_quad_with_subelements; typedef t8_quad_with_subelements t8_pquad_t; @@ -91,30 +91,32 @@ typedef t8_quad_with_subelements t8_pquad_t; /** Return the direction of the third dimension. * This is only valid to call if the toplevel dimension is three. */ -#define T8_QUAD_GET_TNORMAL(quad) \ - ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ - ((int) (quad)->pad16) ) +#define T8_QUAD_GET_TNORMAL(quad) (T8_ASSERT (T8_QUAD_GET_TDIM (quad) == 3), ((int) (quad)->pad16)) /** Return the coordinate in the third dimension. * This is only valid to call if the toplevel dimension is three. */ -#define T8_QUAD_GET_TCOORD(quad) \ - ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ - ((int) (quad)->p.user_long) ) +#define T8_QUAD_GET_TCOORD(quad) (T8_ASSERT (T8_QUAD_GET_TDIM (quad) == 3), ((int) (quad)->p.user_long)) /** Set the toplevel dimension of a quadrilateral. */ -#define T8_QUAD_SET_TDIM(quad,dim) \ - do { T8_ASSERT ((dim) == 2 || (dim) == 3); \ - (quad)->pad8 = (int8_t) (dim); } while (0) +#define T8_QUAD_SET_TDIM(quad, dim) \ + do { \ + T8_ASSERT ((dim) == 2 || (dim) == 3); \ + (quad)->pad8 = (int8_t) (dim); \ + } while (0) /** Set the direction of the third dimension. */ -#define T8_QUAD_SET_TNORMAL(quad,normal) \ - do { T8_ASSERT ((normal) >= 0 && (normal) < 3); \ - (quad)->pad16 = (int16_t) (normal); } while (0) +#define T8_QUAD_SET_TNORMAL(quad, normal) \ + do { \ + T8_ASSERT ((normal) >= 0 && (normal) < 3); \ + (quad)->pad16 = (int16_t) (normal); \ + } while (0) /** Set the coordinate in the third dimension. */ -#define T8_QUAD_SET_TCOORD(quad,coord) \ - do { (quad)->p.user_long = (long) (coord); } while (0) +#define T8_QUAD_SET_TCOORD(quad, coord) \ + do { \ + (quad)->p.user_long = (long) (coord); \ + } while (0) #if 0 /** Provide an implementation for the quadrilateral element class with subelements. */ @@ -123,7 +125,7 @@ t8_eclass_scheme_t *t8_subelement_scheme_new_quad (void); struct t8_subelement_scheme_quad_c: public t8_default_scheme_common_c { -public: + public: /** The virtual table for a particular implementation of an element class. */ /** Constructor. */ @@ -134,253 +136,222 @@ public: /** Allocate memory for a given number of elements. * In debugging mode, ensure that all elements are valid \ref t8_element_is_valid. */ - virtual void t8_element_new (int length, t8_element_t **elem) const; - + virtual void + t8_element_new (int length, t8_element_t **elem) const; -/** Return the maximum level allowed for this element class. */ - virtual int t8_element_maxlevel (void) const; + /** Return the maximum level allowed for this element class. */ + virtual int + t8_element_maxlevel (void) const; -/** Return the type of each child in the ordering of the implementation. */ - virtual t8_eclass_t t8_element_child_eclass (int childid) const; + /** Return the type of each child in the ordering of the implementation. */ + virtual t8_eclass_t + t8_element_child_eclass (int childid) const; -/** Return the refinement level of an element. */ - virtual int t8_element_level (const t8_element_t *elem) const; + /** Return the refinement level of an element. */ + virtual int + t8_element_level (const t8_element_t *elem) const; -/** Copy one element to another */ - virtual void t8_element_copy (const t8_element_t *source, - t8_element_t *dest) const; + /** Copy one element to another */ + virtual void + t8_element_copy (const t8_element_t *source, t8_element_t *dest) const; -/** Compare to elements. returns negative eif elem1 < elem2, zero if elem1 equals elem2 + /** Compare to elements. returns negative eif elem1 < elem2, zero if elem1 equals elem2 * and positive if elem1 > elem2. * If elem2 is a copy of elem1 then the elements are equal. * If both elements are sibling subelements, return 0 if they are identical (same sub_id) and 1 otherwise. */ - virtual int t8_element_compare (const t8_element_t *elem1, - const t8_element_t *elem2) const; + virtual int + t8_element_compare (const t8_element_t *elem1, const t8_element_t *elem2) const; -/** Construct the parent of a given element. */ - virtual void t8_element_parent (const t8_element_t *elem, - t8_element_t *parent) const; + /** Construct the parent of a given element. */ + virtual void + t8_element_parent (const t8_element_t *elem, t8_element_t *parent) const; -/** Construct a same-size sibling of a given element. */ - virtual void t8_element_sibling (const t8_element_t *elem, - int sibid, - t8_element_t *sibling) const; + /** Construct a same-size sibling of a given element. */ + virtual void + t8_element_sibling (const t8_element_t *elem, int sibid, t8_element_t *sibling) const; /** Compute the number of face of a given element. */ - virtual int t8_element_num_faces (const t8_element_t *elem) const; + virtual int + t8_element_num_faces (const t8_element_t *elem) const; /** Compute the maximum number of faces of a given element and all of its * descendants. * \param [in] elem The element. * \return The maximum number of faces of \a elem and its descendants. */ - virtual int t8_element_max_num_faces (const t8_element_t *elem) - const; + virtual int + t8_element_max_num_faces (const t8_element_t *elem) const; /** Return the number of children of an element when it is refined. */ - virtual int t8_element_num_children (const t8_element_t *elem) - const; + virtual int + t8_element_num_children (const t8_element_t *elem) const; /** Return the number of siblings of an element (or the number of elements in the family of elem) */ - virtual int t8_element_num_siblings (const t8_element_t *elem) - const; + virtual int + t8_element_num_siblings (const t8_element_t *elem) const; /** Return the number of children of an element's face when the element is refined. */ - virtual int t8_element_num_face_children (const t8_element_t *elem, - const int face) const; + virtual int + t8_element_num_face_children (const t8_element_t *elem, const int face) const; /** Return the number of children of an element's face when the element is refined. */ - virtual int t8_element_neighbor_is_sibling (const t8_element_t - *elem, int face) const; + virtual int + t8_element_neighbor_is_sibling (const t8_element_t *elem, int face) const; /** Return the number of sibling neighbors at a given face. */ - virtual int t8_element_get_num_sibling_neighbors_at_face (const - t8_element_t - *elem, - int face) - const; + virtual int + t8_element_get_num_sibling_neighbors_at_face (const t8_element_t *elem, int face) const; /** Return zero refine value for schemes that do not have a transition implementation. */ - virtual int t8_element_get_transition_refine_identifier (void) - const; + virtual int + t8_element_get_transition_refine_identifier (void) const; /** Return the corner number of an element's face corner. */ - virtual int t8_element_get_face_corner (const t8_element_t *element, - int face, int corner) const; + virtual int + t8_element_get_face_corner (const t8_element_t *element, int face, int corner) const; /** Return the face numbers of the faces sharing an element's corner. */ - virtual int t8_element_get_corner_face (const t8_element_t *element, - int corner, int face) const; + virtual int + t8_element_get_corner_face (const t8_element_t *element, int corner, int face) const; /** Construct the child element of a given number. */ - virtual void t8_element_child (const t8_element_t *elem, - int childid, - t8_element_t *child) const; + virtual void + t8_element_child (const t8_element_t *elem, int childid, t8_element_t *child) const; /** Construct all sibling neighbors of elem at face - it is required that sibling neighbors of elem at face exist */ virtual void - - - - t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t - *elem, - const int face, - const int - num_neighbors, - t8_element_t - *neighbor_at_face[], - int *neigh_face[]); - -/** Construct all children of a given element. */ - virtual void t8_element_children (const t8_element_t *elem, - int length, - t8_element_t *c[]) const; - -/** Return the child id of an element */ - virtual int t8_element_child_id (const t8_element_t *elem) const; + + t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t *elem, const int face, const int num_neighbors, + t8_element_t *neighbor_at_face[], int *neigh_face[]); + + /** Construct all children of a given element. */ + virtual void + t8_element_children (const t8_element_t *elem, int length, t8_element_t *c[]) const; + + /** Return the child id of an element */ + virtual int + t8_element_child_id (const t8_element_t *elem) const; /** Compute the ancestor id of an element */ - virtual int t8_element_ancestor_id (const t8_element_t *elem, - int level) const; + virtual int + t8_element_ancestor_id (const t8_element_t *elem, int level) const; -/** Return nonzero if collection of elements is a family */ - virtual int t8_element_is_family (t8_element_t *const *fam) const; + /** Return nonzero if collection of elements is a family */ + virtual int + t8_element_is_family (t8_element_t *const *fam) const; -/** Construct the nearest common ancestor of two elements in the same tree. */ - virtual void t8_element_nca (const t8_element_t *elem1, - const t8_element_t *elem2, - t8_element_t *nca) const; + /** Construct the nearest common ancestor of two elements in the same tree. */ + virtual void + t8_element_nca (const t8_element_t *elem1, const t8_element_t *elem2, t8_element_t *nca) const; /** Compute the element shape of the face of an element. */ - virtual t8_element_shape_t t8_element_face_shape (const t8_element_t *elem, - int face) const; + virtual t8_element_shape_t + t8_element_face_shape (const t8_element_t *elem, int face) const; /** Given an element and a face of the element, compute all children of * the element that touch the face. */ /** Given an element and a face of the element, compute all children of * the element that touch the face. */ - virtual void t8_element_children_at_face (const t8_element_t *elem, - int face, - t8_element_t *children[], - int num_children, - int *child_indices) const; + virtual void + t8_element_children_at_face (const t8_element_t *elem, int face, t8_element_t *children[], int num_children, + int *child_indices) const; /** Given a face of an element and a child number of a child of that face, return the face number * of the child of the element that matches the child face. */ - virtual int t8_element_face_child_face (const t8_element_t *elem, - int face, - int face_child) const; + virtual int + t8_element_face_child_face (const t8_element_t *elem, int face, int face_child) const; /** Given a face of an element return the face number * of the parent of the element that matches the element's face. Or return -1 if * no face of the parent matches the face. */ - virtual int t8_element_face_parent_face (const t8_element_t *elem, - int face) const; + virtual int + t8_element_face_parent_face (const t8_element_t *elem, int face) const; /** Transform the coordinates of a quadrilateral considered as boundary element * in a tree-tree connection. */ - virtual void t8_element_transform_face (const t8_element_t *elem1, - t8_element_t *elem2, - int orientation, int sign, - int is_smaller_face) const; + virtual void + t8_element_transform_face (const t8_element_t *elem1, t8_element_t *elem2, int orientation, int sign, + int is_smaller_face) const; /** Given a boundary face inside a root tree's face construct * the element inside the root tree that has the given face as a * face. */ - virtual int t8_element_extrude_face (const t8_element_t *face, - const t8_eclass_scheme_c - *face_scheme, - t8_element_t *elem, - int root_face) const; + virtual int + t8_element_extrude_face (const t8_element_t *face, const t8_eclass_scheme_c *face_scheme, t8_element_t *elem, + int root_face) const; /** Return the tree face id given a boundary face. */ - virtual int t8_element_tree_face (const t8_element_t *elem, - int face) const; + virtual int + t8_element_tree_face (const t8_element_t *elem, int face) const; /** Construct the first descendant of an element that touches a given face. */ - virtual void t8_element_first_descendant_face (const t8_element_t - *elem, int face, - t8_element_t - *first_desc, - int level) const; + virtual void + t8_element_first_descendant_face (const t8_element_t *elem, int face, t8_element_t *first_desc, int level) const; /** Construct the last descendant of an element that touches a given face. */ - virtual void t8_element_last_descendant_face (const t8_element_t - *elem, int face, - t8_element_t - *last_desc, - int level) const; + virtual void + t8_element_last_descendant_face (const t8_element_t *elem, int face, t8_element_t *last_desc, int level) const; /** Construct the boundary element at a specific face. */ - virtual void t8_element_boundary_face (const t8_element_t *elem, - int face, - t8_element_t *boundary, - const t8_eclass_scheme_c - *boundary_scheme) const; + virtual void + t8_element_boundary_face (const t8_element_t *elem, int face, t8_element_t *boundary, + const t8_eclass_scheme_c *boundary_scheme) const; -/** Construct all codimension-one boundary elements of a given element. */ - virtual void t8_element_boundary (const t8_element_t *elem, - int min_dim, int length, - t8_element_t **boundary) const; + /** Construct all codimension-one boundary elements of a given element. */ + virtual void + t8_element_boundary (const t8_element_t *elem, int min_dim, int length, t8_element_t **boundary) const; /** Compute whether a given element shares a given face with its root tree. * \param [in] elem The input element. * \param [in] face A face of \a elem. * \return True if \a face is a subface of the element's root element. */ - virtual int t8_element_is_root_boundary (const t8_element_t *elem, - int face) const; + virtual int + t8_element_is_root_boundary (const t8_element_t *elem, int face) const; /** Construct the face neighbor of a given element if this face neighbor * is inside the root tree. Return 0 otherwise. */ - virtual int t8_element_face_neighbor_inside (const t8_element_t - *elem, - t8_element_t *neigh, - int face, - int *neigh_face) const; - -/** Initialize an element according to a given linear id */ - virtual void t8_element_set_linear_id (t8_element_t *elem, - int level, - t8_linearidx_t id) const; - -/** Calculate the linear id of an element */ - virtual t8_linearidx_t t8_element_get_linear_id (const - t8_element_t *elem, - int level) const; - -/** Calculate the first descendant of a given element e. That is, the + virtual int + t8_element_face_neighbor_inside (const t8_element_t *elem, t8_element_t *neigh, int face, int *neigh_face) const; + + /** Initialize an element according to a given linear id */ + virtual void + t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + + /** Calculate the linear id of an element */ + virtual t8_linearidx_t + t8_element_get_linear_id (const t8_element_t *elem, int level) const; + + /** Calculate the first descendant of a given element e. That is, the * first element in a uniform refinement of e of the maximal possible level. */ - virtual void t8_element_first_descendant (const t8_element_t *elem, - t8_element_t *desc, - int level) const; + virtual void + t8_element_first_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; -/** Calculate the last descendant of a given element e. That is, the + /** Calculate the last descendant of a given element e. That is, the * last element in a uniform refinement of e of the maximal possible level. */ - virtual void t8_element_last_descendant (const t8_element_t *elem, - t8_element_t *desc, - int level) const; + virtual void + t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; -/** Compute s as a successor of t*/ - virtual void t8_element_successor (const t8_element_t *t, - t8_element_t *s) const; + /** Compute s as a successor of t*/ + virtual void + t8_element_successor (const t8_element_t *t, t8_element_t *s) const; -/** Get the integer coordinates of the anchor node of an element */ - virtual void t8_element_anchor (const t8_element_t *elem, - int anchor[3]) const; + /** Get the integer coordinates of the anchor node of an element */ + virtual void + t8_element_anchor (const t8_element_t *elem, int anchor[3]) const; -/** Get the integer root length of an element, that is the length of + /** Get the integer root length of an element, that is the length of * the level 0 ancestor. */ - virtual int t8_element_root_len (const t8_element_t *elem) const; + virtual int + t8_element_root_len (const t8_element_t *elem) const; -/** Compute the integer coordinates of a given element vertex. */ - virtual void t8_element_vertex_coords (const t8_element_t *t, - int vertex, - int coords[]) const; + /** Compute the integer coordinates of a given element vertex. */ + virtual void + t8_element_vertex_coords (const t8_element_t *t, int vertex, int coords[]) const; /** Compute the integer coordinates of a given element vertex. * The default scheme implements the Morton type SFCs. In these SFCs the * elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and @@ -394,7 +365,7 @@ public: virtual void t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const; -/** Convert a point in the reference space of an element to a point in the + /** Convert a point in the reference space of an element to a point in the * reference space of the tree. * * \param [in] elem The element. @@ -402,79 +373,74 @@ public: * \param [in] user_data User data. * \param [out] out_coords The coordinates of the point in the reference space of the tree. */ - virtual void t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, - double *out_coords) - const; + virtual void + t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, + double *out_coords) const; -/** Construct a transition cell of type type */ - virtual void t8_element_to_transition_cell (const t8_element_t *elem, - int type, - t8_element_t *c[]); + /** Construct a transition cell of type type */ + virtual void + t8_element_to_transition_cell (const t8_element_t *elem, int type, t8_element_t *c[]); -/** Determine the number of sibling subelements, of a transition cell of a specific type */ - virtual int t8_element_get_number_of_subelements (int - transition_type) - const; + /** Determine the number of sibling subelements, of a transition cell of a specific type */ + virtual int + t8_element_get_number_of_subelements (int transition_type) const; -/** Test whether a given element is a subelement or not */ - virtual int t8_element_is_subelement (const t8_element * - elem) const; + /** Test whether a given element is a subelement or not */ + virtual int + t8_element_is_subelement (const t8_element *elem) const; -/** Get the subelement type of elem */ - virtual int t8_element_get_transition_type (const - t8_element * elem); + /** Get the subelement type of elem */ + virtual int + t8_element_get_transition_type (const t8_element *elem); -/** Get the subelement id of elem */ - virtual int t8_element_get_subelement_id (const t8_element * elem) const; + /** Get the subelement id of elem */ + virtual int + t8_element_get_subelement_id (const t8_element *elem) const; -/** Get the subelement id of the neighbor subelement of elem at face elem_face + /** Get the subelement id of the neighbor subelement of elem at face elem_face * that is a sibling of the subelement neigh. */ - virtual int t8_element_find_neighbor_in_transition_cell (const - t8_element_t - *elem, - const - t8_element_t - *neigh, - int - elem_face); - -/** Get the face-number of the hypotenuse of the triangular subelement */ - virtual int t8_element_get_face_number_of_hypotenuse (const - t8_element_t - *elem); - -/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ - virtual int t8_element_scheme_supports_transitioning (void); - -/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ - virtual int t8_element_transition_scheme_is_conformal (void); - -/** Returns true, if there is one element in the tree, that does not refine into 2^dim children. + virtual int + t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, const t8_element_t *neigh, int elem_face); + + /** Get the face-number of the hypotenuse of the triangular subelement */ + virtual int + t8_element_get_face_number_of_hypotenuse (const t8_element_t *elem); + + /** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int + t8_element_scheme_supports_transitioning (void); + + /** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int + t8_element_transition_scheme_is_conformal (void); + + /** Returns true, if there is one element in the tree, that does not refine into 2^dim children. * Returns false otherwise. * \return non-zero if there is one element in the tree that does not refine into 2^dim children. */ - virtual int t8_element_refines_irregular (void) const; + virtual int + t8_element_refines_irregular (void) const; -/** Get the shape of a given element. Subelements are triangles */ - virtual t8_element_shape_t t8_element_shape (const t8_element_t *elem) - const; + /** Get the shape of a given element. Subelements are triangles */ + virtual t8_element_shape_t + t8_element_shape (const t8_element_t *elem) const; -/** Return the number of vertices of an element */ - virtual int t8_element_num_corners (const t8_element_t *elem) const; + /** Return the number of vertices of an element */ + virtual int + t8_element_num_corners (const t8_element_t *elem) const; -/** Compute the coordinates of a given element vertex inside a reference tree + /** Compute the coordinates of a given element vertex inside a reference tree * that is embedded into [0,1]^d (d = dimension). * \param [in] t The element to be considered. * \param [in] vertex The id of the vertex whose coordinates shall be computed. * \param [out] coords An array of at least as many doubles as the element's dimension * whose entries will be filled with the coordinates of \a vertex. */ - virtual void t8_element_vertex_reference_coords (const t8_element_t - *t, int vertex, - double coords[]) const; + virtual void + t8_element_vertex_reference_coords (const t8_element_t *t, int vertex, double coords[]) const; - /** Check if two elements are equal. + /** Check if two elements are equal. * \param [in] ts Implementation of a class scheme. * \param [in] elem1 The first element. * \param [in] elem2 The second element. @@ -483,7 +449,7 @@ public: virtual int t8_element_equal (const t8_element_t *elem1, const t8_element_t *elem2) const; - /** Fills an element with the root element. + /** Fills an element with the root element. * \param [in,out] elem The element to be filled with root. */ void @@ -510,13 +476,15 @@ public: t8_element_init (int length, t8_element_t *elem) const; #ifdef T8_ENABLE_DEBUG -/** TODO: this should be the new element_print_element function */ - virtual void t8_element_debug_print (const t8_element_t *elem) const; + /** TODO: this should be the new element_print_element function */ + virtual void + t8_element_debug_print (const t8_element_t *elem) const; -/** Query whether an element is valid */ - virtual int t8_element_is_valid (const t8_element_t *t) const; + /** Query whether an element is valid */ + virtual int + t8_element_is_valid (const t8_element_t *t) const; - /** + /** * Print a given element. For a example for a triangle print the coordinates * and the level of the triangle. This function is only available in the * debugging configuration. @@ -525,10 +493,10 @@ public: */ virtual void t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const; - + #endif -protected: + protected: /** This function determines the vertex coordinates of subelements. * \param [in] elem A valid subelement * \param [in] vertex the number of the vertex whose coordinates should be determined @@ -538,11 +506,8 @@ protected: * eclass scheme. For example, subelements that remove hanging nodes from the quad scheme * are triangles with 3 instead of 4 vertices. */ - void t8_element_vertex_coords_of_subelement (const - t8_element_t *t, - int vertex, - int coords[]) - const; + void + t8_element_vertex_coords_of_subelement (const t8_element_t *t, int vertex, int coords[]) const; /** This function will determine the location of a specific subelement in the parent element. * Since different subelement types are possible, it is a priori not known where for example the @@ -559,30 +524,25 @@ protected: * The information in the location can be used to automatically determine the vertices of any subelement. * Since this function is only used to determine the vertices of subelements, it can be declared as a private/protected function. */ - void t8_element_get_location_of_subelement (const - t8_element_t - *elem, - int location[]) - const; + void + t8_element_get_location_of_subelement (const t8_element_t *elem, int location[]) const; /** This help function returns the subelement if of an element whose location and transition type is known. */ - int t8_element_get_id_from_location (int type, - int location[]); + int + t8_element_get_id_from_location (int type, int location[]); /** This function copies the subelement values from source to dest. * \param [in] source A valid element * \param [in,out] dest A valid element, whose subelement values are equal to those of source */ - void t8_element_copy_subelement_values (const - t8_element_t *source, - t8_element_t *dest) - const; + void + t8_element_copy_subelement_values (const t8_element_t *source, t8_element_t *dest) const; /** This function resets the subelement values of an element to the default value -1. * \param [in,out] elem A valid element, whose subelement values have been reset. */ - void t8_element_reset_subelement_values (t8_element_t *elem) - const; + void + t8_element_reset_subelement_values (t8_element_t *elem) const; virtual void t8_element_MPI_Pack (t8_element_t **const elements, const unsigned int count, void *send_buffer, int buffer_size, @@ -613,9 +573,8 @@ protected: * \param [in] source A element * \return true, if the subelement values are valid */ - int t8_element_subelement_values_are_valid (const - t8_element_t - *elem) const; + int + t8_element_subelement_values_are_valid (const t8_element_t *elem) const; #endif }; diff --git a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx index 27bd257485..a73a2bceef 100644 --- a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx @@ -41,8 +41,10 @@ enum T8_TRANSITION_REFINE_IDENTIFIER { T8_EXTERN_C_BEGIN (); /** Return the subelement element implementations of t8code. */ -t8_scheme_cxx_t *t8_scheme_new_transition_quad_cxx (void); -t8_scheme_cxx_t *t8_scheme_new_transition_hex_cxx (void); +t8_scheme_cxx_t * +t8_scheme_new_transition_quad_cxx (void); +t8_scheme_cxx_t * +t8_scheme_new_transition_hex_cxx (void); T8_EXTERN_C_END (); diff --git a/test/t8_forest_transition/t8_gtest_forest_commit.cxx b/test/t8_forest_transition/t8_gtest_forest_commit.cxx index 83d73346e6..d995af0182 100644 --- a/test/t8_forest_transition/t8_gtest_forest_commit.cxx +++ b/test/t8_forest_transition/t8_gtest_forest_commit.cxx @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -41,8 +41,6 @@ * After these two forests are created, we check for equality. */ - - /* Adapt a forest such that always the first child of a * tree is refined and no other elements. This results in a highly * imbalanced forest. */ @@ -65,17 +63,17 @@ t8_test_adapt_balance (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t // return 1; // } // return 0; - if (lelement_id == 0){ + if (lelement_id == 0) { return 1; } -return 0; + return 0; } /* adapt, balance and partition a given forest in one step */ static t8_forest_t t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) { - t8_debugf("---------start t8_test_forest_commit_abp ---------------------\n"); + t8_debugf ("---------start t8_test_forest_commit_abp ---------------------\n"); t8_forest_t forest_ada_bal_par; @@ -85,11 +83,11 @@ t8_test_forest_commit_abp (t8_forest_t forest, int maxlevel) t8_forest_set_user_data (forest_ada_bal_par, &maxlevel); t8_forest_set_adapt (forest_ada_bal_par, forest, t8_test_adapt_balance, 0); t8_forest_set_balance (forest_ada_bal_par, NULL, 0); - t8_forest_set_transition(forest_ada_bal_par, NULL, 0); + t8_forest_set_transition (forest_ada_bal_par, NULL, 0); t8_forest_set_partition (forest_ada_bal_par, NULL, 0); t8_forest_commit (forest_ada_bal_par); - t8_debugf("---------finsish t8_test_forest_commit_abp ---------------------\n"); + t8_debugf ("---------finsish t8_test_forest_commit_abp ---------------------\n"); return forest_ada_bal_par; } @@ -129,7 +127,7 @@ t8_test_forest_commit_abp_3step (t8_forest_t forest, int maxlevel) TEST (forest_commit, test_forest_commit) { - t8_cmesh_t cmesh; + t8_cmesh_t cmesh; t8_forest_t forest; t8_forest_t forest_ada_bal_tra_part; t8_forest_t forest_abtp_3part; @@ -137,16 +135,15 @@ TEST (forest_commit, test_forest_commit) const int level_step = 0; /* construct a single tree hex cmesh */ cmesh = t8_cmesh_new_hypercube (T8_ECLASS_HEX, sc_MPI_COMM_WORLD, 0, 0, 0); - t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); - int maxlevel = -1; + int maxlevel = -1; for (int level = 0; level <= maxlevel; level++) { - /* ref the cmesh since we reuse it */ + /* ref the cmesh since we reuse it */ t8_cmesh_ref (cmesh); t8_debugf ("Testing forest commit level %i\n", level); - + /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); @@ -161,13 +158,11 @@ TEST (forest_commit, test_forest_commit) ASSERT_TRUE (t8_forest_is_equal (forest_abtp_3part, forest_ada_bal_tra_part)) << "The forests are not equal"; t8_scheme_cxx_ref (scheme); - t8_forest_unref (&forest_ada_bal_tra_part); t8_forest_unref (&forest_abtp_3part); - } - t8_scheme_cxx_unref (&scheme); - t8_cmesh_unref(&cmesh); + t8_scheme_cxx_unref (&scheme); + t8_cmesh_unref (&cmesh); t8_debugf ("Done testing forest commit."); } \ No newline at end of file diff --git a/test/t8_schemes_transition/t8_gtest_child_parent_face.cxx b/test/t8_schemes_transition/t8_gtest_child_parent_face.cxx index 9377612694..5ec073f830 100644 --- a/test/t8_schemes_transition/t8_gtest_child_parent_face.cxx +++ b/test/t8_schemes_transition/t8_gtest_child_parent_face.cxx @@ -80,4 +80,5 @@ TEST_P (class_child_parent_face, t8_recursive_dfs_child_parent_face) check_recursive_dfs_to_max_lvl (maxlvl); } -INSTANTIATE_TEST_SUITE_P (t8_gtest_child_parent_face, class_child_parent_face, testing::Values (T8_ECLASS_HEX), print_eclass); +INSTANTIATE_TEST_SUITE_P (t8_gtest_child_parent_face, class_child_parent_face, testing::Values (T8_ECLASS_HEX), + print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_descendant.cxx b/test/t8_schemes_transition/t8_gtest_descendant.cxx index 9373cca49a..fe0a03ae3a 100644 --- a/test/t8_schemes_transition/t8_gtest_descendant.cxx +++ b/test/t8_schemes_transition/t8_gtest_descendant.cxx @@ -28,7 +28,6 @@ #include #include - /* This program tests the descendant function of an element. */ class class_schemes_descendant: public testing::TestWithParam { diff --git a/test/t8_schemes_transition/t8_gtest_equal.cxx b/test/t8_schemes_transition/t8_gtest_equal.cxx index 75cb16c085..b78b614ce0 100644 --- a/test/t8_schemes_transition/t8_gtest_equal.cxx +++ b/test/t8_schemes_transition/t8_gtest_equal.cxx @@ -28,7 +28,6 @@ #include "t8_gtest_dfs_base.hxx" #include - class class_test_equal: public TestDFS { virtual void check_element () diff --git a/test/t8_schemes_transition/t8_gtest_face_descendant.cxx b/test/t8_schemes_transition/t8_gtest_face_descendant.cxx index 9190be3b78..c65f8e3dde 100644 --- a/test/t8_schemes_transition/t8_gtest_face_descendant.cxx +++ b/test/t8_schemes_transition/t8_gtest_face_descendant.cxx @@ -121,4 +121,5 @@ TEST_P (class_descendant, t8_check_face_desc) check_recursive_dfs_to_max_lvl (maxlvl); } -INSTANTIATE_TEST_SUITE_P (t8_gtest_element_face_descendant, class_descendant, testing::Values (T8_ECLASS_HEX), print_eclass); +INSTANTIATE_TEST_SUITE_P (t8_gtest_element_face_descendant, class_descendant, testing::Values (T8_ECLASS_HEX), + print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_face_neigh.cxx b/test/t8_schemes_transition/t8_gtest_face_neigh.cxx index 7c178ffa06..3068440ae8 100644 --- a/test/t8_schemes_transition/t8_gtest_face_neigh.cxx +++ b/test/t8_schemes_transition/t8_gtest_face_neigh.cxx @@ -28,7 +28,6 @@ #include #include - #include /* *INDENT-OFF* */ @@ -207,4 +206,4 @@ TEST_P (face_neigh, recursive_check_diff) t8_recursive_check_diff (child, element, neigh, ts, maxlvl, level); } -INSTANTIATE_TEST_SUITE_P (t8_gtest_face_neigh, face_neigh, testing::Values(T8_ECLASS_HEX), print_eclass); +INSTANTIATE_TEST_SUITE_P (t8_gtest_face_neigh, face_neigh, testing::Values (T8_ECLASS_HEX), print_eclass); diff --git a/test/t8_schemes_transition/t8_gtest_nca.cxx b/test/t8_schemes_transition/t8_gtest_nca.cxx index a06c0e3397..b740af4632 100644 --- a/test/t8_schemes_transition/t8_gtest_nca.cxx +++ b/test/t8_schemes_transition/t8_gtest_nca.cxx @@ -32,7 +32,6 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include - class nca: public testing::TestWithParam { protected: void diff --git a/test/t8_schemes_transition/t8_gtest_pack_unpack.cxx b/test/t8_schemes_transition/t8_gtest_pack_unpack.cxx index ff8e1e406f..892fa0f0d0 100644 --- a/test/t8_schemes_transition/t8_gtest_pack_unpack.cxx +++ b/test/t8_schemes_transition/t8_gtest_pack_unpack.cxx @@ -27,7 +27,6 @@ #include #include - /** Use DFS to check for all elements, if packing them, sending them to ourself and unpacking them results in the same element * Here, each element is sent individually. */ diff --git a/test/t8_schemes_transition/t8_gtest_successor.cxx b/test/t8_schemes_transition/t8_gtest_successor.cxx index fba4a5d928..188622b0d1 100644 --- a/test/t8_schemes_transition/t8_gtest_successor.cxx +++ b/test/t8_schemes_transition/t8_gtest_successor.cxx @@ -156,4 +156,4 @@ TEST_P (class_successor, test_recursive_and_deep_successor) t8_deep_successor (element, successor, last, ts); } -INSTANTIATE_TEST_SUITE_P (t8_gtest_successor, class_successor, testing::Values(T8_ECLASS_HEX), print_eclass); +INSTANTIATE_TEST_SUITE_P (t8_gtest_successor, class_successor, testing::Values (T8_ECLASS_HEX), print_eclass); From b9fab899c2189653b95cedb889e31137078b6216 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 12 Jun 2024 14:58:36 +0200 Subject: [PATCH 29/55] corrected typo --- .../t8_transition_conformal_hex_cxx.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 971c3a249f..af17623a62 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -369,7 +369,7 @@ struct t8_subelement_scheme_hex_c: public t8_default_scheme_common_c /** Calculate the linear id of an element */ virtual t8_linearidx_t - t8_element_get_linear_id (constt8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, int level) const; /** Calculate the first descendant of a given element e. That is, the * first element in a uniform refinement of e of the maximal possible level. From 8f7ae08da30bf2f88d92d16a376c5eca5a820b09 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Wed, 12 Jun 2024 15:03:16 +0200 Subject: [PATCH 30/55] Little clean-up --- .../t8_transition_conformal_hex_cxx.cxx | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 4b6254db11..4887a22443 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -158,7 +158,6 @@ t8_subelement_scheme_hex_c::t8_element_compare (const t8_element_t *elem1, const int compare = p8est_quadrant_compare (q, r); if (compare == 0 && (t8_element_is_subelement (elem1) || t8_element_is_subelement (elem2))) { - // t8_debugf ("Caution, t8_element_compare is used with subelements.\n"); if (t8_element_is_subelement (elem1) && t8_element_is_subelement (elem2)) { /* Caution: The compare function is used for two subelements. */ @@ -1495,7 +1494,6 @@ t8_subelement_scheme_hex_c::t8_element_is_root_boundary (const t8_element_t *ele coord = face >> 2 ? q->z : face >> 1 ? q->y : q->x; /* If face is 0,2 or 4 check against 0. * If face is 1,3 or 5 check against LAST_OFFSET */ - // t8_debugf("t8 element is root boundary %i\n", coord == (face & 1 ? P8EST_LAST_OFFSET (q->level) : 0)); return coord == (face & 1 ? P8EST_LAST_OFFSET (q->level) : 0); } @@ -1944,8 +1942,6 @@ t8_subelement_scheme_hex_c::t8_element_vertex_coords (const t8_element_t *elem, if (!t8_element_is_subelement (elem)) { int len; - - //T8_ASSERT (0 <= vertex && vertex < 8); /* Get the length of the quadrant */ len = P8EST_QUADRANT_LEN (q1->level); /* Compute the x, y and z coordinates of the vertex depending on the @@ -2318,8 +2314,6 @@ t8_subelement_scheme_hex_c::t8_element_get_number_of_subelements (int transition num_hanging_faces += (transition_type & (1 << ichild)) >> ichild; } - /* The number of subelements equals the number of neighbours: */ - //t8_productionf("number subs %i\n",P8EST_FACES + num_hanging_faces*3); return P8EST_FACES + num_hanging_faces * 3; } @@ -2416,8 +2410,8 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const t8_elem } if (split == 1) { - /* 3.3) determine, whether the subelement is the left/right, front/back or bottom/up subelement at the face */ - //First left/ right (only for face number 2, 3, 4, 5) + /* 3.3) determine, whether the subelement is the left/right, front/back or bottom/up subelement at the face + First left/ right (only for face number 2, 3, 4, 5)*/ if (face_number > 1) { if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 3) == cum_neigh_array[face_number])) { sub_face_id_array[0] = 1; /* right*/ @@ -2426,7 +2420,7 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const t8_elem sub_face_id_array[0] = 0; /* left */ } } - //Second check front or back (only for face numbers 0, 1, 4, 5) + //Second: Check front or back (only for face numbers 0, 1, 4, 5) if (face_number <= 1) { if (((sub_id + 1) == cum_neigh_array[face_number]) || ((sub_id + 3) == cum_neigh_array[face_number])) { sub_face_id_array[1] = 1; /* back subelement */ @@ -2443,7 +2437,7 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const t8_elem sub_face_id_array[1] = 0; /* front subelement */ } } - //Third check up or down (only for face numbers 0, 1, 2, 3) + /*Third check up or down (only for face numbers 0, 1, 2, 3)*/ if (face_number < 4) { if (((sub_id + 2) == cum_neigh_array[face_number]) || ((sub_id + 1) == cum_neigh_array[face_number])) { sub_face_id_array[2] = 1; /* up subelement */ @@ -2452,7 +2446,7 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const t8_elem sub_face_id_array[2] = 0; /* bottom subelement */ } } - //Calculate the sub_face_id out of the sub_face_id_array + /*Calculate the sub_face_id out of the sub_face_id_array*/ for (int i = 0; i < 3; i++) { if (sub_face_id_array[i] == 1) { sub_face_id += std::pow (2, 2 - i); @@ -2479,7 +2473,6 @@ t8_subelement_scheme_hex_c::t8_element_copy_subelement_values (const t8_element { const t8_hex_with_subelements *phex_w_sub_source = (const t8_hex_with_subelements *) source; t8_hex_with_subelements *phex_w_sub_dest = (t8_hex_with_subelements *) dest; - // phex_w_sub_dest->transition_type = phex_w_sub_source->transition_type; phex_w_sub_dest->transition_type = phex_w_sub_source->transition_type; phex_w_sub_dest->subelement_id = phex_w_sub_source->subelement_id; } @@ -2540,8 +2533,8 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell (const t T8_ASSERT (t8_element_is_valid (pseudo_neigh)); /* we expect neigh to be a element in a transition cell, thus to be a subelement */ T8_ASSERT (t8_element_is_subelement (pseudo_neigh)); - //Case 1: the neighbor is ab sibling of elem --> function t8_element_get_sibling_neighbor_in_transition_cell - //Thus, we expect elem_face = 4 + /* Case 1: the neighbor is ab sibling of elem --> function t8_element_get_sibling_neighbor_in_transition_cell + * Thus, we expect elem_face = 4*/ T8_ASSERT (elem_face == 4); const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; @@ -2630,7 +2623,7 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell (const t * This data will be used to determine the sub_id of the neighbor within the transition cell of pseudo_neigh. */ return t8_element_get_id_from_location (t8_element_get_transition_type (pseudo_neigh), location_neigh); } - //Elem is no subelement. + // elem is no subelement. else { /* In this case, we have the following examplary situation for the 2D quad case: * From c8e79b36859cc6a278acb46ecbbc82a978e4fb64 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Thu, 13 Jun 2024 12:58:31 +0200 Subject: [PATCH 31/55] Added LFN example + functions. example does not work yet --- example/transition/Makefile.am | 5 +- example/transition/t8_transition_LFN_hex.cxx | 258 +++++++ src/t8_element_cxx.hxx | 77 +++ src/t8_forest/t8_forest.c | 8 + src/t8_forest/t8_forest_cxx.cxx | 640 +++++++++++++++++- src/t8_forest/t8_forest_general.h | 7 + .../t8_default_common_cxx.cxx | 67 ++ .../t8_default_common_cxx.hxx | 72 ++ .../t8_transition_conformal_hex_cxx.cxx | 70 +- .../t8_transition_conformal_hex_cxx.hxx | 3 + 10 files changed, 1186 insertions(+), 21 deletions(-) create mode 100644 example/transition/t8_transition_LFN_hex.cxx diff --git a/example/transition/Makefile.am b/example/transition/Makefile.am index 302b66bc46..3427e14ad4 100644 --- a/example/transition/Makefile.am +++ b/example/transition/Makefile.am @@ -6,10 +6,11 @@ bin_PROGRAMS += \ example/transition/t8_transition_global_hex \ example/transition/t8_transition_basic_hex \ example/transition/t8_transition_forest \ - example/transition/t8_transition_multiple_trees_hex - + example/transition/t8_transition_multiple_trees_hex \ + example/transition/t8_transition_LFN_hex example_transition_t8_transition_global_hex_SOURCES = example/transition/t8_transition_global_hex.cxx example_transition_t8_transition_basic_hex_SOURCES = example/transition/t8_transition_basic_hex.cxx example_transition_t8_transition_forest_SOURCES = example/transition/t8_transition_forest.cxx example_transition_t8_transition_multiple_trees_hex_SOURCES = example/transition/t8_transition_multiple_trees_hex.cxx +example_transition_t8_transition_LFN_hex_SOURCES = example/transition/t8_transition_LFN_hex.cxx diff --git a/example/transition/t8_transition_LFN_hex.cxx b/example/transition/t8_transition_LFN_hex.cxx new file mode 100644 index 0000000000..6dec97602d --- /dev/null +++ b/example/transition/t8_transition_LFN_hex.cxx @@ -0,0 +1,258 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element types in parallel. + + Copyright (C) 2015 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* Description: + * This is the example file for refinement with transitioning. In this testcase, we are able to + * (i) refine a mesh according to some refinement criterion and use transition cells to make the mesh conformal + * (ii) use multiple adaptation steps in which the refinement criterion changes (e.g. the geometry) + * (iii) decide, whether we want to check the LFN function for each mesh + * (iv) decide, whether we want to get statistics printed out, regarding # of elements in the meshes and runtime infos of the several functions or other debugging information + */ + +/* to switch between the default quad scheme and the transition implementation */ +#include "t8_eclass.h" +#include "t8_forest/t8_forest_types.h" + +#include "t8_forest/t8_forest_general.h" +#include +#include +#include +#include +#include // to write vtk +#include +#include +#include /* for cmesh initialization via for example t8_cmesh_new_hypercube */ +#include +#include + +/* In this example, the left side of a unit cube with initial level 2 is refined to construct an adapted and transitioned forest. */ + +/* Refinement criterion: All elements with x-coordinate smaller than 0.5 are being refined. All other elements remain unchanged. */ +int +t8_adapt_callback (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, t8_locidx_t lelement_id, + t8_eclass_scheme_c *ts, const int is_family, const int num_elements, t8_element_t *elements[]) +{ + int child_id = ts->t8_element_child_id (elements[0]); + if (child_id == 1) { + return 1; + } + return 0; +} + +/* adapt, balance, transition and partition a given forest in one step */ +static t8_forest_t +t8_test_forest_commit_abpt (t8_forest_t forest) +{ + t8_forest_t forest_ada_bal_tra_par; + + /* Adapt, balance and partition the uniform forest */ + t8_forest_init (&forest_ada_bal_tra_par); + t8_forest_set_adapt (forest_ada_bal_tra_par, forest, t8_adapt_callback, 0); + t8_forest_set_balance (forest_ada_bal_tra_par, NULL, 0); + t8_forest_set_transition (forest_ada_bal_tra_par, NULL, 0); + t8_forest_set_partition (forest_ada_bal_tra_par, NULL, 0); + t8_forest_commit (forest_ada_bal_tra_par); + + return forest_ada_bal_tra_par; +} + +/* Compute neighbors of all elements in all trees at all faces */ +void +t8_LFN_test (t8_forest_t forest_adapt) +{ + t8_debugf ("~~~~~~~~~~ Into the LFN test fucntion. ~~~~~~~~~~\n"); + + /* Collecting data of the adapted forest */ + const t8_element_t *current_element; + t8_tree_t current_tree; + t8_locidx_t forest_is_balanced = 1; + t8_element_t **neighbor_leafs; + t8_locidx_t *element_indices; + t8_eclass_scheme_c *neigh_scheme; + t8_eclass_t eclass; + t8_eclass_scheme_c *ts; + + int *dual_faces; + int num_neighbors; + int face_id; + int local_num_trees = t8_forest_get_num_local_trees (forest_adapt); /* get the number of trees, this process knows about */ + int current_tree_num_elements; + int subelement_count = 0; + int LFN_call_count = 0; + int tree_count; + int elem_count; + int neighbor_count; + + + for (tree_count = 0; tree_count < local_num_trees; ++tree_count) { + eclass = t8_forest_get_tree_class (forest_adapt, tree_count); + ts = t8_forest_get_eclass_scheme (forest_adapt, eclass); + + /* get the number of elements in the current tree */ + current_tree = t8_forest_get_tree (forest_adapt, tree_count); + current_tree_num_elements = + t8_forest_get_tree_element_count (current_tree); + + for (elem_count = 0; elem_count < current_tree_num_elements; ++elem_count) { + + /* determing the current element according to the given tree id and element id within the tree */ + current_element = + t8_forest_get_element_in_tree (forest_adapt, tree_count, elem_count); + + if (ts->t8_element_is_subelement (current_element)) { + subelement_count++; + } + + /* print current element */ +#if T8_ENABLE_DEBUG + t8_productionf + ("\n\n________________" + "\nCurrent element: local elem index of this process: %i of %i (without ghosts)\n", + elem_count, t8_forest_get_local_num_elements (forest_adapt)); + ts->t8_element_debug_print (current_element); +#endif + + for (face_id = 0; face_id < ts->t8_element_num_faces (current_element); + ++face_id) { + LFN_call_count++; + t8_forest_leaf_face_neighbors (forest_adapt, tree_count, + current_element, &neighbor_leafs, + face_id, &dual_faces, &num_neighbors, + &element_indices, &neigh_scheme, + forest_is_balanced); + /* free memory if neighbors exist */ + if (num_neighbors > 0) { + + /* print all neighbor elements */ + for (neighbor_count = 0; neighbor_count < num_neighbors; + neighbor_count++) { +#if T8_ENABLE_DEBUG + t8_productionf ("\n_________" + "\nNeighbor: %i of %i at face %i: (dual face: %i | local index %i of %i (with ghosts) | ghost, if >= %i):\n", + neighbor_count + 1, num_neighbors, face_id, + dual_faces[neighbor_count], + element_indices[neighbor_count], + t8_forest_get_local_num_elements (forest_adapt) + + t8_forest_get_num_ghosts (forest_adapt), + t8_forest_get_local_num_elements (forest_adapt) + - 1); + ts->t8_element_debug_print (neighbor_leafs[neighbor_count]); +#endif + } + + neigh_scheme->t8_element_destroy (num_neighbors, neighbor_leafs); + + T8_FREE (element_indices); + T8_FREE (neighbor_leafs); + T8_FREE (dual_faces); + } + else { +#if T8_ENABLE_DEBUG + /* no neighbor in this case */ + t8_productionf ("\n_________" + "\nNeighbor: at face %i: There is no neighbor (domain boundary).\n", + face_id); +#endif + } + } /* end of face loop */ + } /* end of element loop */ + } /* end of tree loop */ + + T8_ASSERT (subelement_count == + t8_forest_get_local_num_subelements (forest_adapt)); + + t8_debugf + ("~~~~~~~~~~ The LFN test function finshed successful ~~~~~~~~~~\n"); +} /* end of t8_LFN_test */ + + + + + +/* Initializing, adapting balancing and transitioning a forest */ +static void +t8_transition_global (void) +{ + /* At the moment, subelements are only implemented for hexes and quads */ + t8_eclass_t eclass + = T8_ECLASS_HEX; /* depending on the include file, this will be the transitioned or default hex implementation */ + t8_forest_t forest; + t8_forest_t forest_adapt; + t8_cmesh_t cmesh; + char filename[BUFSIZ]; + + /* refinement setting */ + int level = 2; /* initial uniform refinement level */ + + t8_locidx_t polygons_x = 2; + t8_locidx_t polygons_y = 1; + t8_locidx_t polygons_z = 1; + + const double boundary[24] = { 0, 0, 0, 2, 0, 0, 0, 1, 0, 2, 1, 0, 0, 0, 1, 2, 0, 1, 0, 1, 1, 2, 1, 1 }; + + t8_scheme_cxx_t *scheme = t8_scheme_new_transition_hex_cxx (); + + /* construct a multiple tree hex cmesh */ + // cmesh = t8_cmesh_new_hypercube_pad (eclass, sc_MPI_COMM_WORLD, boundary, polygons_x, polygons_y, polygons_z, 0); + + cmesh = t8_cmesh_new_hypercube(eclass, sc_MPI_COMM_WORLD, 0, 0, 0); + /* Create a uniformly refined forest */ + forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); + + t8_forest_write_vtk (forest, "forest_global_hex"); + + for (int adaptation_count = 1; adaptation_count <= 1; ++adaptation_count) { + + forest_adapt = t8_test_forest_commit_abpt (forest); + + t8_LFN_test (forest_adapt); + + t8_debugf ("---------------ROUND %i ---------------------------\n\n", adaptation_count); + + forest = forest_adapt; + } + t8_forest_write_vtk (forest, "transition_global_hex"); + + t8_forest_unref (&forest_adapt); + +} /* end of t8_transition_global */ + +int +main (int argc, char **argv) +{ + int mpiret; + + mpiret = sc_MPI_Init (&argc, &argv); + SC_CHECK_MPI (mpiret); + + sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_DEFAULT); + t8_init (SC_LP_DEFAULT); + + t8_transition_global (); + + sc_finalize (); + mpiret = sc_MPI_Finalize (); + + SC_CHECK_MPI (mpiret); + + return 0; +} diff --git a/src/t8_element_cxx.hxx b/src/t8_element_cxx.hxx index a735613606..a559978f6a 100644 --- a/src/t8_element_cxx.hxx +++ b/src/t8_element_cxx.hxx @@ -740,6 +740,83 @@ struct t8_eclass_scheme * \param [in] comm MPI Communicator */ /*-----------------------------------Functions for transition schemes------------------------------------------------*/ + + /** Return the subelement id of the neighbor subelement of elem (possibly not subelement) at face elem_face + * that is a sibling of the subelement neigh. + * \param [in] elem a given element (possibly subelement) + * \param [in] neigh a random subelement (pseudoneighbor) in a transition cell from which we assume that it owns the real neighbor of elem + * \param [in] elem_face a given face number of element elem + * \return the subelement id of the real subelement neighbor of element elem, which is a sibling of neigh. + */ + virtual int t8_element_find_neighbor_in_transition_cell (const + t8_element_t + *elem, + const + t8_element_t + *neigh, + int + elem_face) + = 0; + + /** Return the transition type of an element + * \param [in] elem A valid element + * \return the transition type of elem (0 if elem is no subelement) + */ + virtual int t8_element_get_transition_type (const + t8_element * elem) = 0; + +/** Check whether the neighbors of an element at a specic face are siblings + * \param [in] elem A valid element + * \param [in] elem_face A valid face + * \return true if the neighbor of elem at face elem_face is a sibling. + */ + virtual int t8_element_neighbor_is_sibling (const t8_element * elem, + const int elem_face) + const = 0; + + + /** Check whether the neighbors of an element at a specic face are siblings + * \param [in] elem A valid element + * \param [in] elem_face A valid face + * \return return the number of sibling neighbors at a given face. + */ + virtual int t8_element_get_num_sibling_neighbors_at_face (const + t8_element + * elem, + const int + elem_face) const = 0; + + /** Construct all sibling neighbors of elem at face in hex scheme. */ + virtual void + + + + t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t + *elem, + const int face, + const int + num_neighbors, + t8_element_t + *neighbor_at_face[], + int *neigh_face) = + 0; + + /** Construct all sibling neighbors of elem at face in quad scheme. */ + virtual void + + + + t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t + *elem, + const int face, + const int + num_neighbors, + t8_element_t + *neighbor_at_face[], + int *neigh_face[]) = + 0; + /** Return 1 if the eclass scheme has an implementation for subelements, which is conformal. */ + virtual int t8_element_transition_scheme_is_conformal (void) = 0; /** Return zero refine value for schemes that do not have a transition implementation. * \param [in] elem A valid element * \return Integer, used as the refine value during transition adaptation. diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index 1c7a8a0f76..6c9261ff1e 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -834,6 +834,14 @@ t8_forest_comm_global_num_subelements (t8_forest_t forest) SC_CHECK_MPI (mpiret); forest->global_num_subelements = global_num_subel; } +t8_locidx_t +t8_forest_get_local_num_subelements (t8_forest_t forest) +{ + T8_ASSERT (forest->local_num_subelements <= forest->local_num_elements); + T8_ASSERT (t8_forest_is_committed (forest)); + + return forest->local_num_subelements; +} t8_locidx_t t8_forest_get_num_ghosts (const t8_forest_t forest) diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index 9037a2176c..83b891ab99 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -1697,6 +1697,631 @@ t8_forest_element_half_face_neighbors (t8_forest_t forest, t8_locidx_t ltreeid, return neighbor_tree; } +/* This function does not need a declaration and is only called by LFN_transitioned. + * When entering this function, a neighbr transition cell is found and some additional + * subelement-specific functions are applied to return the right subelement neighbor of leaf. */ +void +t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, + t8_element_t *pseudo_neighbor, + const t8_element_t *leaf, + t8_locidx_t element_index, + int face, + t8_locidx_t lneigh_treeid, + t8_element_t **neighbor_leafs, + t8_locidx_t **pelement_indices, + int neighbor_is_ghost, + int *owners, + t8_locidx_t lghost_treeid, + t8_locidx_t ghost_element_index, + t8_eclass_scheme_c *ts, + t8_eclass_scheme_c *neigh_scheme, + int *num_neighbors) +{ + /* Consider the following situation: + * + * this is not yet implemented + * x - - - - - x - - - - - x x - - - - - x + * | | \ pnei / | / | \ pnei / | + * | | \ / | / | \ / | + * | leaf f| nei x | / f| nei x | + * | | / | \ | / leaf | / | \ | + * | | / | \ | / | / | \ | + * x - - - - - x - - x - - x x - - - - - x - - x - - x + * ts == neigh_scheme ts != neigh_scheme + * + * We are looking for the neighbor (nei) of leaf at f. + * Given is a random element (pnei), called pseudo_neighbor, of the neighboring transition cell. + * The aim of this function is to identify the real subelement neighbor (nei) of leaf at f. + * This function is neither implemented for hybrid meshes, nor for nonconformal meshes - we expect exactly one subelement neighbor. */ + + const t8_element_t *neighbor; + t8_locidx_t pseudo_neighbor_index; + int pseudo_neighbor_sub_id; + int leaf_neighbor_sub_id; + + T8_ASSERT (ts == neigh_scheme); + T8_ASSERT (forest->is_transitioned); + T8_ASSERT (neigh_scheme->t8_element_is_subelement (pseudo_neighbor)); + T8_ASSERT (element_index < forest->global_num_elements); + + pseudo_neighbor_index = element_index; + pseudo_neighbor_sub_id = + neigh_scheme->t8_element_get_subelement_id (pseudo_neighbor); + + /* Get the subelement id of the real neighbor of leaf. + * This function will determine the sub_id of the real neighbor, given leaf, face and the pseudo_neighbor. + * This is why ts == neigh_scheme must be true. */ + //It is only valid to call this function if the face of elem is point outwards, thus face = 4. + t8_debugf("face %i\n", face); + t8_debugf("elem is subelement %i\n", ts->t8_element_is_subelement(leaf)); + t8_debugf("neigh is subelement %i\n", ts->t8_element_is_subelement(pseudo_neighbor)); + + leaf_neighbor_sub_id = + neigh_scheme->t8_element_find_neighbor_in_transition_cell (leaf, + pseudo_neighbor, + face); + + if (!neighbor_is_ghost) { + /* adjust the index of the pseudo neighbor to equal the index of the real neighbor. + * The following computation should be true for every subelement scheme and does not require + * a separate t8_element function. The important - and subelement-scheme-dependent - + * aspect is the computation of leaf_neighbor_sub_id above. */ + element_index = + pseudo_neighbor_index - pseudo_neighbor_sub_id + leaf_neighbor_sub_id; + + /* get the real neighbor */ + neighbor = t8_forest_get_tree_element (t8_forest_get_tree + (forest, lneigh_treeid), + element_index - + t8_forest_get_tree_element_offset + (forest, lneigh_treeid)); + + /* free memory */ + neigh_scheme->t8_element_destroy (0, neighbor_leafs + 1); + /* copy the neighbor */ + neigh_scheme->t8_element_copy (neighbor, neighbor_leafs[0]); + + /* set return values */ + *pelement_indices = T8_ALLOC (t8_locidx_t, 1); + (*pelement_indices)[0] = element_index; + + T8_FREE (owners); + + *num_neighbors = 1; + + return; + } + + /* the neighbor subelement is a ghost */ + int search_direction = + (leaf_neighbor_sub_id > pseudo_neighbor_sub_id) ? 1 : -1; + int id_diff_abs = + (leaf_neighbor_sub_id - pseudo_neighbor_sub_id) * search_direction; + + bool neighbor_found = false; + int subelement_count = 0; + + while (!neighbor_found) { + T8_ASSERT (ghost_element_index >= 0); /* check, that ghost_element_index has been set before */ + + const t8_element_t *check_neighbor; + check_neighbor = + t8_forest_ghost_get_element (forest, lghost_treeid, + ghost_element_index + + search_direction * subelement_count); + + if (neigh_scheme->t8_element_get_subelement_id (check_neighbor) == + leaf_neighbor_sub_id) { + /* both elements should be siblings or equal */ + T8_ASSERT (neigh_scheme->t8_element_get_transition_type (check_neighbor) + == + neigh_scheme->t8_element_get_transition_type + (pseudo_neighbor)); + + /* adjust element index */ + element_index = element_index + search_direction * subelement_count; + + /* free memory */ + neigh_scheme->t8_element_destroy (0, neighbor_leafs + 1); + /* copy the neighbor */ + neigh_scheme->t8_element_copy (check_neighbor, neighbor_leafs[0]); + + /* set return values */ + *pelement_indices = T8_ALLOC (t8_locidx_t, 1); + (*pelement_indices)[0] = element_index; + + T8_FREE (owners); + + /* neighbor found */ + neighbor_found = true; + } + + if (subelement_count > id_diff_abs) { /* we assume that the real neighbor is a sibling subelement and hence we should find it here */ + SC_ABORT ("Ghost subelement neighbor not found!\n"); + } + + subelement_count++; + } /* end while-loop to identify ghost-subelement neighbor */ + + *num_neighbors = 1; + + return; +} + +/* This is the transitioned version of the LFN funciton. It does not need a declaration + * as it is only called by LFN if the input forest is transitioned. + * Note: there is a lot of code duplication compared to LFN, but it might be better to seperate the transitioned LFN + * from the standard LFN for now. */ +void +t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, + t8_locidx_t ltreeid, + const t8_element_t *leaf, + t8_element_t **pneighbor_leafs[], + int face, int *dual_faces[], + int *num_neighbors, + t8_locidx_t **pelement_indices, + t8_eclass_scheme_c + **pneigh_scheme, + int forest_is_balanced) +{ + /* Consider the following transitioned forest: + * + * forest + * f1 + * x - - x - - x - - - - - x + * | | | \ sub / | + * | | | f0\ /f2 | + * x - - x - - x - - x | + * | | f1| / | \ | + * | | elem| / | \ | + * x - - x - - x - - x - - x + * + * How do we identify neighbors in transitioned forests? + * 1) Check whether the current element is a subelement. If yes, then its neighbor might be a sibling subelement (for example sub at f0 or f2). + * If so, then we can quickly compute and return the corresponding neighbor. + * 2) Otherwise (in case of elem at any face or sub at f1), we apply the standard LFN concept of face neighbors or half-face neighbors + * to identify the real neighbor element. Here, it does not matter whether the current element is a subelement or a standard element. + * 3) We are done at 2) if the identified neighbor is no subelement. Otherwise (like in the case of elem at f1), the binary search, based on the Morton-Index + * will randomly pick one subelement of the corresponding transition cell (since, by definition they all share the same Morton Index). + * Hence, in this case we apply some additional - subelement specific - t8_element functions in order to return the right subelement neighbor. */ + + /* In the following, + * - leaf (ts scheme) is the current element of the forest + * - neighbor_leafs[] (neigh_scheme) is an array of neighbors of leaf. At first, it consists of VFNs or VHFNs (virtual (half) face neighbors)of leaf at f + * Later, the real neighbor elements are copied into this array and returned by the LFN function + * - ancestor (neigh_scheme) is a "first guess". It is a leaf element of the forest that corresponds to the VFNs or VHFNs in neighbor_leafs[] */ + + t8_eclass_t neigh_class, eclass; + t8_gloidx_t gneigh_treeid; + t8_locidx_t lneigh_treeid = -1; + t8_locidx_t lghost_treeid = + -1, *element_indices, element_index, subelement_neighbor_index, + ghost_element_index = -1; + t8_eclass_scheme_c *ts, *neigh_scheme; + t8_element_array_t *element_array; + t8_element_t *ancestor, **neighbor_leafs; + t8_linearidx_t neigh_id; + int num_children_at_face, at_maxlevel; + int ineigh, *owners, different_owners, have_ghosts, + neighbor_is_ghost = 0; + + T8_ASSERT (t8_forest_is_committed (forest)); + + /* This function should only be called for transitioned forests */ + T8_ASSERT (forest->is_transitioned); + + if (forest_is_balanced) { + /* In a balanced forest, the leaf neighbor of a leaf is either the neighbor element itself, + * its parent or its children at the face. If the forest is transitioned, + * then the neighbor might also be a subelement whose level will also differ at most by +-1 to the leaf element. + * The leaf might as well be a subelement. */ + eclass = t8_forest_get_tree_class (forest, ltreeid); + ts = t8_forest_get_eclass_scheme (forest, eclass); + + /* LFN_transitioned does not yet support nonconformal transitioned meshes. + * Hybrid meshes can be used if both schemes support conformal transitioning. */ + SC_CHECK_ABORT ((ts->t8_element_scheme_supports_transitioning () + && ts->t8_element_transition_scheme_is_conformal ()), + "LFN_transitioned not implemented for nonconformal transition schemes"); + + /* In the following, we compute the children of the face neighbor elements of leaf. For this, we need the + * neighbor tree's eclass, scheme, and tree id */ + neigh_class = + t8_forest_element_neighbor_eclass (forest, ltreeid, leaf, face); + neigh_scheme = *pneigh_scheme = + t8_forest_get_eclass_scheme (forest, neigh_class); + + /* 1) Check whether the current element is a subelement and whether its neighbor is a sibling subelement */ + + /* If the current element is a subelement, then we can determine whether its neighbor + * at face is a sibling. If so, then we can easily compute its neighbor. + * Note, that a transition cell (a family of subelements will always be within the same process) */ + if (ts->t8_element_is_subelement (leaf)) { + if (ts->t8_element_neighbor_is_sibling (leaf, face) > 0) { + /* subelement siblings will be in the same local tree */ + T8_ASSERT (ts == neigh_scheme); + *num_neighbors = + ts->t8_element_get_num_sibling_neighbors_at_face (leaf, face); + neighbor_leafs = *pneighbor_leafs = + T8_ALLOC (t8_element_t *, *num_neighbors); + *dual_faces = T8_ALLOC (int, *num_neighbors); + ts->t8_element_new (*num_neighbors, neighbor_leafs); + if ( eclass == 4){ + ts->t8_element_get_sibling_neighbor_in_transition_cell_hex (leaf, face, + *num_neighbors, + neighbor_leafs, + *dual_faces); + } + if (eclass == 2) { + ts->t8_element_get_sibling_neighbor_in_transition_cell (leaf, face, + *num_neighbors, + neighbor_leafs, + dual_faces); + } + + *pelement_indices = T8_ALLOC (t8_locidx_t, *num_neighbors); + element_indices = *pelement_indices; + for (int neighbor_count = 0; neighbor_count < *num_neighbors; + neighbor_count++) { + t8_debugf("num neighbors %i\n", *num_neighbors); + neigh_id = + ts->t8_element_get_linear_id (neighbor_leafs[neighbor_count], + forest->maxlevel); + element_array = t8_forest_get_tree_element_array (forest, ltreeid); + subelement_neighbor_index = + t8_forest_bin_search_lower (element_array, neigh_id, + forest->maxlevel); + element_indices[neighbor_count] = + subelement_neighbor_index - + ts->t8_element_get_subelement_id (t8_forest_get_tree_element + (t8_forest_get_tree + (forest, ltreeid), + subelement_neighbor_index)) + + + ts->t8_element_get_subelement_id (neighbor_leafs[neighbor_count]); + T8_ASSERT (element_indices[neighbor_count] >= 0); + } + return; + } + } + + /* 2) The neighbor is no sibling subelement. Move on with the standard (half)-face-neighbor procedure */ + + /* If we are at the maximum refinement level, + * then we compute the single neighbor instead. */ + at_maxlevel = + ts->t8_element_level (leaf) == t8_forest_get_maxlevel (forest); + if (at_maxlevel || ts->t8_element_transition_scheme_is_conformal ()) { + /* If leaf has maxlevel or the current eclass scheme is transitioned and conformal, + * we know that the leaf element has at most one neighbor at each face. + * Note that in hybrid meshes, the mesh must not be conformal since not each tree might be conformal */ + num_children_at_face = 1; + neighbor_leafs = *pneighbor_leafs = T8_ALLOC (t8_element_t *, num_children_at_face); + *dual_faces = T8_ALLOC (int, num_children_at_face); + neigh_scheme->t8_element_new (num_children_at_face, neighbor_leafs); + /* Compute virtual neighbor element and global treeid of the neighbor */ + gneigh_treeid = + t8_forest_element_face_neighbor (forest, ltreeid, leaf, + neighbor_leafs[0], neigh_scheme, + face, *dual_faces); + } + else { + /* At this point, we expect an arbitrary number of neighbors. Our transition implementation is + * build for this case and does not require a conformal mesh. */ + + /* Note the following: LFN is only implemented for balanced meshes and therefore uses the concept of + * virtual half face neighbors. This concept WILL NOT WORK for a nonconformal transition scheme whose transition cells enable more + * neighbors than the maximum number of neighbors per element in the forests pure balanced version. + * This is because in such cases the concept of half face neighbors would not be sufficient to depict all + * neighbor subelements in a neighboring transition cell. + * TODO: think of a solution for this issue to enable more complex transition cells, consider for example the following situation: + * + * quad transition cell + * x - - - - - x - - - x + * | x - - - x -> transition cell with three subelements + * | x - - - x (too many neighbors for only two half face neighbors of leaf) + * | leaf f x - - - x + * | | | -> normal quad + * | | | + * x - - - - - x - - - x + * + * Note that the above example counts as "balanced", but half face neighbors would not be sufficient to find all neighbors of leaf at f. + * Currently, ancestor would identify as the lower normal quad neighbor and afterwards, we would just use the second HFN of leaf as the + * second neighbor. But in such a transitioned case, there is a whole transition cell of neighbors corresponding to the second HFN. + * Furthermore, even if there would only be one subelement neighbor, this neighbor would be a subelement, NOT EQUALING the second HFN. */ + + /* Allocate neighbor element */ + num_children_at_face = ts->t8_element_num_face_children (leaf, face); + neighbor_leafs = *pneighbor_leafs = + T8_ALLOC (t8_element_t *, num_children_at_face); + *dual_faces = T8_ALLOC (int, num_children_at_face); + neigh_scheme->t8_element_new (num_children_at_face, neighbor_leafs); + /* Compute virtual neighbor elements and global treeid of the neighbor */ + gneigh_treeid = + t8_forest_element_half_face_neighbors (forest, ltreeid, leaf, + neighbor_leafs, + neigh_scheme, face, + num_children_at_face, + *dual_faces); + } + + /* neighbor_leafs[i] do now equal the FN or HFN of leaf at f. In the following we check whether there is only one neighbor + * and whether neighbor_leafs[i] have to be adjusted further. Finally, the neighbor_leafs element array is returned by the LFN function. */ + + if (gneigh_treeid < 0) { + /* There exists no face neighbor across this face, we return with this info */ + neigh_scheme->t8_element_destroy (1, neighbor_leafs); + T8_FREE (neighbor_leafs); + T8_FREE (*dual_faces); + *dual_faces = NULL; + *num_neighbors = 0; + *pelement_indices = NULL; + *pneighbor_leafs = NULL; + return; + } + T8_ASSERT (gneigh_treeid >= 0 + && gneigh_treeid < forest->global_num_trees); + /* We have computed the half face neighbor elements, we now compute their owners, + * if they differ, we know that the half face neighbors are the neighbor leafs. + * If the owners do not differ, we have to check if the neighbor leaf is their + * parent or grandparent. */ + owners = T8_ALLOC (int, num_children_at_face); + different_owners = 0; + have_ghosts = 0; + for (ineigh = 0; ineigh < num_children_at_face; ineigh++) { + /* At first, we check whether the current rank owns the neighbor, since + * this is a constant time check and it is the most common case */ + if (t8_forest_element_check_owner (forest, neighbor_leafs[ineigh], + gneigh_treeid, neigh_class, + forest->mpirank, at_maxlevel)) { + owners[ineigh] = forest->mpirank; + /* The neighbor tree is also a local tree. we store its local treeid */ + lneigh_treeid = t8_forest_get_local_id (forest, gneigh_treeid); + } + else { + owners[ineigh] = + t8_forest_element_find_owner (forest, gneigh_treeid, + neighbor_leafs[ineigh], neigh_class); + /* Store that at least one neighbor is a ghost */ + have_ghosts = 1; + } + if (ineigh > 0) { + /* Check if all owners are the same for all neighbors or not */ + different_owners = different_owners + || (owners[ineigh] != owners[ineigh - 1]); + } + } + if (have_ghosts) { + /* At least one neighbor is a ghost, we compute the ghost treeid of the neighbor + * tree. */ + lghost_treeid = + t8_forest_ghost_get_ghost_treeid (forest, gneigh_treeid); + T8_ASSERT (lghost_treeid >= 0); + } + + if (!different_owners) { + /* The face neighbors belong to the same process, we thus need to determine + * if they are leafs or their parent or grandparent. */ + neigh_id = + neigh_scheme->t8_element_get_linear_id (neighbor_leafs[0], + forest->maxlevel); + if (owners[0] != forest->mpirank) { + /* The elements are ghost elements of the same owner */ + neighbor_is_ghost = 1; + element_array = + t8_forest_ghost_get_tree_elements (forest, lghost_treeid); + /* Find the index in element_array of the leaf ancestor of the first neighbor. + * This is either the neighbor itself or its parent, or its grandparent */ + element_index = + t8_forest_bin_search_lower (element_array, neigh_id, + forest->maxlevel); + /* Get the element */ + ancestor = + t8_forest_ghost_get_element (forest, lghost_treeid, element_index); + /* Add the number of ghost elements on previous ghost trees and the number + * of local elements. */ + ghost_element_index = element_index; + element_index += + t8_forest_ghost_get_tree_element_offset (forest, lghost_treeid); + element_index += t8_forest_get_local_num_elements (forest); + T8_ASSERT (forest->local_num_elements <= element_index + && element_index < + forest->local_num_elements + + t8_forest_get_num_ghosts (forest)); + } + else { + /* the elements are local elements */ + element_array = + t8_forest_get_tree_element_array (forest, lneigh_treeid); + /* Find the index in element_array of the leaf ancestor of the first neighbor. + * This is either the neighbor itself or its parent, or its grandparent */ + element_index = + t8_forest_bin_search_lower (element_array, neigh_id, + forest->maxlevel); + /* Get the element */ + ancestor = + t8_forest_get_tree_element (t8_forest_get_tree + (forest, lneigh_treeid), element_index); + /* Add the element offset of this tree to the index */ + element_index += + t8_forest_get_tree_element_offset (forest, lneigh_treeid); + } + + if ((neigh_scheme->t8_element_compare (ancestor, neighbor_leafs[0]) < 0) + || ts->t8_element_is_subelement (leaf)) { + + /* we expect only one neighbor (or a neighboring transition cell with possibly multiple + * subelement neighbors if the transition scheme is not conformal) in this case */ + + /* We need to determine the dual face */ + if (neigh_scheme->t8_element_level (ancestor) == + ts->t8_element_level (leaf)) { + /* The ancestor is the same-level neighbor of leaf */ + if (!at_maxlevel) { + /* its dual face is the face of the parent of the first neighbor leaf */ + *dual_faces[0] = + neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], + *dual_faces[0]); + } + } + else if (neigh_scheme->t8_element_level (ancestor) == + ts->t8_element_level (leaf) + 1) { + *dual_faces[0] = + neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], + *dual_faces[0]); + } + else { + /* The ancestor is the parent of the parent */ + + T8_ASSERT (neigh_scheme->t8_element_level (ancestor) == + ts->t8_element_level (leaf) - 1); + + *dual_faces[0] = + neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], + *dual_faces[0]); + if (!at_maxlevel) { + /* We need to compute the dual face of the grandparent. */ + /* Construct the parent of the grand child */ + neigh_scheme->t8_element_parent (neighbor_leafs[0], + neighbor_leafs[0]); + /* Compute the face id of the parent's face */ + *dual_faces[0] = + neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], + *dual_faces[0]); + } + } + + /* 3) A leaf neighbor (ancestor) is found. First, check whether leaf is a subelement + * in a transition cell. If yes, then apply subelement-specific functions. + * Otherwise, continue with the standard LFN procedure. */ + + /* TODO: nonconformal meshes will need a loop over all ancestors, corresponding to all neighbor_leafs[i]. + * And for each ancestor we would need to check whether it is a subelement and then determine all subelement neighbors + * which might be more than one. */ + + if (neigh_scheme->t8_element_is_subelement (ancestor)) { + /* At this point, "ancestor" is a random subelement of the neighboring transition cell of leaf. */ + /* We need to identify the real subelement neighbor within this transition cell. */ + + /* TODO: in nonconformal transitioned forests there might be more than one subelement neighbor + * in a neighboring transition cell - not implemented yet */ + T8_ASSERT (neigh_scheme->t8_element_transition_scheme_is_conformal + ()); + t8_forest_get_transition_cell_face_neighbor (forest, ancestor, leaf, + element_index, face, + lneigh_treeid, + neighbor_leafs, + pelement_indices, + neighbor_is_ghost, + owners, lghost_treeid, + ghost_element_index, + ts, neigh_scheme, + num_neighbors); + return; + } + + /* free memory */ + neigh_scheme->t8_element_destroy (num_children_at_face - 1, + neighbor_leafs + 1); + /* copy the ancestor */ + neigh_scheme->t8_element_copy (ancestor, neighbor_leafs[0]); + /* set return values */ + *num_neighbors = 1; + *pelement_indices = T8_ALLOC (t8_locidx_t, 1); + (*pelement_indices)[0] = element_index; + + T8_FREE (owners); + return; + } /* end of (t8_element_compare < 0) || leaf is subelement */ + } /* end of if !different owner */ + + /* neighbor_leafs[i] are not adjusted below this comment. + * Hence, we assume that the FNs or HFNs equal the real leaf neighbor elements. */ + + /* The leafs are the face neighbors that we are looking for. */ + /* The face neighbors either belong to different processes and thus must be leafs + * in the forest, or the ancestor leaf of the first half neighbor is the half + * neighbor itself and thus all half neighbors must be leafs. + * Since the forest is balanced, we found all neighbor leafs. + * It remains to compute their local ids */ + *num_neighbors = num_children_at_face; + *pelement_indices = T8_ALLOC (t8_locidx_t, num_children_at_face); + element_indices = *pelement_indices; + for (ineigh = 0; ineigh < num_children_at_face; ineigh++) { + /* Compute the linear id at maxlevel of the neighbor leaf */ + neigh_id = + neigh_scheme->t8_element_get_linear_id (neighbor_leafs[ineigh], + forest->maxlevel); + /* Get a pointer to the element array in which the neighbor lies and search + * for the element's index in this array. + * This is either the local leaf array of the local tree or the corresponding leaf array + * in the ghost structure */ + if (owners[ineigh] == forest->mpirank) { + /* The neighbor is a local leaf */ + element_array = + t8_forest_get_tree_element_array (forest, lneigh_treeid); + /* Find the index of the neighbor in the array */ + element_indices[ineigh] = + t8_forest_bin_search_lower (element_array, neigh_id, + forest->maxlevel); + T8_ASSERT (element_indices[ineigh] >= 0); + /* We have to add the tree's element offset to the index found to get + * the actual local element id */ + element_indices[ineigh] += + t8_forest_get_tree_element_offset (forest, lneigh_treeid); +#if T8_ENABLE_DEBUG + /* We check whether the element is really the element at this local id */ + { + t8_locidx_t check_ltreeid; + t8_element_t *check_element; + check_element = + t8_forest_get_element (forest, element_indices[ineigh], + &check_ltreeid); + T8_ASSERT (check_ltreeid == lneigh_treeid); + T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, + neighbor_leafs + [ineigh])); + } +#endif + } + else { + /* The neighbor is a ghost */ + element_array = + t8_forest_ghost_get_tree_elements (forest, lghost_treeid); + /* Find the index of the neighbor in the array */ + element_indices[ineigh] = + t8_forest_bin_search_lower (element_array, neigh_id, + forest->maxlevel); + +#if T8_ENABLE_DEBUG + /* We check whether the element is really the element at this local id */ + { + t8_element_t *check_element; + check_element = + t8_forest_ghost_get_element (forest, lghost_treeid, + element_indices[ineigh]); + T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, + neighbor_leafs + [ineigh])); + t8_debugf ("LFN_transitioned: the neighbor is a ghost.\n"); + } +#endif + /* Add the element offset of previous ghosts to this index */ + element_indices[ineigh] += + t8_forest_ghost_get_tree_element_offset (forest, lghost_treeid); + /* Add the number of all local elements to this index */ + element_indices[ineigh] += t8_forest_get_local_num_elements (forest); + } + } /* End for loop over neighbor leafs */ + T8_FREE (owners); + } /* end of if (forest_is_balanced || forest->is_transitioned) (main part of the LFN) */ + else { + /* TODO: implement unbalanced version */ + SC_ABORT_NOT_REACHED (); + } +} + + int t8_forest_leaf_face_orientation (t8_forest_t forest, const t8_locidx_t ltreeid, const t8_eclass_scheme_c *ts, const t8_element_t *leaf, int face) @@ -1732,12 +2357,24 @@ t8_forest_leaf_face_neighbors_ext (t8_forest_t forest, t8_locidx_t ltreeid, cons /* TODO: implement is_leaf check to apply to leaf */ T8_ASSERT (t8_forest_is_committed (forest)); - T8_ASSERT (!forest_is_balanced || t8_forest_is_balanced (forest)); + T8_ASSERT (forest_is_balanced); + // T8_ASSERT (!forest_is_balanced || t8_forest_is_balanced (forest)); SC_CHECK_ABORT (forest_is_balanced, "leaf face neighbors is not implemented " "for unbalanced forests.\n"); /* TODO: write version for unbalanced forests */ SC_CHECK_ABORT (forest->mpisize == 1 || forest->ghosts != NULL, "Ghost structure is needed for t8_forest_leaf_face_neighbors " "but was not found in forest.\n"); + /* if the given forest is transitioned, then call the transitioned LFN function. */ + if (forest->is_transitioned) { + t8_forest_leaf_face_neighbors_transitioned (forest, ltreeid, + leaf, pneighbor_leaves, + face, dual_faces, + num_neighbors, + pelement_indices, + pneigh_scheme, + forest_is_balanced); + return; + } if (forest_is_balanced) { /* In a balanced forest, the leaf neighbor of a leaf is either the neighbor element itself, @@ -1959,6 +2596,7 @@ t8_forest_leaf_face_neighbors (t8_forest_t forest, t8_locidx_t ltreeid, const t8 t8_locidx_t **pelement_indices, t8_eclass_scheme_c **pneigh_scheme, int forest_is_balanced) { + t8_forest_leaf_face_neighbors_ext (forest, ltreeid, leaf, pneighbor_leaves, face, dual_faces, num_neighbors, pelement_indices, pneigh_scheme, forest_is_balanced, NULL, NULL); } diff --git a/src/t8_forest/t8_forest_general.h b/src/t8_forest/t8_forest_general.h index 44ac12b453..f1bf0749e0 100644 --- a/src/t8_forest/t8_forest_general.h +++ b/src/t8_forest/t8_forest_general.h @@ -394,6 +394,13 @@ t8_forest_comm_global_num_subelements (t8_forest_t forest); t8_gloidx_t t8_forest_get_global_num_subelements (t8_forest_t forest); +/** Return the number of process local subelements in the forest. + * \param [in] forest A forest. + * \return The number of subelements on this process in \a forest. + * \a forest must be committed before calling this function. + */ +t8_locidx_t t8_forest_get_local_num_subelements (t8_forest_t forest); + /** Set a source forest to use subelements during commit, that will remove hanging faces from the adapted mesh. * \param [in, out] forest The forest. * \param [in] set_from A second forest that should be transitioned. diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx index b4fbaf4aca..12e6f1c7d1 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx @@ -169,6 +169,73 @@ t8_default_scheme_common_c::t8_element_deinit (int length, t8_element_t *elem) c } /*----------------------------Functions for transition schemes--------------------------------------------*/ +int +t8_default_scheme_common_c::t8_element_find_neighbor_in_transition_cell (const + t8_element_t + *elem, + const + t8_element_t + *neigh, + int + elem_face) +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} + +int +t8_default_scheme_common_c::t8_element_get_transition_type (const + t8_element * elem) +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} + +int +t8_default_scheme_common_c::t8_element_neighbor_is_sibling (const t8_element * + elem, + const int face) const +{ + /* No subelements are implemented and therefore we return false, + * meaning "the neighbor at face is not a sibling of elem". */ + t8_debugf + ("This is the default_common implementation of t8_element_neighbor_is_sibling.\n"); + return 0; +} + +int +t8_default_scheme_common_c::t8_element_get_num_sibling_neighbors_at_face (const t8_element * elem, + const int face) const + +{ + /* No subelements are implemented and therefore we return false meaning "the neighbor at face is not a sibling of elem". */ + t8_debugf + ("This is the default_common implementation of t8_element_get_num_sibling_neighbors_at_face.\n"); + return 0; +} +void +t8_default_scheme_common_c::t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t *elem, + const int face, + const int num_neighbors, + t8_element_t *neighbor_at_face[], + int *neigh_face) +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} +void +t8_default_scheme_common_c::t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t *elem, + const int face, + const int num_neighbors, + t8_element_t *neighbor_at_face[], + int *neigh_face[]) +{ + SC_ABORT ("This function is not implemented for the given scheme.\n"); +} +int +t8_default_scheme_common_c::t8_element_transition_scheme_is_conformal (void) +{ + /* Default implementation - current scheme is no transition scheme */ + return 0; +} + int t8_default_scheme_common_c::t8_element_get_transition_refine_identifier () const { diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx index 52ef47f595..4b639296ac 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx @@ -128,6 +128,78 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { t8_element_anchor (const t8_element_t *elem, int anchor[3]) const = 0; /*-----------------------------Functions for transition schemes---------------------------------*/ + /** Return the subelement id of the neighbor subelement of elem at face elem_face + * that is a sibling of the subelement neigh. + * \param [in] elem a given element (possibly subelement) + * \param [in] neigh a random subelement (pseudoneighbor) in a transition cell from which we assume that it owns the real neighbor of elem + * \param [in] elem_face a given face number of element elem + * \return the subelement id of the real subelement neighbor of element elem, which is a sibling of neigh. + */ + virtual int t8_element_find_neighbor_in_transition_cell (const + t8_element_t + *elem, + const + t8_element_t + *neigh, + int + elem_face); + + /** Return the transition type of an element + * \param [in] elem A valid element + * \return the transition type of elem (0 if elem is no subelement) + */ + virtual int t8_element_get_transition_type (const + t8_element * elem); + /** Check whether the neighbors of an element at a specic face are siblings + * \param [in] elem A valid element + * \param [in] elem_face A valid face + * \return true if the neighbor of elem at face elem_face is a sibling. + */ + virtual int t8_element_neighbor_is_sibling (const t8_element * elem, + const int elem_face) + const; + + + /** Check whether the neighbors of an element at a specic face are siblings + * \param [in] elem A valid element + * \param [in] elem_face A valid face + * \return return the number of sibling neighbors at a given face. + */ + virtual int t8_element_get_num_sibling_neighbors_at_face (const + t8_element + * elem, + const int + elem_face) const; + /** Construct all sibling neighbors of elem at face in hex scheme. */ + virtual void + + + + t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t + *elem, + const int face, + const int + num_neighbors, + t8_element_t + *neighbor_at_face[], + int *neigh_face); + + /** Construct all sibling neighbors of elem at face in quad scheme */ + virtual void + + + + t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t + *elem, + const int face, + const int + num_neighbors, + t8_element_t + *neighbor_at_face[], + int *neigh_face[]); + + /** Return 1 if the eclass scheme has an implementation for subelements, which is conformal. */ + virtual int t8_element_transition_scheme_is_conformal (void); /** Return zero refine value for schemes that do not have a transition implementation. * \param [in] elem A valid element diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 4887a22443..971a963056 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -458,6 +458,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h * element ID). If the transition type is = 1 at the hex_face, it's split.*/ //-----------------------------CASE 1-------------------------------------------------------- + t8_debugf("CASE 1\n"); //make rightshift until only the bits for the faces before our neighbors face are left. transition_type_tmp = transition_type >> (5 - neigh_hex_face); @@ -485,6 +486,8 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h } //-------------------------CASE 2-------------------------------------- else { //neighbor is split. We have to return 2 subelements. + t8_debugf("CASE 2\n"); + amount_subelements = 0; int subelement_id_tmp2 = 0; // In here we store the second subelement ID in case 2 if elem has two neighbors /* For case 2 we need a second face neighbor */ @@ -556,6 +559,9 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h //-------------------------CASE 3-------------------------------------- else { + t8_debugf("CASE 3\n"); + t8_debugf("location[0] = %i\n", location[0]); + //The own face is split //get hex_face_number of the face_neighbored subelement //Condition that the neighbor lies not on the same hex face: @@ -564,16 +570,24 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h if (location[0] == 0 || location[0] == 1) { if (((location[2] & 2) == 0) && (face == 1)) { //front hlp += 1; + t8_debugf("hlp front %i\n", hlp); + } if (((location[2] & 2) != 0) && (face == 0)) { //back hlp += 1; + t8_debugf("hlp back %i\n", hlp); + } if (((location[2] & 1) == 0) && (face == 3)) { //bottom hlp += 1; + t8_debugf("hlp bottom %i\n", hlp); + } if (((location[2] & 1) != 0) && (face == 2)) { //up hlp += 1; + t8_debugf("hlp up %i\n", hlp); + } } //hex face 2 and 3 @@ -597,19 +611,26 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h if (location[0] == 4 || location[0] == 5) { if (((location[2] & 4) == 0) && (face == 1)) { //left hlp += 1; + t8_debugf("hlp left %i\n", hlp); + } if (((location[2] & 4) != 0) && (face == 0)) { //right hlp += 1; + t8_debugf("hlp right %i\n", hlp); + } if (((location[2] & 2) == 0) && (face == 3)) { //front hlp += 1; + t8_debugf("hlp front %i\n", hlp); + } if (((location[2] & 2) != 0) && (face == 2)) { //back hlp += 1; + t8_debugf("hlp back %i\n", hlp); + } } - //if none of these conditions is true, we are in case 3 neigh_hex_face = subelement_face_to_dual_subelement[location[0]][face]; if ((hlp == 0) && ((transition_type & (int) pow (2, 5 - neigh_hex_face)) == 0)) { @@ -641,6 +662,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h //---------------------------CASE 4-------------------------------------- else { + t8_debugf("CASE 4\n"); //It's possible, that the neighbored subelement has the same face_hex number as the element itself // amount_subelements = 0; @@ -680,18 +702,20 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h } if (location[0] == 2 || location[0] == 3) { // hex_face = 2/3 - if ((location[2] & 4) != 0) { //right + if ((location[2] & 4) == 0) { //left + if (face == 1) { // then it's the next element + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; + hlp += 1; + } + else { //right if (face == 0) { //then it's the element before. subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; hlp += 1; } } - else { //left - if (face == 1) { // then it's the next element - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; - hlp += 1; - } + } + if ((location[2] & 1) != 0) { //up if (face == 2) { //then it's the element below subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; @@ -707,16 +731,17 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h } if (location[0] == 4 || location[0] == 5) { // hex_face = 4/5 + if ((location[2] & 4) != 0) { //right if (face == 0) { //then it's the element before. subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; hlp += 1; } - else { //left - if (face == 1) { //then it's the next element. - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; - hlp += 1; - } + } + else{ + if (face == 3){ + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; + hlp += 1; } } if ((location[2] & 2) != 0) { //back @@ -882,6 +907,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h } } phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; + t8_debugf("subelement ID nach neighbor function %i\n", subelement_id_tmp); } void @@ -2535,7 +2561,7 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell (const t T8_ASSERT (t8_element_is_subelement (pseudo_neigh)); /* Case 1: the neighbor is ab sibling of elem --> function t8_element_get_sibling_neighbor_in_transition_cell * Thus, we expect elem_face = 4*/ - T8_ASSERT (elem_face == 4); + // T8_ASSERT (elem_face == 4); const t8_hex_with_subelements *phex_w_sub_elem = (const t8_hex_with_subelements *) elem; const t8_hex_with_subelements *phex_w_sub_pseudo_neigh = (const t8_hex_with_subelements *) pseudo_neigh; @@ -2547,11 +2573,11 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell (const t * The idea is to fill a location array with the desired properties of the real neighbor. * Together with the type of the transition cell of pseudo_neigh, we can then identify the sub_id of the right neighbor. */ /* get the location of elem */ - int location_elem[3] = {}; /* {face, is_split, number of subelement at face} */ - t8_element_get_location_of_subelement (elem, location_elem); + //Case 2: The element is a subelement and we are looking for a face neighbor at face 4. if (t8_element_is_subelement (elem)) { - + int location_elem[3] = {}; /* {face, is_split, number of subelement at face} */ + t8_element_get_location_of_subelement (elem, location_elem); /* In this case, we have the following examplary situation in the 2D quad case: * * x - - - - - - - x - - - - - - - x @@ -2647,7 +2673,9 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell (const t /* the pseudo_neigh transition cell has a lower level than elem */ if (phex_w_sub_pseudo_neigh->p8q.level < phex_w_sub_elem->p8q.level) { //actually same case as case 2 just without location array of elem - location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; + // location_neigh[0] = subelement_location_to_parent_dual_face[location_elem[0]]; + location_neigh[0] = subelement_location_to_parent_dual_face[elem_face]; + location_neigh[1] = 1; /* split */ if ((elem_face == 0) || (elem_face == 1)) { /* left/right face of transition cell */ if (phex_w_sub_pseudo_neigh->p8q.y != phex_w_sub_elem->p8q.y) { @@ -2824,6 +2852,12 @@ t8_subelement_scheme_hex_c::t8_element_root (t8_element_t *elem) const p8est_quadrant_set_morton (hex, 0, 0); T8_ASSERT (p8est_quadrant_is_extended (hex)); } +int +t8_subelement_scheme_hex_c::t8_element_transition_scheme_is_conformal (void) +{ + return T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL; +} + #ifdef T8_ENABLE_DEBUG @@ -2849,7 +2883,7 @@ t8_subelement_scheme_hex_c::t8_element_subelement_values_are_valid (const t8_ele { const t8_hex_with_subelements *phex_w_sub = (const t8_hex_with_subelements *) elem; - + // t8_debugf("transition type %i, sub id %i \n", phex_w_sub->transition_type, phex_w_sub->subelement_id); return ((phex_w_sub->transition_type >= 0 && phex_w_sub->transition_type <= T8_SUB_HEX_MAX_TRANSITION_TYPE) && (phex_w_sub->subelement_id >= 0 && phex_w_sub->subelement_id <= T8_SUB_HEX_MAX_SUBELEMENT_ID)); } diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index af17623a62..df65cad34e 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -341,6 +341,9 @@ struct t8_subelement_scheme_hex_c: public t8_default_scheme_common_c virtual void t8_element_last_descendant_face (const t8_element_t *elem, int face, t8_element_t *last_desc, int level) const; +/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int t8_element_transition_scheme_is_conformal (void); + /** Construct the boundary element at a specific face. */ virtual void t8_element_boundary_face (const t8_element_t *elem, int face, t8_element_t *boundary, From b1a1191fe160c17b278c3903483e46d4096da3f4 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Thu, 13 Jun 2024 13:09:10 +0200 Subject: [PATCH 32/55] Typos + corrected bug, LFN works --- example/transition/t8_transition_LFN_hex.cxx | 118 +++--- src/t8_element_cxx.hxx | 83 ++-- src/t8_forest/t8_forest_cxx.cxx | 371 ++++++------------ src/t8_forest/t8_forest_general.h | 3 +- .../t8_default_common_cxx.cxx | 38 +- .../t8_default_common_cxx.hxx | 75 ++-- .../t8_transition_conformal_hex_cxx.cxx | 64 ++- .../t8_transition_conformal_hex_cxx.hxx | 7 +- 8 files changed, 275 insertions(+), 484 deletions(-) diff --git a/example/transition/t8_transition_LFN_hex.cxx b/example/transition/t8_transition_LFN_hex.cxx index 6dec97602d..f0bb1afcda 100644 --- a/example/transition/t8_transition_LFN_hex.cxx +++ b/example/transition/t8_transition_LFN_hex.cxx @@ -79,29 +79,29 @@ t8_test_forest_commit_abpt (t8_forest_t forest) void t8_LFN_test (t8_forest_t forest_adapt) { - t8_debugf ("~~~~~~~~~~ Into the LFN test fucntion. ~~~~~~~~~~\n"); + t8_debugf ("~~~~~~~~~~ Into the LFN test function. ~~~~~~~~~~\n"); /* Collecting data of the adapted forest */ - const t8_element_t *current_element; - t8_tree_t current_tree; - t8_locidx_t forest_is_balanced = 1; - t8_element_t **neighbor_leafs; - t8_locidx_t *element_indices; + const t8_element_t *current_element; + t8_tree_t current_tree; + t8_locidx_t forest_is_balanced = 1; + t8_element_t **neighbor_leafs; + t8_locidx_t *element_indices; t8_eclass_scheme_c *neigh_scheme; - t8_eclass_t eclass; + t8_eclass_t eclass; t8_eclass_scheme_c *ts; - int *dual_faces; - int num_neighbors; - int face_id; - int local_num_trees = t8_forest_get_num_local_trees (forest_adapt); /* get the number of trees, this process knows about */ - int current_tree_num_elements; - int subelement_count = 0; - int LFN_call_count = 0; - int tree_count; - int elem_count; - int neighbor_count; - + int *dual_faces; + int num_neighbors; + int face_id; + int local_num_trees + = t8_forest_get_num_local_trees (forest_adapt); /* get the number of trees, this process knows about */ + int current_tree_num_elements; + int subelement_count = 0; + int LFN_call_count = 0; + int tree_count; + int elem_count; + int neighbor_count; for (tree_count = 0; tree_count < local_num_trees; ++tree_count) { eclass = t8_forest_get_tree_class (forest_adapt, tree_count); @@ -109,55 +109,45 @@ t8_LFN_test (t8_forest_t forest_adapt) /* get the number of elements in the current tree */ current_tree = t8_forest_get_tree (forest_adapt, tree_count); - current_tree_num_elements = - t8_forest_get_tree_element_count (current_tree); + current_tree_num_elements = t8_forest_get_tree_element_count (current_tree); for (elem_count = 0; elem_count < current_tree_num_elements; ++elem_count) { - /* determing the current element according to the given tree id and element id within the tree */ - current_element = - t8_forest_get_element_in_tree (forest_adapt, tree_count, elem_count); + /* determining the current element according to the given tree id and element id within the tree */ + current_element = t8_forest_get_element_in_tree (forest_adapt, tree_count, elem_count); if (ts->t8_element_is_subelement (current_element)) { subelement_count++; } - /* print current element */ + /* print current element */ #if T8_ENABLE_DEBUG - t8_productionf - ("\n\n________________" - "\nCurrent element: local elem index of this process: %i of %i (without ghosts)\n", - elem_count, t8_forest_get_local_num_elements (forest_adapt)); - ts->t8_element_debug_print (current_element); + t8_productionf ("\n\n________________" + "\nCurrent element: local elem index of this process: %i of %i (without ghosts)\n", + elem_count, t8_forest_get_local_num_elements (forest_adapt)); + ts->t8_element_debug_print (current_element); #endif - for (face_id = 0; face_id < ts->t8_element_num_faces (current_element); - ++face_id) { + for (face_id = 0; face_id < ts->t8_element_num_faces (current_element); ++face_id) { LFN_call_count++; - t8_forest_leaf_face_neighbors (forest_adapt, tree_count, - current_element, &neighbor_leafs, - face_id, &dual_faces, &num_neighbors, - &element_indices, &neigh_scheme, - forest_is_balanced); + t8_forest_leaf_face_neighbors (forest_adapt, tree_count, current_element, &neighbor_leafs, face_id, &dual_faces, + &num_neighbors, &element_indices, &neigh_scheme, forest_is_balanced); /* free memory if neighbors exist */ if (num_neighbors > 0) { - /* print all neighbor elements */ - for (neighbor_count = 0; neighbor_count < num_neighbors; - neighbor_count++) { + /* print all neighbor elements */ + for (neighbor_count = 0; neighbor_count < num_neighbors; neighbor_count++) { #if T8_ENABLE_DEBUG - t8_productionf ("\n_________" - "\nNeighbor: %i of %i at face %i: (dual face: %i | local index %i of %i (with ghosts) | ghost, if >= %i):\n", - neighbor_count + 1, num_neighbors, face_id, - dual_faces[neighbor_count], - element_indices[neighbor_count], - t8_forest_get_local_num_elements (forest_adapt) - + t8_forest_get_num_ghosts (forest_adapt), - t8_forest_get_local_num_elements (forest_adapt) - - 1); - ts->t8_element_debug_print (neighbor_leafs[neighbor_count]); + t8_productionf ("\n_________" + "\nNeighbor: %i of %i at face %i: (dual face: %i | local index %i of %i (with ghosts) | " + "ghost, if >= %i):\n", + neighbor_count + 1, num_neighbors, face_id, dual_faces[neighbor_count], + element_indices[neighbor_count], + t8_forest_get_local_num_elements (forest_adapt) + t8_forest_get_num_ghosts (forest_adapt), + t8_forest_get_local_num_elements (forest_adapt) - 1); + ts->t8_element_debug_print (neighbor_leafs[neighbor_count]); #endif - } + } neigh_scheme->t8_element_destroy (num_neighbors, neighbor_leafs); @@ -167,26 +157,20 @@ t8_LFN_test (t8_forest_t forest_adapt) } else { #if T8_ENABLE_DEBUG - /* no neighbor in this case */ - t8_productionf ("\n_________" - "\nNeighbor: at face %i: There is no neighbor (domain boundary).\n", - face_id); + /* no neighbor in this case */ + t8_productionf ("\n_________" + "\nNeighbor: at face %i: There is no neighbor (domain boundary).\n", + face_id); #endif } - } /* end of face loop */ - } /* end of element loop */ - } /* end of tree loop */ - - T8_ASSERT (subelement_count == - t8_forest_get_local_num_subelements (forest_adapt)); - - t8_debugf - ("~~~~~~~~~~ The LFN test function finshed successful ~~~~~~~~~~\n"); -} /* end of t8_LFN_test */ - - + } /* end of face loop */ + } /* end of element loop */ + } /* end of tree loop */ + T8_ASSERT (subelement_count == t8_forest_get_local_num_subelements (forest_adapt)); + t8_debugf ("~~~~~~~~~~ The LFN test function finished successful ~~~~~~~~~~\n"); +} /* end of t8_LFN_test */ /* Initializing, adapting balancing and transitioning a forest */ static void @@ -214,7 +198,7 @@ t8_transition_global (void) /* construct a multiple tree hex cmesh */ // cmesh = t8_cmesh_new_hypercube_pad (eclass, sc_MPI_COMM_WORLD, boundary, polygons_x, polygons_y, polygons_z, 0); - cmesh = t8_cmesh_new_hypercube(eclass, sc_MPI_COMM_WORLD, 0, 0, 0); + cmesh = t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 0, 0); /* Create a uniformly refined forest */ forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); diff --git a/src/t8_element_cxx.hxx b/src/t8_element_cxx.hxx index a559978f6a..f0da8a0612 100644 --- a/src/t8_element_cxx.hxx +++ b/src/t8_element_cxx.hxx @@ -741,82 +741,61 @@ struct t8_eclass_scheme */ /*-----------------------------------Functions for transition schemes------------------------------------------------*/ - /** Return the subelement id of the neighbor subelement of elem (possibly not subelement) at face elem_face + /** Return the subelement id of the neighbor subelement of elem (possibly not subelement) at face elem_face * that is a sibling of the subelement neigh. * \param [in] elem a given element (possibly subelement) * \param [in] neigh a random subelement (pseudoneighbor) in a transition cell from which we assume that it owns the real neighbor of elem * \param [in] elem_face a given face number of element elem * \return the subelement id of the real subelement neighbor of element elem, which is a sibling of neigh. */ - virtual int t8_element_find_neighbor_in_transition_cell (const - t8_element_t - *elem, - const - t8_element_t - *neigh, - int - elem_face) + virtual int + t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, const t8_element_t *neigh, int elem_face) = 0; - /** Return the transition type of an element + /** Return the transition type of an element * \param [in] elem A valid element * \return the transition type of elem (0 if elem is no subelement) */ - virtual int t8_element_get_transition_type (const - t8_element * elem) = 0; + virtual int + t8_element_get_transition_type (const t8_element *elem) + = 0; -/** Check whether the neighbors of an element at a specic face are siblings + /** Check whether the neighbors of an element at a specific face are siblings * \param [in] elem A valid element * \param [in] elem_face A valid face * \return true if the neighbor of elem at face elem_face is a sibling. */ - virtual int t8_element_neighbor_is_sibling (const t8_element * elem, - const int elem_face) - const = 0; - + virtual int + t8_element_neighbor_is_sibling (const t8_element *elem, const int elem_face) const + = 0; - /** Check whether the neighbors of an element at a specic face are siblings + /** Check whether the neighbors of an element at a specific face are siblings * \param [in] elem A valid element * \param [in] elem_face A valid face * \return return the number of sibling neighbors at a given face. */ - virtual int t8_element_get_num_sibling_neighbors_at_face (const - t8_element - * elem, - const int - elem_face) const = 0; + virtual int + t8_element_get_num_sibling_neighbors_at_face (const t8_element *elem, const int elem_face) const + = 0; - /** Construct all sibling neighbors of elem at face in hex scheme. */ + /** Construct all sibling neighbors of elem at face in hex scheme. */ virtual void - - - - t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t - *elem, - const int face, - const int - num_neighbors, - t8_element_t - *neighbor_at_face[], - int *neigh_face) = - 0; - - /** Construct all sibling neighbors of elem at face in quad scheme. */ + + t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t *elem, const int face, + const int num_neighbors, t8_element_t *neighbor_at_face[], + int *neigh_face) + = 0; + + /** Construct all sibling neighbors of elem at face in quad scheme. */ virtual void - - - - t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t - *elem, - const int face, - const int - num_neighbors, - t8_element_t - *neighbor_at_face[], - int *neigh_face[]) = - 0; - /** Return 1 if the eclass scheme has an implementation for subelements, which is conformal. */ - virtual int t8_element_transition_scheme_is_conformal (void) = 0; + + t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t *elem, const int face, const int num_neighbors, + t8_element_t *neighbor_at_face[], int *neigh_face[]) + = 0; + /** Return 1 if the eclass scheme has an implementation for subelements, which is conformal. */ + virtual int + t8_element_transition_scheme_is_conformal (void) + = 0; /** Return zero refine value for schemes that do not have a transition implementation. * \param [in] elem A valid element * \return Integer, used as the refine value during transition adaptation. diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index 83b891ab99..f57bfe4dd2 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -1698,23 +1698,15 @@ t8_forest_element_half_face_neighbors (t8_forest_t forest, t8_locidx_t ltreeid, } /* This function does not need a declaration and is only called by LFN_transitioned. - * When entering this function, a neighbr transition cell is found and some additional + * When entering this function, a neighbor transition cell is found and some additional * subelement-specific functions are applied to return the right subelement neighbor of leaf. */ void -t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, - t8_element_t *pseudo_neighbor, - const t8_element_t *leaf, - t8_locidx_t element_index, - int face, - t8_locidx_t lneigh_treeid, - t8_element_t **neighbor_leafs, - t8_locidx_t **pelement_indices, - int neighbor_is_ghost, - int *owners, - t8_locidx_t lghost_treeid, - t8_locidx_t ghost_element_index, - t8_eclass_scheme_c *ts, - t8_eclass_scheme_c *neigh_scheme, +t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, t8_element_t *pseudo_neighbor, + const t8_element_t *leaf, t8_locidx_t element_index, int face, + t8_locidx_t lneigh_treeid, t8_element_t **neighbor_leafs, + t8_locidx_t **pelement_indices, int neighbor_is_ghost, int *owners, + t8_locidx_t lghost_treeid, t8_locidx_t ghost_element_index, + t8_eclass_scheme_c *ts, t8_eclass_scheme_c *neigh_scheme, int *num_neighbors) { /* Consider the following situation: @@ -1735,9 +1727,9 @@ t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, * This function is neither implemented for hybrid meshes, nor for nonconformal meshes - we expect exactly one subelement neighbor. */ const t8_element_t *neighbor; - t8_locidx_t pseudo_neighbor_index; - int pseudo_neighbor_sub_id; - int leaf_neighbor_sub_id; + t8_locidx_t pseudo_neighbor_index; + int pseudo_neighbor_sub_id; + int leaf_neighbor_sub_id; T8_ASSERT (ts == neigh_scheme); T8_ASSERT (forest->is_transitioned); @@ -1745,36 +1737,28 @@ t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, T8_ASSERT (element_index < forest->global_num_elements); pseudo_neighbor_index = element_index; - pseudo_neighbor_sub_id = - neigh_scheme->t8_element_get_subelement_id (pseudo_neighbor); + pseudo_neighbor_sub_id = neigh_scheme->t8_element_get_subelement_id (pseudo_neighbor); /* Get the subelement id of the real neighbor of leaf. * This function will determine the sub_id of the real neighbor, given leaf, face and the pseudo_neighbor. * This is why ts == neigh_scheme must be true. */ //It is only valid to call this function if the face of elem is point outwards, thus face = 4. - t8_debugf("face %i\n", face); - t8_debugf("elem is subelement %i\n", ts->t8_element_is_subelement(leaf)); - t8_debugf("neigh is subelement %i\n", ts->t8_element_is_subelement(pseudo_neighbor)); + t8_debugf ("face %i\n", face); + t8_debugf ("elem is subelement %i\n", ts->t8_element_is_subelement (leaf)); + t8_debugf ("neigh is subelement %i\n", ts->t8_element_is_subelement (pseudo_neighbor)); - leaf_neighbor_sub_id = - neigh_scheme->t8_element_find_neighbor_in_transition_cell (leaf, - pseudo_neighbor, - face); + leaf_neighbor_sub_id = neigh_scheme->t8_element_find_neighbor_in_transition_cell (leaf, pseudo_neighbor, face); if (!neighbor_is_ghost) { /* adjust the index of the pseudo neighbor to equal the index of the real neighbor. * The following computation should be true for every subelement scheme and does not require * a separate t8_element function. The important - and subelement-scheme-dependent - * aspect is the computation of leaf_neighbor_sub_id above. */ - element_index = - pseudo_neighbor_index - pseudo_neighbor_sub_id + leaf_neighbor_sub_id; + element_index = pseudo_neighbor_index - pseudo_neighbor_sub_id + leaf_neighbor_sub_id; /* get the real neighbor */ - neighbor = t8_forest_get_tree_element (t8_forest_get_tree - (forest, lneigh_treeid), - element_index - - t8_forest_get_tree_element_offset - (forest, lneigh_treeid)); + neighbor = t8_forest_get_tree_element (t8_forest_get_tree (forest, lneigh_treeid), + element_index - t8_forest_get_tree_element_offset (forest, lneigh_treeid)); /* free memory */ neigh_scheme->t8_element_destroy (0, neighbor_leafs + 1); @@ -1793,30 +1777,23 @@ t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, } /* the neighbor subelement is a ghost */ - int search_direction = - (leaf_neighbor_sub_id > pseudo_neighbor_sub_id) ? 1 : -1; - int id_diff_abs = - (leaf_neighbor_sub_id - pseudo_neighbor_sub_id) * search_direction; + int search_direction = (leaf_neighbor_sub_id > pseudo_neighbor_sub_id) ? 1 : -1; + int id_diff_abs = (leaf_neighbor_sub_id - pseudo_neighbor_sub_id) * search_direction; - bool neighbor_found = false; - int subelement_count = 0; + bool neighbor_found = false; + int subelement_count = 0; while (!neighbor_found) { - T8_ASSERT (ghost_element_index >= 0); /* check, that ghost_element_index has been set before */ + T8_ASSERT (ghost_element_index >= 0); /* check, that ghost_element_index has been set before */ const t8_element_t *check_neighbor; - check_neighbor = - t8_forest_ghost_get_element (forest, lghost_treeid, - ghost_element_index + - search_direction * subelement_count); + check_neighbor + = t8_forest_ghost_get_element (forest, lghost_treeid, ghost_element_index + search_direction * subelement_count); - if (neigh_scheme->t8_element_get_subelement_id (check_neighbor) == - leaf_neighbor_sub_id) { + if (neigh_scheme->t8_element_get_subelement_id (check_neighbor) == leaf_neighbor_sub_id) { /* both elements should be siblings or equal */ T8_ASSERT (neigh_scheme->t8_element_get_transition_type (check_neighbor) - == - neigh_scheme->t8_element_get_transition_type - (pseudo_neighbor)); + == neigh_scheme->t8_element_get_transition_type (pseudo_neighbor)); /* adjust element index */ element_index = element_index + search_direction * subelement_count; @@ -1836,33 +1813,28 @@ t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, neighbor_found = true; } - if (subelement_count > id_diff_abs) { /* we assume that the real neighbor is a sibling subelement and hence we should find it here */ + if (subelement_count + > id_diff_abs) { /* we assume that the real neighbor is a sibling subelement and hence we should find it here */ SC_ABORT ("Ghost subelement neighbor not found!\n"); } subelement_count++; - } /* end while-loop to identify ghost-subelement neighbor */ + } /* end while-loop to identify ghost-subelement neighbor */ *num_neighbors = 1; return; } -/* This is the transitioned version of the LFN funciton. It does not need a declaration +/* This is the transitioned version of the LFN function. It does not need a declaration * as it is only called by LFN if the input forest is transitioned. - * Note: there is a lot of code duplication compared to LFN, but it might be better to seperate the transitioned LFN + * Note: there is a lot of code duplication compared to LFN, but it might be better to separate the transitioned LFN * from the standard LFN for now. */ void -t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, - t8_locidx_t ltreeid, - const t8_element_t *leaf, - t8_element_t **pneighbor_leafs[], - int face, int *dual_faces[], - int *num_neighbors, - t8_locidx_t **pelement_indices, - t8_eclass_scheme_c - **pneigh_scheme, - int forest_is_balanced) +t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltreeid, const t8_element_t *leaf, + t8_element_t **pneighbor_leafs[], int face, int *dual_faces[], + int *num_neighbors, t8_locidx_t **pelement_indices, + t8_eclass_scheme_c **pneigh_scheme, int forest_is_balanced) { /* Consider the following transitioned forest: * @@ -1891,19 +1863,16 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, * Later, the real neighbor elements are copied into this array and returned by the LFN function * - ancestor (neigh_scheme) is a "first guess". It is a leaf element of the forest that corresponds to the VFNs or VHFNs in neighbor_leafs[] */ - t8_eclass_t neigh_class, eclass; - t8_gloidx_t gneigh_treeid; - t8_locidx_t lneigh_treeid = -1; - t8_locidx_t lghost_treeid = - -1, *element_indices, element_index, subelement_neighbor_index, - ghost_element_index = -1; + t8_eclass_t neigh_class, eclass; + t8_gloidx_t gneigh_treeid; + t8_locidx_t lneigh_treeid = -1; + t8_locidx_t lghost_treeid = -1, *element_indices, element_index, subelement_neighbor_index, ghost_element_index = -1; t8_eclass_scheme_c *ts, *neigh_scheme; t8_element_array_t *element_array; - t8_element_t *ancestor, **neighbor_leafs; - t8_linearidx_t neigh_id; - int num_children_at_face, at_maxlevel; - int ineigh, *owners, different_owners, have_ghosts, - neighbor_is_ghost = 0; + t8_element_t *ancestor, **neighbor_leafs; + t8_linearidx_t neigh_id; + int num_children_at_face, at_maxlevel; + int ineigh, *owners, different_owners, have_ghosts, neighbor_is_ghost = 0; T8_ASSERT (t8_forest_is_committed (forest)); @@ -1920,16 +1889,14 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, /* LFN_transitioned does not yet support nonconformal transitioned meshes. * Hybrid meshes can be used if both schemes support conformal transitioning. */ - SC_CHECK_ABORT ((ts->t8_element_scheme_supports_transitioning () - && ts->t8_element_transition_scheme_is_conformal ()), - "LFN_transitioned not implemented for nonconformal transition schemes"); + SC_CHECK_ABORT ( + (ts->t8_element_scheme_supports_transitioning () && ts->t8_element_transition_scheme_is_conformal ()), + "LFN_transitioned not implemented for nonconformal transition schemes"); /* In the following, we compute the children of the face neighbor elements of leaf. For this, we need the * neighbor tree's eclass, scheme, and tree id */ - neigh_class = - t8_forest_element_neighbor_eclass (forest, ltreeid, leaf, face); - neigh_scheme = *pneigh_scheme = - t8_forest_get_eclass_scheme (forest, neigh_class); + neigh_class = t8_forest_element_neighbor_eclass (forest, ltreeid, leaf, face); + neigh_scheme = *pneigh_scheme = t8_forest_get_eclass_scheme (forest, neigh_class); /* 1) Check whether the current element is a subelement and whether its neighbor is a sibling subelement */ @@ -1940,57 +1907,41 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, if (ts->t8_element_neighbor_is_sibling (leaf, face) > 0) { /* subelement siblings will be in the same local tree */ T8_ASSERT (ts == neigh_scheme); - *num_neighbors = - ts->t8_element_get_num_sibling_neighbors_at_face (leaf, face); - neighbor_leafs = *pneighbor_leafs = - T8_ALLOC (t8_element_t *, *num_neighbors); + *num_neighbors = ts->t8_element_get_num_sibling_neighbors_at_face (leaf, face); + neighbor_leafs = *pneighbor_leafs = T8_ALLOC (t8_element_t *, *num_neighbors); *dual_faces = T8_ALLOC (int, *num_neighbors); ts->t8_element_new (*num_neighbors, neighbor_leafs); - if ( eclass == 4){ - ts->t8_element_get_sibling_neighbor_in_transition_cell_hex (leaf, face, - *num_neighbors, - neighbor_leafs, - *dual_faces); + if (eclass == 4) { + ts->t8_element_get_sibling_neighbor_in_transition_cell_hex (leaf, face, *num_neighbors, neighbor_leafs, + *dual_faces); } - if (eclass == 2) { - ts->t8_element_get_sibling_neighbor_in_transition_cell (leaf, face, - *num_neighbors, - neighbor_leafs, - dual_faces); + if (eclass == 2) { + ts->t8_element_get_sibling_neighbor_in_transition_cell (leaf, face, *num_neighbors, neighbor_leafs, + dual_faces); } - + *pelement_indices = T8_ALLOC (t8_locidx_t, *num_neighbors); element_indices = *pelement_indices; - for (int neighbor_count = 0; neighbor_count < *num_neighbors; - neighbor_count++) { - t8_debugf("num neighbors %i\n", *num_neighbors); - neigh_id = - ts->t8_element_get_linear_id (neighbor_leafs[neighbor_count], - forest->maxlevel); + for (int neighbor_count = 0; neighbor_count < *num_neighbors; neighbor_count++) { + t8_debugf ("num neighbors %i\n", *num_neighbors); + neigh_id = ts->t8_element_get_linear_id (neighbor_leafs[neighbor_count], forest->maxlevel); element_array = t8_forest_get_tree_element_array (forest, ltreeid); - subelement_neighbor_index = - t8_forest_bin_search_lower (element_array, neigh_id, - forest->maxlevel); - element_indices[neighbor_count] = - subelement_neighbor_index - - ts->t8_element_get_subelement_id (t8_forest_get_tree_element - (t8_forest_get_tree - (forest, ltreeid), - subelement_neighbor_index)) - + - ts->t8_element_get_subelement_id (neighbor_leafs[neighbor_count]); + subelement_neighbor_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); + element_indices[neighbor_count] = subelement_neighbor_index + - ts->t8_element_get_subelement_id (t8_forest_get_tree_element ( + t8_forest_get_tree (forest, ltreeid), subelement_neighbor_index)) + + ts->t8_element_get_subelement_id (neighbor_leafs[neighbor_count]); T8_ASSERT (element_indices[neighbor_count] >= 0); } return; } } - /* 2) The neighbor is no sibling subelement. Move on with the standard (half)-face-neighbor procedure */ + /* 2) The neighbor is no sibling subelement. Move on with the standard (half)-face-neighbor procedure */ /* If we are at the maximum refinement level, * then we compute the single neighbor instead. */ - at_maxlevel = - ts->t8_element_level (leaf) == t8_forest_get_maxlevel (forest); + at_maxlevel = ts->t8_element_level (leaf) == t8_forest_get_maxlevel (forest); if (at_maxlevel || ts->t8_element_transition_scheme_is_conformal ()) { /* If leaf has maxlevel or the current eclass scheme is transitioned and conformal, * we know that the leaf element has at most one neighbor at each face. @@ -2000,10 +1951,8 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, *dual_faces = T8_ALLOC (int, num_children_at_face); neigh_scheme->t8_element_new (num_children_at_face, neighbor_leafs); /* Compute virtual neighbor element and global treeid of the neighbor */ - gneigh_treeid = - t8_forest_element_face_neighbor (forest, ltreeid, leaf, - neighbor_leafs[0], neigh_scheme, - face, *dual_faces); + gneigh_treeid + = t8_forest_element_face_neighbor (forest, ltreeid, leaf, neighbor_leafs[0], neigh_scheme, face, *dual_faces); } else { /* At this point, we expect an arbitrary number of neighbors. Our transition implementation is @@ -2032,17 +1981,12 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, /* Allocate neighbor element */ num_children_at_face = ts->t8_element_num_face_children (leaf, face); - neighbor_leafs = *pneighbor_leafs = - T8_ALLOC (t8_element_t *, num_children_at_face); + neighbor_leafs = *pneighbor_leafs = T8_ALLOC (t8_element_t *, num_children_at_face); *dual_faces = T8_ALLOC (int, num_children_at_face); neigh_scheme->t8_element_new (num_children_at_face, neighbor_leafs); /* Compute virtual neighbor elements and global treeid of the neighbor */ - gneigh_treeid = - t8_forest_element_half_face_neighbors (forest, ltreeid, leaf, - neighbor_leafs, - neigh_scheme, face, - num_children_at_face, - *dual_faces); + gneigh_treeid = t8_forest_element_half_face_neighbors (forest, ltreeid, leaf, neighbor_leafs, neigh_scheme, face, + num_children_at_face, *dual_faces); } /* neighbor_leafs[i] do now equal the FN or HFN of leaf at f. In the following we check whether there is only one neighbor @@ -2059,8 +2003,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, *pneighbor_leafs = NULL; return; } - T8_ASSERT (gneigh_treeid >= 0 - && gneigh_treeid < forest->global_num_trees); + T8_ASSERT (gneigh_treeid >= 0 && gneigh_treeid < forest->global_num_trees); /* We have computed the half face neighbor elements, we now compute their owners, * if they differ, we know that the half face neighbors are the neighbor leafs. * If the owners do not differ, we have to check if the neighbor leaf is their @@ -2071,123 +2014,90 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, for (ineigh = 0; ineigh < num_children_at_face; ineigh++) { /* At first, we check whether the current rank owns the neighbor, since * this is a constant time check and it is the most common case */ - if (t8_forest_element_check_owner (forest, neighbor_leafs[ineigh], - gneigh_treeid, neigh_class, - forest->mpirank, at_maxlevel)) { + if (t8_forest_element_check_owner (forest, neighbor_leafs[ineigh], gneigh_treeid, neigh_class, forest->mpirank, + at_maxlevel)) { owners[ineigh] = forest->mpirank; /* The neighbor tree is also a local tree. we store its local treeid */ lneigh_treeid = t8_forest_get_local_id (forest, gneigh_treeid); } else { - owners[ineigh] = - t8_forest_element_find_owner (forest, gneigh_treeid, - neighbor_leafs[ineigh], neigh_class); + owners[ineigh] = t8_forest_element_find_owner (forest, gneigh_treeid, neighbor_leafs[ineigh], neigh_class); /* Store that at least one neighbor is a ghost */ have_ghosts = 1; } if (ineigh > 0) { /* Check if all owners are the same for all neighbors or not */ - different_owners = different_owners - || (owners[ineigh] != owners[ineigh - 1]); + different_owners = different_owners || (owners[ineigh] != owners[ineigh - 1]); } } if (have_ghosts) { /* At least one neighbor is a ghost, we compute the ghost treeid of the neighbor * tree. */ - lghost_treeid = - t8_forest_ghost_get_ghost_treeid (forest, gneigh_treeid); + lghost_treeid = t8_forest_ghost_get_ghost_treeid (forest, gneigh_treeid); T8_ASSERT (lghost_treeid >= 0); } if (!different_owners) { /* The face neighbors belong to the same process, we thus need to determine * if they are leafs or their parent or grandparent. */ - neigh_id = - neigh_scheme->t8_element_get_linear_id (neighbor_leafs[0], - forest->maxlevel); + neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leafs[0], forest->maxlevel); if (owners[0] != forest->mpirank) { /* The elements are ghost elements of the same owner */ neighbor_is_ghost = 1; - element_array = - t8_forest_ghost_get_tree_elements (forest, lghost_treeid); + element_array = t8_forest_ghost_get_tree_elements (forest, lghost_treeid); /* Find the index in element_array of the leaf ancestor of the first neighbor. * This is either the neighbor itself or its parent, or its grandparent */ - element_index = - t8_forest_bin_search_lower (element_array, neigh_id, - forest->maxlevel); + element_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); /* Get the element */ - ancestor = - t8_forest_ghost_get_element (forest, lghost_treeid, element_index); + ancestor = t8_forest_ghost_get_element (forest, lghost_treeid, element_index); /* Add the number of ghost elements on previous ghost trees and the number * of local elements. */ ghost_element_index = element_index; - element_index += - t8_forest_ghost_get_tree_element_offset (forest, lghost_treeid); + element_index += t8_forest_ghost_get_tree_element_offset (forest, lghost_treeid); element_index += t8_forest_get_local_num_elements (forest); T8_ASSERT (forest->local_num_elements <= element_index - && element_index < - forest->local_num_elements + - t8_forest_get_num_ghosts (forest)); + && element_index < forest->local_num_elements + t8_forest_get_num_ghosts (forest)); } else { /* the elements are local elements */ - element_array = - t8_forest_get_tree_element_array (forest, lneigh_treeid); + element_array = t8_forest_get_tree_element_array (forest, lneigh_treeid); /* Find the index in element_array of the leaf ancestor of the first neighbor. * This is either the neighbor itself or its parent, or its grandparent */ - element_index = - t8_forest_bin_search_lower (element_array, neigh_id, - forest->maxlevel); + element_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); /* Get the element */ - ancestor = - t8_forest_get_tree_element (t8_forest_get_tree - (forest, lneigh_treeid), element_index); + ancestor = t8_forest_get_tree_element (t8_forest_get_tree (forest, lneigh_treeid), element_index); /* Add the element offset of this tree to the index */ - element_index += - t8_forest_get_tree_element_offset (forest, lneigh_treeid); + element_index += t8_forest_get_tree_element_offset (forest, lneigh_treeid); } - if ((neigh_scheme->t8_element_compare (ancestor, neighbor_leafs[0]) < 0) - || ts->t8_element_is_subelement (leaf)) { + if ((neigh_scheme->t8_element_compare (ancestor, neighbor_leafs[0]) < 0) || ts->t8_element_is_subelement (leaf)) { /* we expect only one neighbor (or a neighboring transition cell with possibly multiple * subelement neighbors if the transition scheme is not conformal) in this case */ /* We need to determine the dual face */ - if (neigh_scheme->t8_element_level (ancestor) == - ts->t8_element_level (leaf)) { + if (neigh_scheme->t8_element_level (ancestor) == ts->t8_element_level (leaf)) { /* The ancestor is the same-level neighbor of leaf */ if (!at_maxlevel) { /* its dual face is the face of the parent of the first neighbor leaf */ - *dual_faces[0] = - neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], - *dual_faces[0]); + *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], *dual_faces[0]); } } - else if (neigh_scheme->t8_element_level (ancestor) == - ts->t8_element_level (leaf) + 1) { - *dual_faces[0] = - neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], - *dual_faces[0]); + else if (neigh_scheme->t8_element_level (ancestor) == ts->t8_element_level (leaf) + 1) { + *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], *dual_faces[0]); } else { /* The ancestor is the parent of the parent */ - T8_ASSERT (neigh_scheme->t8_element_level (ancestor) == - ts->t8_element_level (leaf) - 1); + T8_ASSERT (neigh_scheme->t8_element_level (ancestor) == ts->t8_element_level (leaf) - 1); - *dual_faces[0] = - neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], - *dual_faces[0]); + *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], *dual_faces[0]); if (!at_maxlevel) { /* We need to compute the dual face of the grandparent. */ /* Construct the parent of the grand child */ - neigh_scheme->t8_element_parent (neighbor_leafs[0], - neighbor_leafs[0]); + neigh_scheme->t8_element_parent (neighbor_leafs[0], neighbor_leafs[0]); /* Compute the face id of the parent's face */ - *dual_faces[0] = - neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], - *dual_faces[0]); + *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], *dual_faces[0]); } } @@ -2205,24 +2115,15 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, /* TODO: in nonconformal transitioned forests there might be more than one subelement neighbor * in a neighboring transition cell - not implemented yet */ - T8_ASSERT (neigh_scheme->t8_element_transition_scheme_is_conformal - ()); - t8_forest_get_transition_cell_face_neighbor (forest, ancestor, leaf, - element_index, face, - lneigh_treeid, - neighbor_leafs, - pelement_indices, - neighbor_is_ghost, - owners, lghost_treeid, - ghost_element_index, - ts, neigh_scheme, - num_neighbors); + T8_ASSERT (neigh_scheme->t8_element_transition_scheme_is_conformal ()); + t8_forest_get_transition_cell_face_neighbor ( + forest, ancestor, leaf, element_index, face, lneigh_treeid, neighbor_leafs, pelement_indices, + neighbor_is_ghost, owners, lghost_treeid, ghost_element_index, ts, neigh_scheme, num_neighbors); return; } /* free memory */ - neigh_scheme->t8_element_destroy (num_children_at_face - 1, - neighbor_leafs + 1); + neigh_scheme->t8_element_destroy (num_children_at_face - 1, neighbor_leafs + 1); /* copy the ancestor */ neigh_scheme->t8_element_copy (ancestor, neighbor_leafs[0]); /* set return values */ @@ -2232,8 +2133,8 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, T8_FREE (owners); return; - } /* end of (t8_element_compare < 0) || leaf is subelement */ - } /* end of if !different owner */ + } /* end of (t8_element_compare < 0) || leaf is subelement */ + } /* end of if !different owner */ /* neighbor_leafs[i] are not adjusted below this comment. * Hence, we assume that the FNs or HFNs equal the real leaf neighbor elements. */ @@ -2249,79 +2150,60 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, element_indices = *pelement_indices; for (ineigh = 0; ineigh < num_children_at_face; ineigh++) { /* Compute the linear id at maxlevel of the neighbor leaf */ - neigh_id = - neigh_scheme->t8_element_get_linear_id (neighbor_leafs[ineigh], - forest->maxlevel); + neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leafs[ineigh], forest->maxlevel); /* Get a pointer to the element array in which the neighbor lies and search * for the element's index in this array. * This is either the local leaf array of the local tree or the corresponding leaf array * in the ghost structure */ if (owners[ineigh] == forest->mpirank) { /* The neighbor is a local leaf */ - element_array = - t8_forest_get_tree_element_array (forest, lneigh_treeid); + element_array = t8_forest_get_tree_element_array (forest, lneigh_treeid); /* Find the index of the neighbor in the array */ - element_indices[ineigh] = - t8_forest_bin_search_lower (element_array, neigh_id, - forest->maxlevel); + element_indices[ineigh] = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); T8_ASSERT (element_indices[ineigh] >= 0); /* We have to add the tree's element offset to the index found to get * the actual local element id */ - element_indices[ineigh] += - t8_forest_get_tree_element_offset (forest, lneigh_treeid); + element_indices[ineigh] += t8_forest_get_tree_element_offset (forest, lneigh_treeid); #if T8_ENABLE_DEBUG /* We check whether the element is really the element at this local id */ { - t8_locidx_t check_ltreeid; - t8_element_t *check_element; - check_element = - t8_forest_get_element (forest, element_indices[ineigh], - &check_ltreeid); + t8_locidx_t check_ltreeid; + t8_element_t *check_element; + check_element = t8_forest_get_element (forest, element_indices[ineigh], &check_ltreeid); T8_ASSERT (check_ltreeid == lneigh_treeid); - T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, - neighbor_leafs - [ineigh])); + T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, neighbor_leafs[ineigh])); } #endif } else { /* The neighbor is a ghost */ - element_array = - t8_forest_ghost_get_tree_elements (forest, lghost_treeid); + element_array = t8_forest_ghost_get_tree_elements (forest, lghost_treeid); /* Find the index of the neighbor in the array */ - element_indices[ineigh] = - t8_forest_bin_search_lower (element_array, neigh_id, - forest->maxlevel); + element_indices[ineigh] = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); #if T8_ENABLE_DEBUG /* We check whether the element is really the element at this local id */ { - t8_element_t *check_element; - check_element = - t8_forest_ghost_get_element (forest, lghost_treeid, - element_indices[ineigh]); - T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, - neighbor_leafs - [ineigh])); + t8_element_t *check_element; + check_element = t8_forest_ghost_get_element (forest, lghost_treeid, element_indices[ineigh]); + T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, neighbor_leafs[ineigh])); t8_debugf ("LFN_transitioned: the neighbor is a ghost.\n"); } #endif /* Add the element offset of previous ghosts to this index */ - element_indices[ineigh] += - t8_forest_ghost_get_tree_element_offset (forest, lghost_treeid); + element_indices[ineigh] += t8_forest_ghost_get_tree_element_offset (forest, lghost_treeid); /* Add the number of all local elements to this index */ element_indices[ineigh] += t8_forest_get_local_num_elements (forest); } - } /* End for loop over neighbor leafs */ + } /* End for loop over neighbor leafs */ T8_FREE (owners); - } /* end of if (forest_is_balanced || forest->is_transitioned) (main part of the LFN) */ + } /* end of if (forest_is_balanced || forest->is_transitioned) (main part of the LFN) */ else { /* TODO: implement unbalanced version */ SC_ABORT_NOT_REACHED (); } } - int t8_forest_leaf_face_orientation (t8_forest_t forest, const t8_locidx_t ltreeid, const t8_eclass_scheme_c *ts, const t8_element_t *leaf, int face) @@ -2366,15 +2248,10 @@ t8_forest_leaf_face_neighbors_ext (t8_forest_t forest, t8_locidx_t ltreeid, cons "but was not found in forest.\n"); /* if the given forest is transitioned, then call the transitioned LFN function. */ if (forest->is_transitioned) { - t8_forest_leaf_face_neighbors_transitioned (forest, ltreeid, - leaf, pneighbor_leaves, - face, dual_faces, - num_neighbors, - pelement_indices, - pneigh_scheme, - forest_is_balanced); + t8_forest_leaf_face_neighbors_transitioned (forest, ltreeid, leaf, pneighbor_leaves, face, dual_faces, + num_neighbors, pelement_indices, pneigh_scheme, forest_is_balanced); return; - } + } if (forest_is_balanced) { /* In a balanced forest, the leaf neighbor of a leaf is either the neighbor element itself, diff --git a/src/t8_forest/t8_forest_general.h b/src/t8_forest/t8_forest_general.h index f1bf0749e0..d1f0d5c01c 100644 --- a/src/t8_forest/t8_forest_general.h +++ b/src/t8_forest/t8_forest_general.h @@ -399,7 +399,8 @@ t8_forest_get_global_num_subelements (t8_forest_t forest); * \return The number of subelements on this process in \a forest. * \a forest must be committed before calling this function. */ -t8_locidx_t t8_forest_get_local_num_subelements (t8_forest_t forest); +t8_locidx_t +t8_forest_get_local_num_subelements (t8_forest_t forest); /** Set a source forest to use subelements during commit, that will remove hanging faces from the adapted mesh. * \param [in, out] forest The forest. diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx index 12e6f1c7d1..3850e638ac 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx @@ -170,60 +170,44 @@ t8_default_scheme_common_c::t8_element_deinit (int length, t8_element_t *elem) c /*----------------------------Functions for transition schemes--------------------------------------------*/ int -t8_default_scheme_common_c::t8_element_find_neighbor_in_transition_cell (const - t8_element_t - *elem, - const - t8_element_t - *neigh, - int - elem_face) +t8_default_scheme_common_c::t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, + const t8_element_t *neigh, int elem_face) { SC_ABORT ("This function is not implemented for the given scheme.\n"); } int -t8_default_scheme_common_c::t8_element_get_transition_type (const - t8_element * elem) +t8_default_scheme_common_c::t8_element_get_transition_type (const t8_element *elem) { SC_ABORT ("This function is not implemented for the given scheme.\n"); } int -t8_default_scheme_common_c::t8_element_neighbor_is_sibling (const t8_element * - elem, - const int face) const +t8_default_scheme_common_c::t8_element_neighbor_is_sibling (const t8_element *elem, const int face) const { /* No subelements are implemented and therefore we return false, * meaning "the neighbor at face is not a sibling of elem". */ - t8_debugf - ("This is the default_common implementation of t8_element_neighbor_is_sibling.\n"); + t8_debugf ("This is the default_common implementation of t8_element_neighbor_is_sibling.\n"); return 0; } int -t8_default_scheme_common_c::t8_element_get_num_sibling_neighbors_at_face (const t8_element * elem, - const int face) const - +t8_default_scheme_common_c::t8_element_get_num_sibling_neighbors_at_face (const t8_element *elem, const int face) const + { /* No subelements are implemented and therefore we return false meaning "the neighbor at face is not a sibling of elem". */ - t8_debugf - ("This is the default_common implementation of t8_element_get_num_sibling_neighbors_at_face.\n"); + t8_debugf ("This is the default_common implementation of t8_element_get_num_sibling_neighbors_at_face.\n"); return 0; } void -t8_default_scheme_common_c::t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t *elem, - const int face, - const int num_neighbors, - t8_element_t *neighbor_at_face[], - int *neigh_face) +t8_default_scheme_common_c::t8_element_get_sibling_neighbor_in_transition_cell_hex ( + const t8_element_t *elem, const int face, const int num_neighbors, t8_element_t *neighbor_at_face[], int *neigh_face) { SC_ABORT ("This function is not implemented for the given scheme.\n"); } void t8_default_scheme_common_c::t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t *elem, - const int face, - const int num_neighbors, + const int face, const int num_neighbors, t8_element_t *neighbor_at_face[], int *neigh_face[]) { diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx index 4b639296ac..fff51a9af0 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx @@ -128,78 +128,53 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { t8_element_anchor (const t8_element_t *elem, int anchor[3]) const = 0; /*-----------------------------Functions for transition schemes---------------------------------*/ - /** Return the subelement id of the neighbor subelement of elem at face elem_face + /** Return the subelement id of the neighbor subelement of elem at face elem_face * that is a sibling of the subelement neigh. * \param [in] elem a given element (possibly subelement) * \param [in] neigh a random subelement (pseudoneighbor) in a transition cell from which we assume that it owns the real neighbor of elem * \param [in] elem_face a given face number of element elem * \return the subelement id of the real subelement neighbor of element elem, which is a sibling of neigh. */ - virtual int t8_element_find_neighbor_in_transition_cell (const - t8_element_t - *elem, - const - t8_element_t - *neigh, - int - elem_face); + virtual int + t8_element_find_neighbor_in_transition_cell (const t8_element_t *elem, const t8_element_t *neigh, int elem_face); /** Return the transition type of an element * \param [in] elem A valid element * \return the transition type of elem (0 if elem is no subelement) */ - virtual int t8_element_get_transition_type (const - t8_element * elem); - /** Check whether the neighbors of an element at a specic face are siblings + virtual int + t8_element_get_transition_type (const t8_element *elem); + /** Check whether the neighbors of an element at a specific face are siblings * \param [in] elem A valid element * \param [in] elem_face A valid face * \return true if the neighbor of elem at face elem_face is a sibling. */ - virtual int t8_element_neighbor_is_sibling (const t8_element * elem, - const int elem_face) - const; + virtual int + t8_element_neighbor_is_sibling (const t8_element *elem, const int elem_face) const; - - /** Check whether the neighbors of an element at a specic face are siblings + /** Check whether the neighbors of an element at a specific face are siblings * \param [in] elem A valid element * \param [in] elem_face A valid face * \return return the number of sibling neighbors at a given face. */ - virtual int t8_element_get_num_sibling_neighbors_at_face (const - t8_element - * elem, - const int - elem_face) const; - /** Construct all sibling neighbors of elem at face in hex scheme. */ + virtual int + t8_element_get_num_sibling_neighbors_at_face (const t8_element *elem, const int elem_face) const; + /** Construct all sibling neighbors of elem at face in hex scheme. */ virtual void - - - - t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t - *elem, - const int face, - const int - num_neighbors, - t8_element_t - *neighbor_at_face[], - int *neigh_face); - - /** Construct all sibling neighbors of elem at face in quad scheme */ + + t8_element_get_sibling_neighbor_in_transition_cell_hex (const t8_element_t *elem, const int face, + const int num_neighbors, t8_element_t *neighbor_at_face[], + int *neigh_face); + + /** Construct all sibling neighbors of elem at face in quad scheme */ virtual void - - - - t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t - *elem, - const int face, - const int - num_neighbors, - t8_element_t - *neighbor_at_face[], - int *neigh_face[]); - - /** Return 1 if the eclass scheme has an implementation for subelements, which is conformal. */ - virtual int t8_element_transition_scheme_is_conformal (void); + + t8_element_get_sibling_neighbor_in_transition_cell (const t8_element_t *elem, const int face, const int num_neighbors, + t8_element_t *neighbor_at_face[], int *neigh_face[]); + + /** Return 1 if the eclass scheme has an implementation for subelements, which is conformal. */ + virtual int + t8_element_transition_scheme_is_conformal (void); /** Return zero refine value for schemes that do not have a transition implementation. * \param [in] elem A valid element diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 971a963056..daa738414e 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -458,7 +458,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h * element ID). If the transition type is = 1 at the hex_face, it's split.*/ //-----------------------------CASE 1-------------------------------------------------------- - t8_debugf("CASE 1\n"); + t8_debugf ("CASE 1\n"); //make rightshift until only the bits for the faces before our neighbors face are left. transition_type_tmp = transition_type >> (5 - neigh_hex_face); @@ -486,7 +486,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h } //-------------------------CASE 2-------------------------------------- else { //neighbor is split. We have to return 2 subelements. - t8_debugf("CASE 2\n"); + t8_debugf ("CASE 2\n"); amount_subelements = 0; int subelement_id_tmp2 = 0; // In here we store the second subelement ID in case 2 if elem has two neighbors @@ -559,8 +559,8 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h //-------------------------CASE 3-------------------------------------- else { - t8_debugf("CASE 3\n"); - t8_debugf("location[0] = %i\n", location[0]); + t8_debugf ("CASE 3\n"); + t8_debugf ("location[0] = %i\n", location[0]); //The own face is split //get hex_face_number of the face_neighbored subelement @@ -570,24 +570,20 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h if (location[0] == 0 || location[0] == 1) { if (((location[2] & 2) == 0) && (face == 1)) { //front hlp += 1; - t8_debugf("hlp front %i\n", hlp); - + t8_debugf ("hlp front %i\n", hlp); } if (((location[2] & 2) != 0) && (face == 0)) { //back hlp += 1; - t8_debugf("hlp back %i\n", hlp); - + t8_debugf ("hlp back %i\n", hlp); } if (((location[2] & 1) == 0) && (face == 3)) { //bottom hlp += 1; - t8_debugf("hlp bottom %i\n", hlp); - + t8_debugf ("hlp bottom %i\n", hlp); } if (((location[2] & 1) != 0) && (face == 2)) { //up hlp += 1; - t8_debugf("hlp up %i\n", hlp); - + t8_debugf ("hlp up %i\n", hlp); } } //hex face 2 and 3 @@ -611,24 +607,20 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h if (location[0] == 4 || location[0] == 5) { if (((location[2] & 4) == 0) && (face == 1)) { //left hlp += 1; - t8_debugf("hlp left %i\n", hlp); - + t8_debugf ("hlp left %i\n", hlp); } if (((location[2] & 4) != 0) && (face == 0)) { //right hlp += 1; - t8_debugf("hlp right %i\n", hlp); - + t8_debugf ("hlp right %i\n", hlp); } if (((location[2] & 2) == 0) && (face == 3)) { //front hlp += 1; - t8_debugf("hlp front %i\n", hlp); - + t8_debugf ("hlp front %i\n", hlp); } if (((location[2] & 2) != 0) && (face == 2)) { //back hlp += 1; - t8_debugf("hlp back %i\n", hlp); - + t8_debugf ("hlp back %i\n", hlp); } } //if none of these conditions is true, we are in case 3 @@ -662,7 +654,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h //---------------------------CASE 4-------------------------------------- else { - t8_debugf("CASE 4\n"); + t8_debugf ("CASE 4\n"); //It's possible, that the neighbored subelement has the same face_hex number as the element itself // amount_subelements = 0; @@ -703,19 +695,18 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h if (location[0] == 2 || location[0] == 3) { // hex_face = 2/3 if ((location[2] & 4) == 0) { //left - if (face == 1) { // then it's the next element + if (face == 1) { // then it's the next element subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; hlp += 1; } else { //right - if (face == 0) { //then it's the element before. - subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; - hlp += 1; + if (face == 0) { //then it's the element before. + subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; + hlp += 1; + } } } - - } - + if ((location[2] & 1) != 0) { //up if (face == 2) { //then it's the element below subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 2; @@ -731,15 +722,15 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h } if (location[0] == 4 || location[0] == 5) { // hex_face = 4/5 - - if ((location[2] & 4) != 0) { //right - if (face == 0) { //then it's the element before. + + if ((location[2] & 4) != 0) { //right + if (face == 0) { //then it's the element before. subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id - 1; hlp += 1; } } - else{ - if (face == 3){ + else { + if (face == 1) { subelement_id_tmp = phex_w_sub_neighbor_at_face->subelement_id + 1; hlp += 1; } @@ -907,7 +898,7 @@ t8_subelement_scheme_hex_c::t8_element_get_sibling_neighbor_in_transition_cell_h } } phex_w_sub_neighbor_at_face->subelement_id = subelement_id_tmp; - t8_debugf("subelement ID nach neighbor function %i\n", subelement_id_tmp); + t8_debugf ("subelement ID nach neighbor function %i\n", subelement_id_tmp); } void @@ -2576,8 +2567,8 @@ t8_subelement_scheme_hex_c::t8_element_find_neighbor_in_transition_cell (const t //Case 2: The element is a subelement and we are looking for a face neighbor at face 4. if (t8_element_is_subelement (elem)) { - int location_elem[3] = {}; /* {face, is_split, number of subelement at face} */ - t8_element_get_location_of_subelement (elem, location_elem); + int location_elem[3] = {}; /* {face, is_split, number of subelement at face} */ + t8_element_get_location_of_subelement (elem, location_elem); /* In this case, we have the following examplary situation in the 2D quad case: * * x - - - - - - - x - - - - - - - x @@ -2858,7 +2849,6 @@ t8_subelement_scheme_hex_c::t8_element_transition_scheme_is_conformal (void) return T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL; } - #ifdef T8_ENABLE_DEBUG /* *INDENT-OFF* */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index df65cad34e..58145fcd28 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -341,9 +341,10 @@ struct t8_subelement_scheme_hex_c: public t8_default_scheme_common_c virtual void t8_element_last_descendant_face (const t8_element_t *elem, int face, t8_element_t *last_desc, int level) const; -/** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ - virtual int t8_element_transition_scheme_is_conformal (void); - + /** Return 1 if the eclass scheme has an implementation for subelements. Return 0 otherwise. */ + virtual int + t8_element_transition_scheme_is_conformal (void); + /** Construct the boundary element at a specific face. */ virtual void t8_element_boundary_face (const t8_element_t *elem, int face, t8_element_t *boundary, From 89c3d698589f8e1725737276474434f7702523b1 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Thu, 13 Jun 2024 13:25:54 +0200 Subject: [PATCH 33/55] corrected typo leafs->leaves --- src/t8_forest/t8_forest_cxx.cxx | 100 ++++++++++++++++---------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index f57bfe4dd2..71902c52d0 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -1703,7 +1703,7 @@ t8_forest_element_half_face_neighbors (t8_forest_t forest, t8_locidx_t ltreeid, void t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, t8_element_t *pseudo_neighbor, const t8_element_t *leaf, t8_locidx_t element_index, int face, - t8_locidx_t lneigh_treeid, t8_element_t **neighbor_leafs, + t8_locidx_t lneigh_treeid, t8_element_t **neighbor_leaves, t8_locidx_t **pelement_indices, int neighbor_is_ghost, int *owners, t8_locidx_t lghost_treeid, t8_locidx_t ghost_element_index, t8_eclass_scheme_c *ts, t8_eclass_scheme_c *neigh_scheme, @@ -1761,9 +1761,9 @@ t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, t8_element_t *p element_index - t8_forest_get_tree_element_offset (forest, lneigh_treeid)); /* free memory */ - neigh_scheme->t8_element_destroy (0, neighbor_leafs + 1); + neigh_scheme->t8_element_destroy (0, neighbor_leaves + 1); /* copy the neighbor */ - neigh_scheme->t8_element_copy (neighbor, neighbor_leafs[0]); + neigh_scheme->t8_element_copy (neighbor, neighbor_leaves[0]); /* set return values */ *pelement_indices = T8_ALLOC (t8_locidx_t, 1); @@ -1799,9 +1799,9 @@ t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, t8_element_t *p element_index = element_index + search_direction * subelement_count; /* free memory */ - neigh_scheme->t8_element_destroy (0, neighbor_leafs + 1); + neigh_scheme->t8_element_destroy (0, neighbor_leaves + 1); /* copy the neighbor */ - neigh_scheme->t8_element_copy (check_neighbor, neighbor_leafs[0]); + neigh_scheme->t8_element_copy (check_neighbor, neighbor_leaves[0]); /* set return values */ *pelement_indices = T8_ALLOC (t8_locidx_t, 1); @@ -1832,7 +1832,7 @@ t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, t8_element_t *p * from the standard LFN for now. */ void t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltreeid, const t8_element_t *leaf, - t8_element_t **pneighbor_leafs[], int face, int *dual_faces[], + t8_element_t **pneighbor_leaves[], int face, int *dual_faces[], int *num_neighbors, t8_locidx_t **pelement_indices, t8_eclass_scheme_c **pneigh_scheme, int forest_is_balanced) { @@ -1859,9 +1859,9 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre /* In the following, * - leaf (ts scheme) is the current element of the forest - * - neighbor_leafs[] (neigh_scheme) is an array of neighbors of leaf. At first, it consists of VFNs or VHFNs (virtual (half) face neighbors)of leaf at f + * - neighbor_leaves[] (neigh_scheme) is an array of neighbors of leaf. At first, it consists of VFNs or VHFNs (virtual (half) face neighbors)of leaf at f * Later, the real neighbor elements are copied into this array and returned by the LFN function - * - ancestor (neigh_scheme) is a "first guess". It is a leaf element of the forest that corresponds to the VFNs or VHFNs in neighbor_leafs[] */ + * - ancestor (neigh_scheme) is a "first guess". It is a leaf element of the forest that corresponds to the VFNs or VHFNs in neighbor_leaves[] */ t8_eclass_t neigh_class, eclass; t8_gloidx_t gneigh_treeid; @@ -1869,7 +1869,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre t8_locidx_t lghost_treeid = -1, *element_indices, element_index, subelement_neighbor_index, ghost_element_index = -1; t8_eclass_scheme_c *ts, *neigh_scheme; t8_element_array_t *element_array; - t8_element_t *ancestor, **neighbor_leafs; + t8_element_t *ancestor, **neighbor_leaves; t8_linearidx_t neigh_id; int num_children_at_face, at_maxlevel; int ineigh, *owners, different_owners, have_ghosts, neighbor_is_ghost = 0; @@ -1908,15 +1908,15 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre /* subelement siblings will be in the same local tree */ T8_ASSERT (ts == neigh_scheme); *num_neighbors = ts->t8_element_get_num_sibling_neighbors_at_face (leaf, face); - neighbor_leafs = *pneighbor_leafs = T8_ALLOC (t8_element_t *, *num_neighbors); + neighbor_leaves = *pneighbor_leaves = T8_ALLOC (t8_element_t *, *num_neighbors); *dual_faces = T8_ALLOC (int, *num_neighbors); - ts->t8_element_new (*num_neighbors, neighbor_leafs); + ts->t8_element_new (*num_neighbors, neighbor_leaves); if (eclass == 4) { - ts->t8_element_get_sibling_neighbor_in_transition_cell_hex (leaf, face, *num_neighbors, neighbor_leafs, + ts->t8_element_get_sibling_neighbor_in_transition_cell_hex (leaf, face, *num_neighbors, neighbor_leaves, *dual_faces); } if (eclass == 2) { - ts->t8_element_get_sibling_neighbor_in_transition_cell (leaf, face, *num_neighbors, neighbor_leafs, + ts->t8_element_get_sibling_neighbor_in_transition_cell (leaf, face, *num_neighbors, neighbor_leaves, dual_faces); } @@ -1924,13 +1924,13 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre element_indices = *pelement_indices; for (int neighbor_count = 0; neighbor_count < *num_neighbors; neighbor_count++) { t8_debugf ("num neighbors %i\n", *num_neighbors); - neigh_id = ts->t8_element_get_linear_id (neighbor_leafs[neighbor_count], forest->maxlevel); + neigh_id = ts->t8_element_get_linear_id (neighbor_leaves[neighbor_count], forest->maxlevel); element_array = t8_forest_get_tree_element_array (forest, ltreeid); subelement_neighbor_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); element_indices[neighbor_count] = subelement_neighbor_index - ts->t8_element_get_subelement_id (t8_forest_get_tree_element ( t8_forest_get_tree (forest, ltreeid), subelement_neighbor_index)) - + ts->t8_element_get_subelement_id (neighbor_leafs[neighbor_count]); + + ts->t8_element_get_subelement_id (neighbor_leaves[neighbor_count]); T8_ASSERT (element_indices[neighbor_count] >= 0); } return; @@ -1947,12 +1947,12 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre * we know that the leaf element has at most one neighbor at each face. * Note that in hybrid meshes, the mesh must not be conformal since not each tree might be conformal */ num_children_at_face = 1; - neighbor_leafs = *pneighbor_leafs = T8_ALLOC (t8_element_t *, num_children_at_face); + neighbor_leaves = *pneighbor_leaves = T8_ALLOC (t8_element_t *, num_children_at_face); *dual_faces = T8_ALLOC (int, num_children_at_face); - neigh_scheme->t8_element_new (num_children_at_face, neighbor_leafs); + neigh_scheme->t8_element_new (num_children_at_face, neighbor_leaves); /* Compute virtual neighbor element and global treeid of the neighbor */ gneigh_treeid - = t8_forest_element_face_neighbor (forest, ltreeid, leaf, neighbor_leafs[0], neigh_scheme, face, *dual_faces); + = t8_forest_element_face_neighbor (forest, ltreeid, leaf, neighbor_leaves[0], neigh_scheme, face, *dual_faces); } else { /* At this point, we expect an arbitrary number of neighbors. Our transition implementation is @@ -1981,31 +1981,31 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre /* Allocate neighbor element */ num_children_at_face = ts->t8_element_num_face_children (leaf, face); - neighbor_leafs = *pneighbor_leafs = T8_ALLOC (t8_element_t *, num_children_at_face); + neighbor_leaves = *pneighbor_leaves = T8_ALLOC (t8_element_t *, num_children_at_face); *dual_faces = T8_ALLOC (int, num_children_at_face); - neigh_scheme->t8_element_new (num_children_at_face, neighbor_leafs); + neigh_scheme->t8_element_new (num_children_at_face, neighbor_leaves); /* Compute virtual neighbor elements and global treeid of the neighbor */ - gneigh_treeid = t8_forest_element_half_face_neighbors (forest, ltreeid, leaf, neighbor_leafs, neigh_scheme, face, + gneigh_treeid = t8_forest_element_half_face_neighbors (forest, ltreeid, leaf, neighbor_leaves, neigh_scheme, face, num_children_at_face, *dual_faces); } - /* neighbor_leafs[i] do now equal the FN or HFN of leaf at f. In the following we check whether there is only one neighbor - * and whether neighbor_leafs[i] have to be adjusted further. Finally, the neighbor_leafs element array is returned by the LFN function. */ + /* neighbor_leaves[i] do now equal the FN or HFN of leaf at f. In the following we check whether there is only one neighbor + * and whether neighbor_leaves[i] have to be adjusted further. Finally, the neighbor_leaves element array is returned by the LFN function. */ if (gneigh_treeid < 0) { /* There exists no face neighbor across this face, we return with this info */ - neigh_scheme->t8_element_destroy (1, neighbor_leafs); - T8_FREE (neighbor_leafs); + neigh_scheme->t8_element_destroy (1, neighbor_leaves); + T8_FREE (neighbor_leaves); T8_FREE (*dual_faces); *dual_faces = NULL; *num_neighbors = 0; *pelement_indices = NULL; - *pneighbor_leafs = NULL; + *pneighbor_leaves = NULL; return; } T8_ASSERT (gneigh_treeid >= 0 && gneigh_treeid < forest->global_num_trees); /* We have computed the half face neighbor elements, we now compute their owners, - * if they differ, we know that the half face neighbors are the neighbor leafs. + * if they differ, we know that the half face neighbors are the neighbor leaves. * If the owners do not differ, we have to check if the neighbor leaf is their * parent or grandparent. */ owners = T8_ALLOC (int, num_children_at_face); @@ -2014,14 +2014,14 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre for (ineigh = 0; ineigh < num_children_at_face; ineigh++) { /* At first, we check whether the current rank owns the neighbor, since * this is a constant time check and it is the most common case */ - if (t8_forest_element_check_owner (forest, neighbor_leafs[ineigh], gneigh_treeid, neigh_class, forest->mpirank, + if (t8_forest_element_check_owner (forest, neighbor_leaves[ineigh], gneigh_treeid, neigh_class, forest->mpirank, at_maxlevel)) { owners[ineigh] = forest->mpirank; /* The neighbor tree is also a local tree. we store its local treeid */ lneigh_treeid = t8_forest_get_local_id (forest, gneigh_treeid); } else { - owners[ineigh] = t8_forest_element_find_owner (forest, gneigh_treeid, neighbor_leafs[ineigh], neigh_class); + owners[ineigh] = t8_forest_element_find_owner (forest, gneigh_treeid, neighbor_leaves[ineigh], neigh_class); /* Store that at least one neighbor is a ghost */ have_ghosts = 1; } @@ -2039,8 +2039,8 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre if (!different_owners) { /* The face neighbors belong to the same process, we thus need to determine - * if they are leafs or their parent or grandparent. */ - neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leafs[0], forest->maxlevel); + * if they are leaves or their parent or grandparent. */ + neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leaves[0], forest->maxlevel); if (owners[0] != forest->mpirank) { /* The elements are ghost elements of the same owner */ neighbor_is_ghost = 1; @@ -2070,7 +2070,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre element_index += t8_forest_get_tree_element_offset (forest, lneigh_treeid); } - if ((neigh_scheme->t8_element_compare (ancestor, neighbor_leafs[0]) < 0) || ts->t8_element_is_subelement (leaf)) { + if ((neigh_scheme->t8_element_compare (ancestor, neighbor_leaves[0]) < 0) || ts->t8_element_is_subelement (leaf)) { /* we expect only one neighbor (or a neighboring transition cell with possibly multiple * subelement neighbors if the transition scheme is not conformal) in this case */ @@ -2080,24 +2080,24 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre /* The ancestor is the same-level neighbor of leaf */ if (!at_maxlevel) { /* its dual face is the face of the parent of the first neighbor leaf */ - *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], *dual_faces[0]); + *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leaves[0], *dual_faces[0]); } } else if (neigh_scheme->t8_element_level (ancestor) == ts->t8_element_level (leaf) + 1) { - *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], *dual_faces[0]); + *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leaves[0], *dual_faces[0]); } else { /* The ancestor is the parent of the parent */ T8_ASSERT (neigh_scheme->t8_element_level (ancestor) == ts->t8_element_level (leaf) - 1); - *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], *dual_faces[0]); + *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leaves[0], *dual_faces[0]); if (!at_maxlevel) { /* We need to compute the dual face of the grandparent. */ /* Construct the parent of the grand child */ - neigh_scheme->t8_element_parent (neighbor_leafs[0], neighbor_leafs[0]); + neigh_scheme->t8_element_parent (neighbor_leaves[0], neighbor_leaves[0]); /* Compute the face id of the parent's face */ - *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leafs[0], *dual_faces[0]); + *dual_faces[0] = neigh_scheme->t8_element_face_parent_face (neighbor_leaves[0], *dual_faces[0]); } } @@ -2105,7 +2105,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre * in a transition cell. If yes, then apply subelement-specific functions. * Otherwise, continue with the standard LFN procedure. */ - /* TODO: nonconformal meshes will need a loop over all ancestors, corresponding to all neighbor_leafs[i]. + /* TODO: nonconformal meshes will need a loop over all ancestors, corresponding to all neighbor_leaves[i]. * And for each ancestor we would need to check whether it is a subelement and then determine all subelement neighbors * which might be more than one. */ @@ -2117,15 +2117,15 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre * in a neighboring transition cell - not implemented yet */ T8_ASSERT (neigh_scheme->t8_element_transition_scheme_is_conformal ()); t8_forest_get_transition_cell_face_neighbor ( - forest, ancestor, leaf, element_index, face, lneigh_treeid, neighbor_leafs, pelement_indices, + forest, ancestor, leaf, element_index, face, lneigh_treeid, neighbor_leaves, pelement_indices, neighbor_is_ghost, owners, lghost_treeid, ghost_element_index, ts, neigh_scheme, num_neighbors); return; } /* free memory */ - neigh_scheme->t8_element_destroy (num_children_at_face - 1, neighbor_leafs + 1); + neigh_scheme->t8_element_destroy (num_children_at_face - 1, neighbor_leaves + 1); /* copy the ancestor */ - neigh_scheme->t8_element_copy (ancestor, neighbor_leafs[0]); + neigh_scheme->t8_element_copy (ancestor, neighbor_leaves[0]); /* set return values */ *num_neighbors = 1; *pelement_indices = T8_ALLOC (t8_locidx_t, 1); @@ -2136,21 +2136,21 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre } /* end of (t8_element_compare < 0) || leaf is subelement */ } /* end of if !different owner */ - /* neighbor_leafs[i] are not adjusted below this comment. + /* neighbor_leaves[i] are not adjusted below this comment. * Hence, we assume that the FNs or HFNs equal the real leaf neighbor elements. */ - /* The leafs are the face neighbors that we are looking for. */ - /* The face neighbors either belong to different processes and thus must be leafs + /* The leaves are the face neighbors that we are looking for. */ + /* The face neighbors either belong to different processes and thus must be leaves * in the forest, or the ancestor leaf of the first half neighbor is the half - * neighbor itself and thus all half neighbors must be leafs. - * Since the forest is balanced, we found all neighbor leafs. + * neighbor itself and thus all half neighbors must be leaves. + * Since the forest is balanced, we found all neighbor leaves. * It remains to compute their local ids */ *num_neighbors = num_children_at_face; *pelement_indices = T8_ALLOC (t8_locidx_t, num_children_at_face); element_indices = *pelement_indices; for (ineigh = 0; ineigh < num_children_at_face; ineigh++) { /* Compute the linear id at maxlevel of the neighbor leaf */ - neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leafs[ineigh], forest->maxlevel); + neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leaves[ineigh], forest->maxlevel); /* Get a pointer to the element array in which the neighbor lies and search * for the element's index in this array. * This is either the local leaf array of the local tree or the corresponding leaf array @@ -2171,7 +2171,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre t8_element_t *check_element; check_element = t8_forest_get_element (forest, element_indices[ineigh], &check_ltreeid); T8_ASSERT (check_ltreeid == lneigh_treeid); - T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, neighbor_leafs[ineigh])); + T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, neighbor_leaves[ineigh])); } #endif } @@ -2186,7 +2186,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre { t8_element_t *check_element; check_element = t8_forest_ghost_get_element (forest, lghost_treeid, element_indices[ineigh]); - T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, neighbor_leafs[ineigh])); + T8_ASSERT (!neigh_scheme->t8_element_compare (check_element, neighbor_leaves[ineigh])); t8_debugf ("LFN_transitioned: the neighbor is a ghost.\n"); } #endif @@ -2195,7 +2195,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre /* Add the number of all local elements to this index */ element_indices[ineigh] += t8_forest_get_local_num_elements (forest); } - } /* End for loop over neighbor leafs */ + } /* End for loop over neighbor leaves */ T8_FREE (owners); } /* end of if (forest_is_balanced || forest->is_transitioned) (main part of the LFN) */ else { From 4331133b5695d279f07d73679b844f2fe27d51a1 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Thu, 13 Jun 2024 13:26:15 +0200 Subject: [PATCH 34/55] clang-format --- src/t8_forest/t8_forest_cxx.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index 71902c52d0..fa1cd14d02 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -2070,7 +2070,8 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre element_index += t8_forest_get_tree_element_offset (forest, lneigh_treeid); } - if ((neigh_scheme->t8_element_compare (ancestor, neighbor_leaves[0]) < 0) || ts->t8_element_is_subelement (leaf)) { + if ((neigh_scheme->t8_element_compare (ancestor, neighbor_leaves[0]) < 0) + || ts->t8_element_is_subelement (leaf)) { /* we expect only one neighbor (or a neighboring transition cell with possibly multiple * subelement neighbors if the transition scheme is not conformal) in this case */ From 6c121972b63c56f6ac8921a03c1199a2d6cc8a92 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Thu, 13 Jun 2024 13:35:35 +0200 Subject: [PATCH 35/55] corrected typo --- example/transition/t8_transition_LFN_hex.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/example/transition/t8_transition_LFN_hex.cxx b/example/transition/t8_transition_LFN_hex.cxx index f0bb1afcda..e4f4a7c34f 100644 --- a/example/transition/t8_transition_LFN_hex.cxx +++ b/example/transition/t8_transition_LFN_hex.cxx @@ -85,7 +85,7 @@ t8_LFN_test (t8_forest_t forest_adapt) const t8_element_t *current_element; t8_tree_t current_tree; t8_locidx_t forest_is_balanced = 1; - t8_element_t **neighbor_leafs; + t8_element_t **neighbor_leaves; t8_locidx_t *element_indices; t8_eclass_scheme_c *neigh_scheme; t8_eclass_t eclass; @@ -130,7 +130,7 @@ t8_LFN_test (t8_forest_t forest_adapt) for (face_id = 0; face_id < ts->t8_element_num_faces (current_element); ++face_id) { LFN_call_count++; - t8_forest_leaf_face_neighbors (forest_adapt, tree_count, current_element, &neighbor_leafs, face_id, &dual_faces, + t8_forest_leaf_face_neighbors (forest_adapt, tree_count, current_element, &neighbor_leaves, face_id, &dual_faces, &num_neighbors, &element_indices, &neigh_scheme, forest_is_balanced); /* free memory if neighbors exist */ if (num_neighbors > 0) { @@ -145,14 +145,14 @@ t8_LFN_test (t8_forest_t forest_adapt) element_indices[neighbor_count], t8_forest_get_local_num_elements (forest_adapt) + t8_forest_get_num_ghosts (forest_adapt), t8_forest_get_local_num_elements (forest_adapt) - 1); - ts->t8_element_debug_print (neighbor_leafs[neighbor_count]); + ts->t8_element_debug_print (neighbor_leaves[neighbor_count]); #endif } - neigh_scheme->t8_element_destroy (num_neighbors, neighbor_leafs); + neigh_scheme->t8_element_destroy (num_neighbors, neighbor_leaves); T8_FREE (element_indices); - T8_FREE (neighbor_leafs); + T8_FREE (neighbor_leaves); T8_FREE (dual_faces); } else { From 44eb4e35a56494d4bc6bd0bac66e2d154b5f6a33 Mon Sep 17 00:00:00 2001 From: Tabea Leistikow Date: Thu, 13 Jun 2024 13:42:10 +0200 Subject: [PATCH 36/55] clang-format --- example/transition/t8_transition_LFN_hex.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/example/transition/t8_transition_LFN_hex.cxx b/example/transition/t8_transition_LFN_hex.cxx index e4f4a7c34f..f118abe0ba 100644 --- a/example/transition/t8_transition_LFN_hex.cxx +++ b/example/transition/t8_transition_LFN_hex.cxx @@ -130,8 +130,9 @@ t8_LFN_test (t8_forest_t forest_adapt) for (face_id = 0; face_id < ts->t8_element_num_faces (current_element); ++face_id) { LFN_call_count++; - t8_forest_leaf_face_neighbors (forest_adapt, tree_count, current_element, &neighbor_leaves, face_id, &dual_faces, - &num_neighbors, &element_indices, &neigh_scheme, forest_is_balanced); + t8_forest_leaf_face_neighbors (forest_adapt, tree_count, current_element, &neighbor_leaves, face_id, + &dual_faces, &num_neighbors, &element_indices, &neigh_scheme, + forest_is_balanced); /* free memory if neighbors exist */ if (num_neighbors > 0) { From 1624806b2ebc00730fe09237ee32b80363447a38 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Fri, 12 Jul 2024 14:59:08 +0200 Subject: [PATCH 37/55] Use more const pointers according to new changes in main --- src/t8_forest/t8_forest_adapt.cxx | 2 +- src/t8_forest/t8_forest_cxx.cxx | 19 ++++++++++--------- src/t8_forest/t8_forest_transition.cxx | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/t8_forest/t8_forest_adapt.cxx b/src/t8_forest/t8_forest_adapt.cxx index d5a83a59d6..e9c954cb11 100644 --- a/src/t8_forest/t8_forest_adapt.cxx +++ b/src/t8_forest/t8_forest_adapt.cxx @@ -604,7 +604,7 @@ t8_forest_adapt (t8_forest_t forest) (void) t8_element_array_push_count (telements, num_subelements); for (zz = 0; zz < num_subelements; zz++) { - elements[zz] = t8_element_array_index_locidx (telements, el_inserted + zz); + elements[zz] = t8_element_array_index_locidx_mutable (telements, el_inserted + zz); } tscheme->t8_element_to_transition_cell (elements_from[0], refine - 1, elements); el_inserted += num_subelements; diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index 5c78b1c962..6a68879b46 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -1710,8 +1710,8 @@ t8_forest_element_half_face_neighbors (t8_forest_t forest, t8_locidx_t ltreeid, /* This function does not need a declaration and is only called by LFN_transitioned. * When entering this function, a neighbor transition cell is found and some additional * subelement-specific functions are applied to return the right subelement neighbor of leaf. */ -void -t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, t8_element_t *pseudo_neighbor, +static void +t8_forest_get_transition_cell_face_neighbor (t8_forest_t forest, const t8_element_t *pseudo_neighbor, const t8_element_t *leaf, t8_locidx_t element_index, int face, t8_locidx_t lneigh_treeid, t8_element_t **neighbor_leaves, t8_locidx_t **pelement_indices, int neighbor_is_ghost, int *owners, @@ -1878,8 +1878,9 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre t8_locidx_t lneigh_treeid = -1; t8_locidx_t lghost_treeid = -1, *element_indices, element_index, subelement_neighbor_index, ghost_element_index = -1; t8_eclass_scheme_c *ts, *neigh_scheme; - t8_element_array_t *element_array; - t8_element_t *ancestor, **neighbor_leaves; + + const t8_element_t *ancestor; + t8_element_t **neighbor_leaves; t8_linearidx_t neigh_id; int num_children_at_face, at_maxlevel; int ineigh, *owners, different_owners, have_ghosts, neighbor_is_ghost = 0; @@ -1935,7 +1936,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre for (int neighbor_count = 0; neighbor_count < *num_neighbors; neighbor_count++) { t8_debugf ("num neighbors %i\n", *num_neighbors); neigh_id = ts->t8_element_get_linear_id (neighbor_leaves[neighbor_count], forest->maxlevel); - element_array = t8_forest_get_tree_element_array (forest, ltreeid); + const t8_element_array_t *element_array = t8_forest_get_tree_element_array (forest, ltreeid); subelement_neighbor_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); element_indices[neighbor_count] = subelement_neighbor_index - ts->t8_element_get_subelement_id (t8_forest_get_tree_element ( @@ -2054,7 +2055,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre if (owners[0] != forest->mpirank) { /* The elements are ghost elements of the same owner */ neighbor_is_ghost = 1; - element_array = t8_forest_ghost_get_tree_elements (forest, lghost_treeid); + const t8_element_array_t *element_array = t8_forest_ghost_get_tree_elements (forest, lghost_treeid); /* Find the index in element_array of the leaf ancestor of the first neighbor. * This is either the neighbor itself or its parent, or its grandparent */ element_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); @@ -2070,7 +2071,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre } else { /* the elements are local elements */ - element_array = t8_forest_get_tree_element_array (forest, lneigh_treeid); + const t8_element_array_t *element_array = t8_forest_get_tree_element_array (forest, lneigh_treeid); /* Find the index in element_array of the leaf ancestor of the first neighbor. * This is either the neighbor itself or its parent, or its grandparent */ element_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); @@ -2168,7 +2169,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre * in the ghost structure */ if (owners[ineigh] == forest->mpirank) { /* The neighbor is a local leaf */ - element_array = t8_forest_get_tree_element_array (forest, lneigh_treeid); + const t8_element_array_t *element_array = t8_forest_get_tree_element_array (forest, lneigh_treeid); /* Find the index of the neighbor in the array */ element_indices[ineigh] = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); T8_ASSERT (element_indices[ineigh] >= 0); @@ -2188,7 +2189,7 @@ t8_forest_leaf_face_neighbors_transitioned (t8_forest_t forest, t8_locidx_t ltre } else { /* The neighbor is a ghost */ - element_array = t8_forest_ghost_get_tree_elements (forest, lghost_treeid); + const t8_element_array_t *element_array = t8_forest_ghost_get_tree_elements (forest, lghost_treeid); /* Find the index of the neighbor in the array */ element_indices[ineigh] = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx index 02801c9dd1..77dfa5ee0c 100644 --- a/src/t8_forest/t8_forest_transition.cxx +++ b/src/t8_forest/t8_forest_transition.cxx @@ -320,7 +320,7 @@ t8_forest_is_transitioned (t8_forest_t forest) telements = ¤t_tree->elements; num_elems = (t8_locidx_t) t8_element_array_get_count (telements); for (elem_count = 0; elem_count < num_elems; elem_count++) { - t8_element_t *current_element = t8_element_array_index_locidx (telements, elem_count); + const t8_element_t *current_element = t8_element_array_index_locidx (telements, elem_count); tscheme = forest->scheme_cxx->eclass_schemes[current_tree->eclass]; if (tscheme->t8_element_is_subelement (current_element)) { /* subelement found -> return true */ From 58f58068c39f93754502fc5e9a9dc97f533ef99c Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 22 Jul 2024 13:28:00 +0200 Subject: [PATCH 38/55] t8_element_reference_coords for 2D transition scheme --- .../t8_transition_conformal_quad_cxx.cxx | 41 ++++++++++++++++++- .../t8_transition_conformal_quad_cxx.hxx | 2 - 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index c7eb009d5e..edc1a4e7a8 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "t8.h" #include "t8_transition_conformal_quad_cxx.hxx" @@ -1370,7 +1372,44 @@ void t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) const { - SC_ABORT ("This function is not implemented for the given scheme.\n"); + T8_ASSERT (ref_coords != NULL); + T8_ASSERT (out_coords != NULL); + T8_ASSERT (num_coords == 2); + T8_ASSERT (t8_element_is_valid (elem)); + static struct t8_default_scheme_quad_c default_quad_scheme; + + const t8_quad_with_subelements *element = (t8_quad_with_subelements *) elem; + if (!t8_element_is_subelement (elem)) { + const t8_element_t * quad = (const t8_element_t *)&element->p4q; + // We call the default quad reference coord function for the quad coordinates. + // We could think about doing this in more cases. For that it would + // be beneficial to store a t8_default_scheme_quad_c pointer as member variable + // of the t8_subelement_scheme_quad_c class. + default_quad_scheme.t8_element_reference_coords (quad, ref_coords, num_coords, out_coords); + } + else { + /* This element is a subelement and hence a triangle. */ + T8_ASSERT (t8_element_shape (elem) == T8_ECLASS_TRIANGLE); + + /* We first convert the reference coordinates to barycentric + * coordinates. + * Since the reference triangle has vertices + * (0,0) (1,0) and (1,1) + * A vector (x,y) in that triangle has barycentric + * coordinates (0, x-y, y). + * This is since 0 * (0,0) + (x-y) * (1,0) + y * (1,1) = (0 + x - y + y, y) = (x,y) + * + * After that we use t8_geom_triangular_interpolation to compute the actual value. + */ + const double barycentric_coeff[3] = {0, ref_coords[0] - ref_coords[1], ref_coords[1]}; + constexpr int num_vertices = 3; // Should use t8_eclass_num_vertices[T8_ECLASS_TRIANGLE]; but is not constexpr + constexpr int num_vertex_coords = num_vertices * 3; + double vertex_coords[num_vertex_coords]; // Stores the triangle's vertices + for (int ivertex = 0;ivertex < num_vertices;++ivertex) { + t8_element_vertex_reference_coords (elem, ivertex, vertex_coords + 3*ivertex); + } + t8_geom_triangular_interpolation (barycentric_coeff, vertex_coords, 3, 2, out_coords); + } } void diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index 36fea72c17..b47496af7b 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -75,8 +75,6 @@ typedef struct int subelement_id; } t8_quad_with_subelements; -typedef t8_quad_with_subelements t8_pquad_t; - /** define some subelement related constants */ #define T8_SUB_QUAD_MAX_TRANSITION_TYPE 15 #define T8_SUB_QUAD_MAX_SUBELEMENT_ID 7 From fcd2090f0306f16f4a44843e6646019c40b15aaf Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 22 Jul 2024 16:08:59 +0200 Subject: [PATCH 39/55] Rename forest_cxx.cxx to forest.cxx to prepare merge --- .../{t8_forest_cxx.cxx => t8_forest.cxx} | 1684 +++++++++++++++++ 1 file changed, 1684 insertions(+) rename src/t8_forest/{t8_forest_cxx.cxx => t8_forest.cxx} (72%) diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest.cxx similarity index 72% rename from src/t8_forest/t8_forest_cxx.cxx rename to src/t8_forest/t8_forest.cxx index 6a68879b46..1a7196b371 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest.cxx @@ -3294,4 +3294,1688 @@ t8_forest_element_has_leaf_desc (t8_forest_t forest, t8_gloidx_t gtreeid, const return 0; } +void +t8_forest_init (t8_forest_t *pforest) +{ + t8_forest_t forest; + + T8_ASSERT (pforest != NULL); + + forest = *pforest = T8_ALLOC_ZERO (t8_forest_struct_t, 1); + t8_refcount_init (&forest->rc); + + /* sensible (hard error) defaults */ + forest->mpicomm = sc_MPI_COMM_NULL; + forest->dimension = -1; + forest->from_method = T8_FOREST_FROM_LAST; + + forest->mpisize = -1; + forest->mpirank = -1; + forest->first_local_tree = -1; + forest->global_num_elements = -1; + forest->set_adapt_recursive = -1; + forest->set_balance = -1; + forest->maxlevel_existing = -1; + forest->stats_computed = 0; + forest->incomplete_trees = -1; + forest->set_subelements = 0; + forest->is_transitioned = 0; +} + +int +t8_forest_is_initialized (t8_forest_t forest) +{ + return forest != NULL && t8_refcount_is_active (&forest->rc) && !forest->committed; +} + +/** Check whether at least one eclass scheme of forest supports transitioning + * \param [in] forest A forest + * \return True if at least one eclass scheme in forest has an implementation for subelements + */ +int +t8_forest_supports_transitioning (t8_forest_t forest) +{ + int supports_transition = 1; + int supports_transition_all_procs = 0; /* Result over all procs */ + int int_eclass; + int mpiret; + t8_eclass_scheme_c *tscheme; + + /* Iterate over all eclasses */ + for (int_eclass = (int) T8_ECLASS_ZERO; int_eclass < (int) T8_ECLASS_COUNT; int_eclass++) { + /* If the forest has trees of the current eclass, check if elements of this + * eclass supports transitioning. */ + if (forest->cmesh->num_local_trees_per_eclass[int_eclass] > 0) { + tscheme = forest->scheme_cxx->eclass_schemes[int_eclass]; + supports_transition = supports_transition && t8_element_scheme_supports_transitioning (tscheme); + } + } + /* Combine the process-local results via a logic or and distribute the + * result over all procs (in the communicator).*/ + mpiret = sc_MPI_Allreduce (&supports_transition, &supports_transition_all_procs, 1, sc_MPI_INT, sc_MPI_LAND, + forest->mpicomm); + SC_CHECK_MPI (mpiret); + + return supports_transition_all_procs; +} + +int +t8_forest_is_committed (const t8_forest_t forest) +{ + return forest != NULL && t8_refcount_is_active (&forest->rc) && forest->committed; +} + +static void +t8_forest_set_mpicomm (t8_forest_t forest, sc_MPI_Comm mpicomm, int do_dup) +{ + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + T8_ASSERT (forest->mpicomm == sc_MPI_COMM_NULL); + T8_ASSERT (forest->set_from == NULL); + + T8_ASSERT (mpicomm != sc_MPI_COMM_NULL); + + forest->mpicomm = mpicomm; + forest->do_dup = do_dup; +} + +/* TODO: Change forest mpi logic */ +void +t8_forest_set_cmesh (t8_forest_t forest, t8_cmesh_t cmesh, sc_MPI_Comm comm) +{ + int do_dup; + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + T8_ASSERT (forest->cmesh == NULL); + T8_ASSERT (forest->set_from == NULL); + + T8_ASSERT (cmesh != NULL); + + if (forest->cmesh != NULL) { + t8_cmesh_unref (&forest->cmesh); + } + if (cmesh != NULL) { + T8_ASSERT (t8_cmesh_comm_is_valid (cmesh, comm)); + } + forest->cmesh = cmesh; + do_dup = 0; + t8_forest_set_mpicomm (forest, comm, do_dup); +} + +void +t8_forest_set_scheme (t8_forest_t forest, t8_scheme_cxx_t *scheme) +{ + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + T8_ASSERT (forest->scheme_cxx == NULL); + T8_ASSERT (forest->set_from == NULL); + + T8_ASSERT (scheme != NULL); + + forest->scheme_cxx = scheme; +} + +void +t8_forest_set_level (t8_forest_t forest, int level) +{ + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + + T8_ASSERT (0 <= level); + + forest->set_level = level; +} + +void +t8_forest_set_copy (t8_forest_t forest, const t8_forest_t set_from) +{ + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + T8_ASSERT (forest->mpicomm == sc_MPI_COMM_NULL); + T8_ASSERT (forest->cmesh == NULL); + T8_ASSERT (forest->scheme_cxx == NULL); + T8_ASSERT (forest->set_from == NULL); + + T8_ASSERT (set_from != NULL); + + forest->set_from = set_from; + /* Set the from_method to COPY. This overwrites any previous setting of ADAPT, PARTITION, or BALANCE */ + forest->from_method = T8_FOREST_FROM_COPY; + + /* Overwrite any previous setting */ + forest->set_adapt_fn = NULL; + forest->set_adapt_recursive = -1; + forest->set_balance = -1; + forest->set_for_coarsening = -1; +} + +void +t8_forest_set_partition (t8_forest_t forest, const t8_forest_t set_from, int set_for_coarsening) +{ + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + T8_ASSERT (forest->mpicomm == sc_MPI_COMM_NULL); + T8_ASSERT (forest->cmesh == NULL); + T8_ASSERT (forest->scheme_cxx == NULL); + + forest->set_for_coarsening = set_for_coarsening; + + if (set_from != NULL) { + /* If set_from = NULL, we assume a previous forest_from was set */ + forest->set_from = set_from; + } + /* Add PARTITION to the from_method. + * This overwrites T8_FOREST_FROM_COPY */ + if (forest->from_method == T8_FOREST_FROM_LAST) { + forest->from_method = T8_FOREST_FROM_PARTITION; + } + else { + forest->from_method |= T8_FOREST_FROM_PARTITION; + } +} + +void +t8_forest_set_balance (t8_forest_t forest, const t8_forest_t set_from, int no_repartition) +{ + T8_ASSERT (t8_forest_is_initialized (forest)); + + if (no_repartition) { + /* We do not repartition the forest during balance */ + forest->set_balance = T8_FOREST_BALANCE_NO_REPART; + } + else { + /* Repartition during balance */ + forest->set_balance = T8_FOREST_BALANCE_REPART; + } + + if (set_from != NULL) { + /* If set_from = NULL, we assume a previous forest_from was set */ + forest->set_from = set_from; + } + + /* Add BALANCE to the from_method. + * This overwrites T8_FOREST_FROM_COPY */ + if (forest->from_method == T8_FOREST_FROM_LAST) { + forest->from_method = T8_FOREST_FROM_BALANCE; + } + else { + forest->from_method |= T8_FOREST_FROM_BALANCE; + } +} + +void +t8_forest_set_transition (t8_forest_t forest, const t8_forest_t set_from, int set_transition_with_balance) +{ + T8_ASSERT (t8_forest_is_initialized (forest)); + + if (set_transition_with_balance) { + t8_debugf ("-------------set transition with balance -------------\n"); + /* balance with repartition */ + t8_forest_set_balance (forest, set_from, 0); + } + + if (set_from != NULL) { + /* Note that it is possible to apply transitioning to a forest without transition implementation. + * In this case, the transition refine routine will return 0, keeping the forest unchanged. + * Nevertheless, we assert here in this case. */ + T8_ASSERT (t8_forest_supports_transitioning (set_from)); + /* If set_from = NULL, we assume a previous forest_from was set */ + forest->set_from = set_from; + } + else { + T8_ASSERT (forest->set_from != NULL); + T8_ASSERT (t8_forest_supports_transitioning (forest->set_from)); + } + + /* Add SUBELEMENTS to the from_method. + * This overwrites T8_FOREST_FROM_COPY */ + if (forest->from_method == T8_FOREST_FROM_LAST) { + forest->from_method = T8_FOREST_FROM_TRANSITION; + } + else { + forest->from_method |= T8_FOREST_FROM_TRANSITION; + } + + /* set the forests subelement flag, which is for example used by the LFN routine */ + forest->set_subelements = 1; + // forest->is_transitioned = 1; +} + +void +t8_forest_set_ghost_ext (t8_forest_t forest, int do_ghost, t8_ghost_type_t ghost_type, int ghost_version) +{ + T8_ASSERT (t8_forest_is_initialized (forest)); + /* We currently only support face ghosts */ + SC_CHECK_ABORT (do_ghost == 0 || ghost_type == T8_GHOST_FACES, + "Ghost neighbors other than face-neighbors are not supported.\n"); + SC_CHECK_ABORT (1 <= ghost_version && ghost_version <= 3, "Invalid choice for ghost version. Choose 1, 2, or 3.\n"); + + if (ghost_type == T8_GHOST_NONE) { + /* none type disables ghost */ + forest->do_ghost = 0; + } + else { + forest->do_ghost = (do_ghost != 0); /* True if and only if do_ghost != 0 */ + } + if (forest->do_ghost) { + forest->ghost_type = ghost_type; + forest->ghost_algorithm = ghost_version; + } +} + +void +t8_forest_set_ghost (t8_forest_t forest, int do_ghost, t8_ghost_type_t ghost_type) +{ + /* Use ghost version 3, top-down search and for unbalanced forests. */ + t8_forest_set_ghost_ext (forest, do_ghost, ghost_type, 3); +} + +void +t8_forest_set_adapt (t8_forest_t forest, const t8_forest_t set_from, t8_forest_adapt_t adapt_fn, int recursive) +{ + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + T8_ASSERT (forest->mpicomm == sc_MPI_COMM_NULL); + T8_ASSERT (forest->cmesh == NULL); + T8_ASSERT (forest->scheme_cxx == NULL); + T8_ASSERT (forest->set_adapt_fn == NULL); + T8_ASSERT (forest->set_adapt_recursive == -1); + + forest->set_adapt_fn = adapt_fn; + forest->set_adapt_recursive = recursive != 0; + + if (set_from != NULL) { + /* If set_from = NULL, we assume a previous forest_from was set */ + forest->set_from = set_from; + } + + /* Add ADAPT to the from_method. + * This overwrites T8_FOREST_FROM_COPY */ + + if (forest->from_method == T8_FOREST_FROM_LAST) { + forest->from_method = T8_FOREST_FROM_ADAPT; + } + else { + forest->from_method |= T8_FOREST_FROM_ADAPT; + } +} + +void +t8_forest_set_user_data (t8_forest_t forest, void *data) +{ + /* TODO: we need a is_initialized and may be committed check! */ + forest->user_data = data; +} + +void * +t8_forest_get_user_data (const t8_forest_t forest) +{ + return forest->user_data; +} + +void +t8_forest_set_user_function (t8_forest_t forest, t8_generic_function_pointer function) +{ + T8_ASSERT (t8_forest_is_initialized (forest) || t8_forest_is_committed (forest)); + forest->user_function = function; +} + +t8_generic_function_pointer +t8_forest_get_user_function (t8_forest_t forest) +{ + //T8_ASSERT (t8_forest_is_initialized (forest) || t8_forest_is_committed (forest)); + return forest->user_function; +} + +void +t8_forest_comm_global_num_elements (t8_forest_t forest) +{ + int mpiret; + t8_gloidx_t local_num_el; + t8_gloidx_t global_num_el; + + local_num_el = (t8_gloidx_t) forest->local_num_elements; + mpiret = sc_MPI_Allreduce (&local_num_el, &global_num_el, 1, T8_MPI_GLOIDX, sc_MPI_SUM, forest->mpicomm); + SC_CHECK_MPI (mpiret); + forest->global_num_elements = global_num_el; +} + +/** Adapt callback function to refine every element in the forest. + * It is merely used to build a new forest with pyramids. + * + * \param [in] forest the forest to which the new elements belong + * \param [in] forest_from the forest that is adapted. + * \param [in] which_tree the local tree containing \a elements + * \param [in] lelement_id the local element id in \a forest_old in the tree of the current element + * \param [in] ts the eclass scheme of the tree + * \param [in] is_family if 1, the first \a num_elements entries in \a elements form a family. If 0, they do not. + * \param [in] num_elements the number of entries in \a elements that are defined + * \param [in] elements Pointers to a family or, if \a is_family is zero, + * pointer to one element. + * \return Always return 1, to refine every element + */ +static int +t8_forest_refine_everything (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, + t8_locidx_t lelement_id, t8_eclass_scheme_c *ts, const int is_family, + const int num_elements, t8_element_t *elements[]) +{ + + return 1; +} + +/** + * Check if any tree in a forest refines irregularly. + * An irregular refining tree is a tree with an element that does not + * refine into 2^dim children. For example the default implementation + * of pyramids. + * \note This function is MPI collective + * + * \param[in] forest The forest to check + * \return non-zero if any tree refines irregular + */ +static int +t8_forest_refines_irregular (t8_forest_t forest) +{ + int irregular = 0; + int irregular_all_procs = 0; /* Result over all procs */ + int int_eclass; + int mpiret; + t8_eclass_scheme_c *tscheme; + /* Iterate over all eclasses */ + for (int_eclass = (int) T8_ECLASS_ZERO; int_eclass < (int) T8_ECLASS_COUNT; int_eclass++) { + /* If the forest has trees of the current eclass, check if elements of this eclass refine irregular. */ + if (forest->cmesh->num_local_trees_per_eclass[int_eclass] > 0) { + tscheme = t8_forest_get_eclass_scheme_before_commit (forest, (t8_eclass_t) int_eclass); + irregular = irregular || t8_element_refines_irregular (tscheme); + } + } + /* Combine the process-local results via a logic or and distribute the result over all procs (in the communicator).*/ + mpiret = sc_MPI_Allreduce (&irregular, &irregular_all_procs, 1, sc_MPI_INT, sc_MPI_LOR, forest->mpicomm); + SC_CHECK_MPI (mpiret); + return irregular_all_procs; +} + +/** Algorithm to populate a forest, if any tree refines irregularly. + * Create the elements on this process given a uniform partition + * of the coarse mesh. We can not use the function t8_forest_populate, because + * it assumes a regular refinement for all trees. + * \param[in] forest The forest to populate +*/ +static void +t8_forest_populate_irregular (t8_forest_t forest) +{ + t8_forest_t forest_zero; + t8_forest_t forest_tmp; + t8_forest_t forest_tmp_partition; + t8_cmesh_ref (forest->cmesh); + t8_scheme_cxx_ref (forest->scheme_cxx); + /* We start with a level 0 uniform refinement */ + t8_forest_init (&forest_zero); + t8_forest_set_level (forest_zero, 0); + t8_forest_set_cmesh (forest_zero, forest->cmesh, forest->mpicomm); + t8_forest_set_scheme (forest_zero, forest->scheme_cxx); + + t8_forest_commit (forest_zero); + /* Up to the specified level we refine every element. */ + for (int i = 1; i <= forest->set_level; i++) { + t8_forest_init (&forest_tmp); + t8_forest_set_level (forest_tmp, i); + t8_forest_set_adapt (forest_tmp, forest_zero, t8_forest_refine_everything, 0); + t8_forest_commit (forest_tmp); + /* Partition the forest to even the load */ + t8_forest_init (&forest_tmp_partition); + t8_forest_set_partition (forest_tmp_partition, forest_tmp, 0); + t8_forest_commit (forest_tmp_partition); + + forest_zero = forest_tmp_partition; + } + + /* Copy all elements over to the original forest. */ + t8_forest_copy_trees (forest, forest_zero, 1); + + t8_forest_unref (&forest_tmp_partition); +} + +void +t8_forest_commit (t8_forest_t forest) +{ + int mpiret; + int partitioned = 0; + sc_MPI_Comm comm_dup; + + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + if (forest->profile != NULL) { + /* If profiling is enabled, we measure the runtime of commit */ + forest->profile->commit_runtime = sc_MPI_Wtime (); + } + + if (forest->set_from == NULL) { + /* This forest is constructed solely from its cmesh as a uniform + * forest */ + T8_ASSERT (forest->mpicomm != sc_MPI_COMM_NULL); + T8_ASSERT (forest->cmesh != NULL); + T8_ASSERT (forest->scheme_cxx != NULL); + T8_ASSERT (forest->from_method == T8_FOREST_FROM_LAST); + T8_ASSERT (forest->incomplete_trees == -1); + T8_ASSERT (forest->set_subelements == 0); + T8_ASSERT (forest->is_transitioned == 0); + /* dup communicator if requested */ + if (forest->do_dup) { + mpiret = sc_MPI_Comm_dup (forest->mpicomm, &comm_dup); + SC_CHECK_MPI (mpiret); + forest->mpicomm = comm_dup; + } + forest->dimension = forest->cmesh->dimension; + /* Set mpirank and mpisize */ + mpiret = sc_MPI_Comm_size (forest->mpicomm, &forest->mpisize); + SC_CHECK_MPI (mpiret); + + mpiret = sc_MPI_Comm_rank (forest->mpicomm, &forest->mpirank); + SC_CHECK_MPI (mpiret); + /* Compute the maximum allowed refinement level */ + t8_forest_compute_maxlevel (forest); + T8_ASSERT (forest->set_level <= forest->maxlevel); + + /* populate a new forest with tree and quadrant objects */ + if (t8_forest_refines_irregular (forest) && forest->set_level > 0) { + /* On root level we will also use the normal algorithm */ + t8_forest_populate_irregular (forest); + } + else { + + t8_forest_populate (forest); + } + forest->global_num_trees = t8_cmesh_get_num_trees (forest->cmesh); + forest->incomplete_trees = 0; + forest->is_transitioned = 0; + } + else { + /* set_from != NULL */ + t8_forest_t forest_from = forest->set_from; /* temporarily store set_from, since we may overwrite it */ + + T8_ASSERT (forest->mpicomm == sc_MPI_COMM_NULL); + T8_ASSERT (forest->cmesh == NULL); + T8_ASSERT (forest->scheme_cxx == NULL); + T8_ASSERT (!forest->do_dup); + T8_ASSERT (forest->from_method >= T8_FOREST_FROM_FIRST && forest->from_method < T8_FOREST_FROM_LAST); + T8_ASSERT (forest->set_from->incomplete_trees > -1); + + /* TODO: optimize all this when forest->set_from has reference count one */ + /* TODO: Get rid of duping the communicator */ + /* we must prevent the case that set_from frees the source communicator */ + if (!forest->set_from->do_dup) { + forest->mpicomm = forest->set_from->mpicomm; + } + else { + mpiret = sc_MPI_Comm_dup (forest->set_from->mpicomm, &forest->mpicomm); + SC_CHECK_MPI (mpiret); + } + forest->do_dup = forest->set_from->do_dup; + + /* Set mpirank and mpisize */ + mpiret = sc_MPI_Comm_size (forest->mpicomm, &forest->mpisize); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Comm_rank (forest->mpicomm, &forest->mpirank); + SC_CHECK_MPI (mpiret); + + /* increase reference count of cmesh and scheme from the input forest */ + t8_cmesh_ref (forest->set_from->cmesh); + t8_scheme_cxx_ref (forest->set_from->scheme_cxx); + /* set the dimension, cmesh and scheme from the old forest */ + forest->dimension = forest->set_from->dimension; + forest->cmesh = forest->set_from->cmesh; + forest->scheme_cxx = forest->set_from->scheme_cxx; + forest->global_num_trees = forest->set_from->global_num_trees; + + /* Compute the maximum allowed refinement level */ + t8_forest_compute_maxlevel (forest); + if (forest->from_method == T8_FOREST_FROM_COPY) { + SC_CHECK_ABORT (forest->set_from != NULL, "No forest to copy from was specified."); + t8_forest_copy_trees (forest, forest->set_from, 1); + } + /* TODO: currently we can only handle copy, adapt, partition, and balance */ + + /* T8_ASSERT (forest->from_method == T8_FOREST_FROM_COPY); */ + if (forest->from_method & T8_FOREST_FROM_ADAPT) { + SC_CHECK_ABORT (forest->set_adapt_fn != NULL, "No adapt function specified"); + + forest->from_method -= T8_FOREST_FROM_ADAPT; + if (forest->from_method > 0) { + /* The forest should also be partitioned/balanced/transitioned. + * We first untransition the forest, then adapt the forest, then balance and then partition and then possibly transition the forest again*/ + if (forest->set_from->is_transitioned) { + T8_ASSERT (forest->is_transitioned == 0); + t8_forest_untransition (forest); + } + + t8_forest_t forest_adapt; + + t8_forest_init (&forest_adapt); + /* forest_adapt should not change ownership of forest->set_from */ + if (forest_from == forest->set_from) { + t8_forest_ref (forest->set_from); + } + /* set user data of forest to forest_adapt */ + t8_forest_set_user_data (forest_adapt, t8_forest_get_user_data (forest)); + /* Construct an intermediate, adapted forest */ + t8_forest_set_adapt (forest_adapt, forest->set_from, forest->set_adapt_fn, forest->set_adapt_recursive); + /* Set profiling if enabled */ + t8_forest_set_profiling (forest_adapt, forest->profile != NULL); + t8_forest_commit (forest_adapt); + /* The new forest will be partitioned/balanced from forest_adapt */ + forest->set_from = forest_adapt; + /* Set the user data of forest_from to forest_adapt */ + t8_forest_set_user_data (forest_adapt, t8_forest_get_user_data (forest_from)); + /* If profiling is enabled copy the runtime of adapt. */ + if (forest->profile != NULL) { + forest->profile->adapt_runtime = forest_adapt->profile->adapt_runtime; + } + } + else { + /* This forest should only be adapted */ + t8_forest_copy_trees (forest, forest->set_from, 0); + + t8_forest_adapt (forest); + } + } + if (forest->from_method & T8_FOREST_FROM_PARTITION) { + partitioned = 1; + /* Partition this forest */ + forest->from_method -= T8_FOREST_FROM_PARTITION; + + if (forest->from_method > 0) { + /* The forest should also be balanced/transitioned after partition */ + t8_forest_t forest_partition; + + t8_forest_init (&forest_partition); + if (forest_from == forest->set_from) { + /* forest_partition should not change ownership of forest->set_from */ + t8_forest_ref (forest->set_from); + } + t8_forest_set_partition (forest_partition, forest->set_from, forest->set_for_coarsening); + /* activate profiling, if this forest has profiling */ + t8_forest_set_profiling (forest_partition, forest->profile != NULL); + /* Commit the partitioned forest */ + t8_forest_commit (forest_partition); + forest->set_from = forest_partition; + if (forest->profile != NULL) { + forest->profile->partition_bytes_sent = forest_partition->profile->partition_bytes_sent; + forest->profile->partition_elements_recv = forest_partition->profile->partition_elements_recv; + forest->profile->partition_elements_shipped = forest_partition->profile->partition_elements_shipped; + forest->profile->partition_procs_sent = forest_partition->profile->partition_procs_sent; + forest->profile->partition_runtime = forest_partition->profile->partition_runtime; + } + } + else { + forest->incomplete_trees = forest->set_from->incomplete_trees; + /* Partitioning is the last routine, no balance was set */ + forest->global_num_elements = forest->set_from->global_num_elements; + /* Initialize the trees array of the forest */ + forest->trees = sc_array_new (sizeof (t8_tree_struct_t)); + /* partition the forest */ + t8_forest_partition (forest); + } + } + if (forest->from_method & T8_FOREST_FROM_BALANCE) { + /* balance the forest */ + forest->from_method -= T8_FOREST_FROM_BALANCE; + if (forest->from_method > 0) { + int flag_rep; + if (forest->set_balance == T8_FOREST_BALANCE_NO_REPART) { + /* balance without repartition */ + flag_rep = 1; + } + else { + /* balance with repartition */ + flag_rep = 0; + } + /* in this case, we will transition after balancing */ + t8_forest_t forest_balance; + t8_forest_init (&forest_balance); + /* forest_balance should not change ownership of forest->set_from */ + if (forest_from == forest->set_from) { + t8_forest_ref (forest->set_from); + } + t8_forest_set_balance (forest_balance, forest->set_from, flag_rep); + /* Set profiling if enabled */ + t8_forest_set_profiling (forest_balance, forest->profile != NULL); + t8_forest_commit (forest_balance); + /* The new forest will be partitioned/transitioned from forest_balance */ + forest->set_from = forest_balance; + } + else { + /* Only execute t8_balance.*/ + T8_ASSERT (forest->from_method == 0); + + /* This forest should only be balanced */ + if (forest->set_balance == T8_FOREST_BALANCE_NO_REPART) { + /* balance without repartition */ + t8_forest_balance (forest, 0); + } + else { + /* balance with repartition */ + t8_forest_balance (forest, 1); + } + } + } + if (forest->from_method & T8_FOREST_FROM_TRANSITION) { + forest->from_method -= T8_FOREST_FROM_TRANSITION; + /* this is the last from method that we execute, + * nothing should be left todo */ + T8_ASSERT (forest->from_method == 0); + /* use subelements */ + t8_forest_transition (forest); + forest->is_transitioned = 1; + } + if (forest_from != forest->set_from) { + /* decrease reference count of intermediate input forest, possibly destroying it */ + t8_forest_unref (&forest->set_from); + } + /* reset forest->set_from */ + forest->set_from = forest_from; + + /* decrease reference count of input forest, possibly destroying it */ + t8_forest_unref (&forest->set_from); + } /* end set_from != NULL */ + /* Compute the element offset of the trees */ + t8_forest_compute_elements_offset (forest); + + /* Compute first and last descendant for each tree */ + t8_forest_compute_desc (forest); + + /* we do not need the set parameters anymore */ + forest->set_level = 0; + forest->set_for_coarsening = 0; + forest->set_from = NULL; + forest->committed = 1; + t8_debugf ("Forest is transitioned %i \n", forest->is_transitioned); + t8_debugf ("Committed forest with %li local elements and %lli " + "global elements.\n\tTree range is from %lli to %lli.\n", + (long) forest->local_num_elements, (long long) forest->global_num_elements, + (long long) forest->first_local_tree, (long long) forest->last_local_tree); + + if (forest->tree_offsets == NULL) { + /* Compute the tree offset array */ + t8_forest_partition_create_tree_offsets (forest); + } + + if (forest->element_offsets == NULL) { + /* Compute element offsets */ + t8_forest_partition_create_offsets (forest); + } + if (forest->global_first_desc == NULL) { + /* Compute global first desc array */ + t8_forest_partition_create_first_desc (forest); + } + + if (forest->profile != NULL) { + /* If profiling is enabled, we measure the runtime of commit */ + forest->profile->commit_runtime = sc_MPI_Wtime () - forest->profile->commit_runtime; + } + + /* From here on, the forest passes the t8_forest_is_committed check */ + + /* re-partition the cmesh */ + if (forest->cmesh->set_partition && partitioned) { + t8_forest_partition_cmesh (forest, forest->mpicomm, forest->profile != NULL); + } + + if (forest->mpisize > 1) { + /* Construct a ghost layer, if desired */ + if (forest->do_ghost) { + /* TODO: ghost type */ + switch (forest->ghost_algorithm) { + case 1: + t8_forest_ghost_create_balanced_only (forest); + break; + case 2: + t8_forest_ghost_create (forest); + break; + case 3: + t8_forest_ghost_create_topdown (forest); + break; + default: + SC_ABORT ("Invalid choice of ghost algorithm"); + } + } + forest->do_ghost = 0; + } +#ifdef T8_ENABLE_DEBUG + t8_forest_partition_test_boundary_element (forest); +#endif +} + +t8_locidx_t +t8_forest_get_local_num_elements (const t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + + return forest->local_num_elements; +} + +t8_gloidx_t +t8_forest_get_global_num_elements (const t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + + return forest->global_num_elements; +} + +t8_gloidx_t +t8_forest_get_global_num_subelements (t8_forest_t forest) +{ + T8_ASSERT (forest->global_num_subelements <= forest->global_num_elements); + T8_ASSERT (t8_forest_is_committed (forest)); + + return forest->global_num_subelements; +} + +void +t8_forest_comm_global_num_subelements (t8_forest_t forest) +{ + int mpiret; + t8_gloidx_t local_num_subel; + t8_gloidx_t global_num_subel; + + local_num_subel = (t8_gloidx_t) forest->local_num_subelements; + mpiret = sc_MPI_Allreduce (&local_num_subel, &global_num_subel, 1, T8_MPI_GLOIDX, sc_MPI_SUM, forest->mpicomm); + SC_CHECK_MPI (mpiret); + forest->global_num_subelements = global_num_subel; +} +t8_locidx_t +t8_forest_get_local_num_subelements (t8_forest_t forest) +{ + T8_ASSERT (forest->local_num_subelements <= forest->local_num_elements); + T8_ASSERT (t8_forest_is_committed (forest)); + + return forest->local_num_subelements; +} + +t8_locidx_t +t8_forest_get_num_ghosts (const t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + + /* Return the number of ghost elements, or 0 if no ghost structure exists. */ + if (forest->ghosts == NULL) { + return 0; + } + return forest->ghosts->num_ghosts_elements; +} + +/* Currently this function is not used */ + +/* Compute the offset array for a partition cmesh that should match the + * forest's partition. + */ +static t8_shmem_array_t +t8_forest_compute_cmesh_offset (t8_forest_t forest, sc_MPI_Comm comm) +{ + t8_shmem_array_t offset; + + if (forest->tree_offsets == NULL) { + /* Create the tree offsets if necessary */ + t8_forest_partition_create_tree_offsets (forest); + } + /* initialize the shared memory array */ + t8_shmem_array_init (&offset, sizeof (t8_gloidx_t), forest->mpisize + 1, comm); + + /* Copy the contents */ + t8_shmem_array_copy (offset, forest->tree_offsets); + + return offset; +} + +void +t8_forest_partition_cmesh (t8_forest_t forest, sc_MPI_Comm comm, int set_profiling) +{ + t8_cmesh_t cmesh_partition; + t8_shmem_array_t offsets; + + t8_debugf ("Partitioning cmesh according to forest\n"); + + t8_cmesh_init (&cmesh_partition); + t8_cmesh_set_derive (cmesh_partition, forest->cmesh); + /* set partition range of new cmesh according to forest trees */ + if (forest->tree_offsets == NULL) { + t8_forest_partition_create_tree_offsets (forest); + } + offsets = t8_forest_compute_cmesh_offset (forest, comm); + + t8_cmesh_set_partition_offsets (cmesh_partition, offsets); + /* Set the profiling of the cmesh */ + t8_cmesh_set_profiling (cmesh_partition, set_profiling); + /* Commit the new cmesh */ + t8_cmesh_commit (cmesh_partition, comm); + /* set the new cmesh as the cmesh of the forest */ + forest->cmesh = cmesh_partition; + t8_debugf ("Done partitioning cmesh\n"); +} + +sc_MPI_Comm +t8_forest_get_mpicomm (const t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + return forest->mpicomm; +} + +t8_gloidx_t +t8_forest_get_first_local_tree_id (const t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + + return forest->first_local_tree; +} + +t8_locidx_t +t8_forest_get_num_ghost_trees (const t8_forest_t forest) +{ + if (forest->ghosts != NULL) { + return t8_forest_ghost_num_trees (forest); + } + else { + return 0; + } +} + +t8_locidx_t +t8_forest_get_num_local_trees (const t8_forest_t forest) +{ + t8_locidx_t num_trees; + + num_trees = forest->last_local_tree - forest->first_local_tree + 1; + /* assert for possible overflow */ + T8_ASSERT ((t8_gloidx_t) num_trees == forest->last_local_tree - forest->first_local_tree + 1); + if (num_trees < 0) { + /* Set number of trees to zero if there are none */ + num_trees = 0; + } + return num_trees; +} + +t8_gloidx_t +t8_forest_get_num_global_trees (const t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + + return forest->global_num_trees; +} + +t8_gloidx_t +t8_forest_global_tree_id (const t8_forest_t forest, const t8_locidx_t ltreeid) +{ + t8_locidx_t num_local_trees; + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (0 <= ltreeid && ltreeid < t8_forest_get_num_local_trees (forest) + t8_forest_ghost_num_trees (forest)); + + num_local_trees = t8_forest_get_num_local_trees (forest); + if (ltreeid < num_local_trees) { + /* The tree is a local tree */ + return ltreeid + forest->first_local_tree; + } + else { + T8_ASSERT (forest->ghosts != NULL); + /* Return the global id of the ghost tree */ + return t8_forest_ghost_get_global_treeid (forest, ltreeid - num_local_trees); + } +} + +/* TODO: We use this function in forest_partition when the + * forest is only partially committed. Thus, we cannot check whether the + * forest is committed here. */ +t8_tree_t +t8_forest_get_tree (const t8_forest_t forest, const t8_locidx_t ltree_id) +{ + T8_ASSERT (forest->trees != NULL); + T8_ASSERT (0 <= ltree_id && ltree_id < t8_forest_get_num_local_trees (forest)); + return (t8_tree_t) t8_sc_array_index_locidx (forest->trees, ltree_id); +} + +double * +t8_forest_get_tree_vertices (t8_forest_t forest, t8_locidx_t ltreeid) +{ + return t8_cmesh_get_tree_vertices (forest->cmesh, t8_forest_ltreeid_to_cmesh_ltreeid (forest, ltreeid)); +} + +t8_element_array_t * +t8_forest_tree_get_leaves (const t8_forest_t forest, const t8_locidx_t ltree_id) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (0 <= ltree_id && ltree_id < t8_forest_get_num_local_trees (forest)); + + return &t8_forest_get_tree (forest, ltree_id)->elements; +} + +t8_cmesh_t +t8_forest_get_cmesh (const t8_forest_t forest) +{ + return forest->cmesh; +} + +/* Compare function for the binary search in t8_forest_get_element. + * Given a local element id and tree, this function returns 0 + * if the element is inside the tree, -1 if it is inside a tree with + * bigger local tree id and +1 if the element is inside a tree with + * smaller local tree id. + */ +static int +t8_forest_compare_elem_tree (const void *lelement_id, const void *ltree) +{ + t8_locidx_t leid = *(const t8_locidx_t *) lelement_id; + const t8_tree_t tree = (const t8_tree_t) ltree; + + if (tree->elements_offset > leid) { + /* We have to look further to the left */ + return -1; + } + else if (tree->elements_offset + (t8_locidx_t) t8_element_array_get_count (&tree->elements) > leid) { + /* We have found the tree */ + return 0; + } + else { + /* We have to look further right */ + return 1; + } +} + +t8_element_t * +t8_forest_get_element (t8_forest_t forest, t8_locidx_t lelement_id, t8_locidx_t *ltreeid) +{ + t8_tree_t tree; + t8_locidx_t ltree; +#ifdef T8_ENABLE_DEBUG + t8_locidx_t ltreedebug; +#endif + + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (lelement_id >= 0); + if (lelement_id >= t8_forest_get_local_num_elements (forest)) { + return NULL; + } + /* We optimized the binary search out by using sc_bsearch, + * but keep it in for debugging. We check whether the hand-written + * binary search matches the sc_array_bsearch. */ +#ifdef T8_ENABLE_DEBUG + { + t8_locidx_t ltree_a, ltree_b; + ltree_a = 0; + ltree_b = t8_forest_get_num_local_trees (forest); + ltreedebug = (ltree_a + ltree_b) / 2; + while (ltree_a < ltree_b) { + ltreedebug = (ltree_a + ltree_b) / 2; + tree = t8_forest_get_tree (forest, ltreedebug); + if (tree->elements_offset > lelement_id) { + /* We have to look further to the left */ + ltree_b = ltreedebug; + } + else if (tree->elements_offset + (t8_locidx_t) t8_element_array_get_count (&tree->elements) > lelement_id) { + /* We have found the tree */ + ltree_a = ltree_b; + } + else { + /* We have to look further right */ + ltree_a = ltreedebug; + } + } + } +#endif + ltree = sc_array_bsearch (forest->trees, &lelement_id, t8_forest_compare_elem_tree); + T8_ASSERT (ltreedebug == ltree); + if (ltreeid != NULL) { + *ltreeid = ltree; + } + + /* The tree that contains the element is now local tree ltree. + * Or the element is not a local element. */ + tree = t8_forest_get_tree (forest, ltree); + if (tree->elements_offset <= lelement_id + && lelement_id < tree->elements_offset + (t8_locidx_t) t8_element_array_get_count (&tree->elements)) { + return t8_element_array_index_locidx_mutable (&tree->elements, lelement_id - tree->elements_offset); + } + /* The element was not found. + * This case is covered by the first if and should therefore never happen. */ + SC_ABORT_NOT_REACHED (); + return NULL; +} + +const t8_element_t * +t8_forest_get_element_in_tree (t8_forest_t forest, t8_locidx_t ltreeid, t8_locidx_t leid_in_tree) +{ + t8_tree_t tree; + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (0 <= ltreeid && ltreeid < t8_forest_get_num_local_trees (forest)); + + tree = t8_forest_get_tree (forest, ltreeid); + const t8_element_t *element = t8_forest_get_tree_element (tree, leid_in_tree); + T8_ASSERT (t8_forest_element_is_leaf (forest, element, ltreeid)); + return element; +} + +t8_locidx_t +t8_forest_get_tree_element_offset (const t8_forest_t forest, const t8_locidx_t ltreeid) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + + return t8_forest_get_tree (forest, ltreeid)->elements_offset; +} + +t8_locidx_t +t8_forest_get_tree_element_count (t8_tree_t tree) +{ + t8_locidx_t element_count; + + T8_ASSERT (tree != NULL); + element_count = t8_element_array_get_count (&tree->elements); + /* check for type conversion errors */ + T8_ASSERT ((size_t) element_count == t8_element_array_get_count (&tree->elements)); + return element_count; +} + +t8_locidx_t +t8_forest_get_tree_num_elements (t8_forest_t forest, t8_locidx_t ltreeid) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (0 <= ltreeid && ltreeid < t8_forest_get_num_local_trees (forest)); + + return t8_forest_get_tree_element_count (t8_forest_get_tree (forest, ltreeid)); +} + +t8_eclass_t +t8_forest_get_tree_class (const t8_forest_t forest, const t8_locidx_t ltreeid) +{ + t8_locidx_t num_local_trees = t8_forest_get_num_local_trees (forest); + + T8_ASSERT (0 <= ltreeid && ltreeid < num_local_trees + t8_forest_get_num_ghost_trees (forest)); + if (ltreeid < num_local_trees) { + /* The id belongs to a local tree */ + return t8_forest_get_tree (forest, ltreeid)->eclass; + } + else { + /* The id belongs to a ghost tree */ + return t8_forest_ghost_get_tree_class (forest, ltreeid - num_local_trees); + } +} + +/* Return the global index of the first local element */ +t8_gloidx_t +t8_forest_get_first_local_element_id (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + + if (forest->element_offsets != NULL) { + return t8_shmem_array_get_gloidx (forest->element_offsets, forest->mpirank); + } + return -1; +} + +t8_scheme_cxx_t * +t8_forest_get_scheme (const t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->scheme_cxx != NULL); + + return forest->scheme_cxx; +} + +t8_eclass_scheme_c * +t8_forest_get_eclass_scheme (const t8_forest_t forest, const t8_eclass_t eclass) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->scheme_cxx != NULL); + T8_ASSERT (eclass != T8_ECLASS_COUNT); + + return forest->scheme_cxx->eclass_schemes[eclass]; +} + +t8_eclass_scheme_c * +t8_forest_get_eclass_scheme_before_commit (t8_forest_t forest, t8_eclass_t eclass) +{ + T8_ASSERT (t8_forest_is_initialized (forest)); + T8_ASSERT (forest->scheme_cxx != NULL); + T8_ASSERT (eclass != T8_ECLASS_COUNT); + + return forest->scheme_cxx->eclass_schemes[eclass]; +} + +t8_eclass_t +t8_forest_get_eclass (const t8_forest_t forest, const t8_locidx_t ltreeid) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + return t8_forest_get_tree (forest, ltreeid)->eclass; +} + +t8_locidx_t +t8_forest_get_local_id (const t8_forest_t forest, const t8_gloidx_t gtreeid) +{ + t8_gloidx_t ltreeid; + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (0 <= gtreeid && gtreeid < t8_forest_get_num_global_trees (forest)); + + /* If the tree is local then its local id is the global id minus the + * first global tree id on this forest. If this number is not in the + * range of local tree ids then the tree is not local. */ + /* we use a gloidx for ltreeid to prevent overflow and false positives */ + ltreeid = gtreeid - t8_forest_get_first_local_tree_id (forest); + /* Check if this tree is a local tree and if so return its local id */ + if (0 <= ltreeid && ltreeid < t8_forest_get_num_local_trees (forest)) { + return ltreeid; + } + else { + return -1; + } +} +t8_locidx_t +t8_forest_get_local_or_ghost_id (const t8_forest_t forest, const t8_gloidx_t gtreeid) +{ + t8_gloidx_t ltreeid; + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (0 <= gtreeid && gtreeid < t8_forest_get_num_global_trees (forest)); + + /* If the tree is local then its local id is the global id minus the + * first global tree id on this forest. If this number is not in the + * range of local tree ids then the tree is not local. */ + /* we use a gloidx for ltreeid to prevent overflow and false positives */ + ltreeid = gtreeid - t8_forest_get_first_local_tree_id (forest); + /* Check if this tree is a local tree and if so return its local id */ + if (0 <= ltreeid && ltreeid < t8_forest_get_num_local_trees (forest)) { + return ltreeid; + } + else { + t8_locidx_t ghost_id = t8_forest_ghost_get_ghost_treeid (forest, gtreeid); + if (ghost_id >= 0) + return t8_forest_get_num_local_trees (forest) + ghost_id; + return -1; + } +} + +t8_locidx_t +t8_forest_ltreeid_to_cmesh_ltreeid (t8_forest_t forest, t8_locidx_t ltreeid) +{ + t8_gloidx_t cmesh_gfirst; + t8_locidx_t num_local_trees; + + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->cmesh != NULL); + num_local_trees = t8_forest_get_num_local_trees (forest); + T8_ASSERT (0 <= ltreeid && ltreeid < num_local_trees + t8_forest_ghost_num_trees (forest)); + + if (ltreeid < num_local_trees) { + /* This a local tree and not a ghost */ + + cmesh_gfirst = t8_cmesh_get_first_treeid (forest->cmesh); + return forest->first_local_tree - cmesh_gfirst + ltreeid; + } + else { + /* This is a ghost */ + t8_gloidx_t globalid; + t8_locidx_t cmesh_local_id; + /* Compute the global id of this ghost tree */ + globalid = t8_forest_ghost_get_global_treeid (forest, ltreeid - num_local_trees); + /* Compute the cmesh local id of the ghost */ + cmesh_local_id = t8_cmesh_get_local_id (forest->cmesh, globalid); + /* is < 0 if this ghost does not exist */ + T8_ASSERT (cmesh_local_id >= 0); + return cmesh_local_id; + } +} + +t8_locidx_t +t8_forest_cmesh_ltreeid_to_ltreeid (t8_forest_t forest, t8_locidx_t lctreeid) +{ + t8_locidx_t ltreeid; + + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->cmesh != NULL); + + ltreeid = t8_cmesh_get_first_treeid (forest->cmesh) - t8_forest_get_first_local_tree_id (forest) + lctreeid; + if (0 <= ltreeid && ltreeid < t8_forest_get_num_local_trees (forest)) { + /* The tree is a forest local tree */ + return ltreeid; + } + else { + /* The tree is not forest local */ + return -1; + } +} + +t8_ctree_t +t8_forest_get_coarse_tree_ext (t8_forest_t forest, t8_locidx_t ltreeid, t8_locidx_t **face_neigh, int8_t **ttf) +{ + t8_locidx_t lctreeid; + + T8_ASSERT (t8_forest_is_committed (forest)); + + /* Compute the coarse tree's local id */ + lctreeid = t8_forest_ltreeid_to_cmesh_ltreeid (forest, ltreeid); + + return t8_cmesh_trees_get_tree_ext (forest->cmesh->trees, lctreeid, face_neigh, ttf); +} + +t8_ctree_t +t8_forest_get_coarse_tree (t8_forest_t forest, t8_locidx_t ltreeid) +{ + return t8_forest_get_coarse_tree_ext (forest, ltreeid, NULL, NULL); +} + +void +t8_forest_set_profiling (t8_forest_t forest, int set_profiling) +{ + T8_ASSERT (t8_forest_is_initialized (forest)); + + if (set_profiling) { + if (forest->profile == NULL) { + /* Only do something if profiling is not enabled already */ + forest->profile = T8_ALLOC_ZERO (t8_profile_struct_t, 1); + } + } + else { + /* Free any profile that is already set */ + if (forest->profile != NULL) { + T8_FREE (forest->profile); + } + } +} + +void +t8_forest_compute_profile (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + if (forest->profile != NULL) { + /* Only print something if profiling is enabled */ + t8_profile_t *profile = forest->profile; + + /* Set the stats */ + sc_stats_set1 (&forest->stats[0], profile->partition_elements_shipped, "forest: Number of elements sent."); + sc_stats_set1 (&forest->stats[1], profile->partition_elements_recv, "forest: Number of elements received."); + sc_stats_set1 (&forest->stats[2], profile->partition_bytes_sent, "forest: Number of bytes sent."); + sc_stats_set1 (&forest->stats[3], profile->partition_procs_sent, "forest: Number of processes sent to."); + sc_stats_set1 (&forest->stats[4], profile->ghosts_shipped, "forest: Number of ghost elements sent."); + sc_stats_set1 (&forest->stats[5], profile->ghosts_received, "forest: Number of ghost elements received."); + sc_stats_set1 (&forest->stats[6], profile->ghosts_remotes, + "forest: Number of processes we sent ghosts to/received from."); + sc_stats_set1 (&forest->stats[7], profile->adapt_runtime, "forest: Adapt runtime."); + sc_stats_set1 (&forest->stats[8], profile->partition_runtime, "forest: Partition runtime."); + sc_stats_set1 (&forest->stats[9], profile->commit_runtime, "forest: Commit runtime."); + sc_stats_set1 (&forest->stats[10], profile->ghost_runtime, "forest: Ghost runtime."); + sc_stats_set1 (&forest->stats[11], profile->ghost_waittime, "forest: Ghost waittime."); + sc_stats_set1 (&forest->stats[12], profile->balance_runtime, "forest: Balance runtime."); + sc_stats_set1 (&forest->stats[13], profile->balance_rounds, "forest: Balance rounds."); + /* compute stats */ + sc_stats_compute (sc_MPI_COMM_WORLD, T8_PROFILE_NUM_STATS, forest->stats); + forest->stats_computed = 1; + } +} + +void +t8_forest_print_profile (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + if (forest->profile != NULL) { + /* Compute the stats if not already computed. */ + if (!forest->stats_computed) { + t8_forest_compute_profile (forest); + } + /* print stats */ + t8_logf (SC_LC_GLOBAL, SC_LP_STATISTICS, "Printing stats for forest.\n"); + sc_stats_print (t8_get_package_id (), SC_LP_STATISTICS, T8_PROFILE_NUM_STATS, forest->stats, 1, 1); + } +} + +const sc_statinfo_t * +t8_forest_profile_get_adapt_stats (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->profile != NULL); + T8_ASSERT (forest->stats_computed); + return &forest->stats[7]; +} + +const sc_statinfo_t * +t8_forest_profile_get_ghost_stats (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->profile != NULL); + T8_ASSERT (forest->stats_computed); + return &forest->stats[10]; +} + +const sc_statinfo_t * +t8_forest_profile_get_partition_stats (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->profile != NULL); + T8_ASSERT (forest->stats_computed); + return &forest->stats[8]; +} + +const sc_statinfo_t * +t8_forest_profile_get_commit_stats (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->profile != NULL); + T8_ASSERT (forest->stats_computed); + return &forest->stats[9]; +} + +const sc_statinfo_t * +t8_forest_profile_get_balance_stats (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->profile != NULL); + T8_ASSERT (forest->stats_computed); + return &forest->stats[12]; +} + +const sc_statinfo_t * +t8_forest_profile_get_balance_rounds_stats (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + T8_ASSERT (forest->profile != NULL); + T8_ASSERT (forest->stats_computed); + return &forest->stats[13]; +} + +double +t8_forest_profile_get_adapt_time (t8_forest_t forest) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + if (forest->profile != NULL) { + return forest->profile->adapt_runtime; + } + return 0; +} + +double +t8_forest_profile_get_partition_time (t8_forest_t forest, int *procs_sent) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + if (forest->profile != NULL) { + *procs_sent = forest->profile->partition_procs_sent; + return forest->profile->partition_runtime; + } + return 0; +} + +double +t8_forest_profile_get_balance_time (t8_forest_t forest, int *balance_rounds) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + if (forest->profile != NULL) { + *balance_rounds = forest->profile->balance_rounds; + return forest->profile->balance_runtime; + } + return 0; +} + +double +t8_forest_profile_get_ghost_time (t8_forest_t forest, t8_locidx_t *ghosts_sent) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + if (forest->profile != NULL) { + *ghosts_sent = forest->profile->ghosts_shipped; + return forest->profile->ghost_runtime; + } + *ghosts_sent = 0; + return 0; +} + +double +t8_forest_profile_get_ghostexchange_waittime (t8_forest_t forest) +{ + + T8_ASSERT (t8_forest_is_committed (forest)); + if (forest->profile != NULL) { + return forest->profile->ghost_waittime; + } + return 0; +} + +double +t8_forest_profile_get_balance (t8_forest_t forest, int *balance_rounds) +{ + T8_ASSERT (t8_forest_is_committed (forest)); + if (forest->profile != NULL) { + *balance_rounds = forest->profile->balance_rounds; + return forest->profile->balance_runtime; + } + return 0; +} + +void +t8_forest_compute_elements_offset (t8_forest_t forest) +{ + + t8_locidx_t itree, num_trees; + t8_locidx_t current_offset; + t8_tree_t tree; + + T8_ASSERT (t8_forest_is_initialized (forest)); + + /* Get the number of local trees */ + num_trees = t8_forest_get_num_local_trees (forest); + + current_offset = 0; + /* Iterate through all trees, sum up the element counts and set it as + * the element_offsets */ + for (itree = 0; itree < num_trees; itree++) { + tree = t8_forest_get_tree (forest, itree); + tree->elements_offset = current_offset; + current_offset += t8_forest_get_tree_element_count (tree); + } + /* At the end, we counted all elements */ + T8_ASSERT (current_offset == forest->local_num_elements); +} + +int +t8_forest_write_vtk_ext (t8_forest_t forest, const char *fileprefix, const int write_treeid, const int write_mpirank, + const int write_level, const int write_element_id, const int write_ghosts, + const int write_curved, int do_not_use_API, const int num_data, t8_vtk_data_field_t *data) +{ + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (forest->committed); + +#if T8_WITH_VTK + if (do_not_use_API && write_curved) { + t8_errorf ("WARNING: Export of curved elements not yet available with the inbuild function. " + "Using the VTK API instead.\n"); + do_not_use_API = 0; + } +#else + /* We are not linked against the VTK library, so + * we do not use the API by default. + */ + if (write_curved) { + t8_errorf ("WARNING: Export of curved elements not yet available with the inbuild function. " + "Please link to VTK.\n" + "Using the inbuild function to write out uncurved elements instead.\n"); + } + do_not_use_API = 1; +#endif + if (!do_not_use_API) { + return t8_forest_vtk_write_file_via_API (forest, fileprefix, write_treeid, write_mpirank, write_level, + write_element_id, write_ghosts, write_curved, num_data, data); + } + else { + T8_ASSERT (!write_curved); + return t8_forest_vtk_write_file (forest, fileprefix, write_treeid, write_mpirank, write_level, write_element_id, + write_ghosts, num_data, data); + } +} + +int +t8_forest_write_vtk (t8_forest_t forest, const char *fileprefix) +{ + return t8_forest_write_vtk_ext (forest, fileprefix, 1, 1, 1, 1, 0, 0, 0, 0, NULL); +} + +t8_forest_t +t8_forest_new_uniform (t8_cmesh_t cmesh, t8_scheme_cxx_t *scheme, const int level, const int do_face_ghost, + sc_MPI_Comm comm) +{ + t8_forest_t forest; + + T8_ASSERT (t8_cmesh_is_committed (cmesh)); + T8_ASSERT (scheme != NULL); + T8_ASSERT (0 <= level); + + /* Initialize the forest */ + t8_forest_init (&forest); + T8_ASSERT (t8_forest_is_initialized (forest)); + /* Set the cmesh, scheme and level */ + t8_forest_set_cmesh (forest, cmesh, comm); + t8_forest_set_scheme (forest, scheme); + t8_forest_set_level (forest, level); + if (do_face_ghost) { + t8_forest_set_ghost (forest, 1, T8_GHOST_FACES); + } + /* commit the forest */ + t8_forest_commit (forest); + t8_global_productionf ("Constructed uniform forest with %lli global elements.\n", + (long long) forest->global_num_elements); + + return forest; +} + +t8_forest_t +t8_forest_new_adapt (t8_forest_t forest_from, t8_forest_adapt_t adapt_fn, int recursive, int do_face_ghost, + void *user_data) +{ + t8_forest_t forest; + + t8_forest_init (&forest); + t8_forest_set_adapt (forest, forest_from, adapt_fn, recursive); + t8_forest_set_ghost (forest, do_face_ghost, T8_GHOST_FACES); + if (user_data != NULL) { + t8_forest_set_user_data (forest, user_data); + } + t8_forest_commit (forest); + return forest; +} + +/* Iterate through all the trees and free the element memory as well as + * the tree memory. + */ +static void +t8_forest_free_trees (t8_forest_t forest) +{ + t8_tree_t tree; + t8_locidx_t jt, number_of_trees; + + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->committed); + + number_of_trees = forest->trees->elem_count; + for (jt = 0; jt < number_of_trees; jt++) { + tree = (t8_tree_t) t8_sc_array_index_locidx (forest->trees, jt); + + if (t8_forest_get_tree_element_count (tree) < 1) { + /* if local tree is empty */ + T8_ASSERT (forest->incomplete_trees); + continue; + } + t8_element_array_reset (&tree->elements); + /* destroy first and last descendant */ + const t8_eclass_t eclass = t8_forest_get_tree_class (forest, jt); + const t8_eclass_scheme_c *scheme = forest->scheme_cxx->eclass_schemes[eclass]; + t8_element_destroy (scheme, 1, &tree->first_desc); + t8_element_destroy (scheme, 1, &tree->last_desc); + } + sc_array_destroy (forest->trees); +} + +/* Completely destroy a forest and unreference all structs that the + * forest has taken ownership on. + */ +static void +t8_forest_reset (t8_forest_t *pforest) +{ + int mpiret; + t8_forest_t forest; + + T8_ASSERT (pforest != NULL); + forest = *pforest; + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount == 0); + + if (!forest->committed) { + if (forest->set_from != NULL) { + /* in this case we have taken ownership and not released it yet */ + t8_forest_unref (&forest->set_from); + } + } + else { + T8_ASSERT (forest->set_from == NULL); + } + + /* undup communicator if necessary */ + if (forest->committed) { + if (forest->do_dup) { + mpiret = sc_MPI_Comm_free (&forest->mpicomm); + SC_CHECK_MPI (mpiret); + } + t8_forest_free_trees (forest); + } + + /* Destroy the ghost layer if it exists */ + if (forest->ghosts != NULL) { + t8_forest_ghost_unref (&forest->ghosts); + } + /* we have taken ownership on calling t8_forest_set_* */ + if (forest->scheme_cxx != NULL) { + t8_scheme_cxx_unref (&forest->scheme_cxx); + } + if (forest->cmesh != NULL) { + t8_cmesh_unref (&forest->cmesh); + } + + /* free the memory of the offset array */ + if (forest->element_offsets != NULL) { + t8_shmem_array_destroy (&forest->element_offsets); + } + /* free the memory of the global_first_desc array */ + if (forest->global_first_desc != NULL) { + t8_shmem_array_destroy (&forest->global_first_desc); + } + /* free the memory of the tree_offsets array */ + if (forest->tree_offsets != NULL) { + t8_shmem_array_destroy (&forest->tree_offsets); + } + if (forest->profile != NULL) { + T8_FREE (forest->profile); + } + T8_FREE (forest); + *pforest = NULL; +} + +void +t8_forest_ref (t8_forest_t forest) +{ + T8_ASSERT (forest != NULL); + t8_refcount_ref (&forest->rc); +} + +void +t8_forest_unref (t8_forest_t *pforest) +{ + t8_forest_t forest; + + T8_ASSERT (pforest != NULL); + forest = *pforest; + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (forest != NULL); + if (t8_refcount_unref (&forest->rc)) { + t8_forest_reset (pforest); + } +} + T8_EXTERN_C_END (); From 88eafc3d1b54f46666ed95976228396187a09e7b Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 22 Jul 2024 16:20:04 +0200 Subject: [PATCH 40/55] fix merge gone wrong --- src/t8_forest/t8_forest.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/t8_forest/t8_forest.cxx b/src/t8_forest/t8_forest.cxx index 74540418ad..b92d1115bb 100644 --- a/src/t8_forest/t8_forest.cxx +++ b/src/t8_forest/t8_forest.cxx @@ -3331,6 +3331,12 @@ t8_forest_is_initialized (t8_forest_t forest) return forest != NULL && t8_refcount_is_active (&forest->rc) && !forest->committed; } +int +t8_forest_is_committed (const t8_forest_t forest) +{ + return forest != NULL && t8_refcount_is_active (&forest->rc) && forest->committed; +} + /** Check whether at least one eclass scheme of forest supports transitioning * \param [in] forest A forest */ @@ -3361,9 +3367,6 @@ t8_forest_supports_transitioning (t8_forest_t forest) return supports_transition_all_procs; } -int - return forest != NULL && t8_refcount_is_active (&forest->rc) && forest->committed; -} static void t8_forest_set_mpicomm (t8_forest_t forest, sc_MPI_Comm mpicomm, int do_dup) From c33bbf33616f35e8daf402918cc17e6b2ae7a597 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 22 Jul 2024 16:34:30 +0200 Subject: [PATCH 41/55] finish merge - adapt to new file names --- src/CMakeLists.txt | 1 + src/t8_forest/t8_forest_transition.cxx | 2 +- .../t8_transition_conformal_hex_cxx.hxx | 6 +++--- .../t8_transition_conformal_quad_cxx.hxx | 8 ++++---- src/t8_schemes/t8_transition/t8_transition_cxx.hxx | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0dcea760ef..ce6bfd55c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -111,6 +111,7 @@ target_sources( T8 PRIVATE t8_forest/t8_forest_iterate.cxx t8_forest/t8_forest_balance.cxx t8_forest/t8_forest_netcdf.cxx + t8_forest/t8_forest_transition.cxx t8_geometry/t8_geometry.cxx t8_geometry/t8_geometry_helpers.c t8_geometry/t8_geometry_base.cxx diff --git a/src/t8_forest/t8_forest_transition.cxx b/src/t8_forest/t8_forest_transition.cxx index 77dfa5ee0c..cd2080024e 100644 --- a/src/t8_forest/t8_forest_transition.cxx +++ b/src/t8_forest/t8_forest_transition.cxx @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 58145fcd28..a790e44c45 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -34,10 +34,10 @@ #define T8_TRANSITION_CONFORMAL_HEX_CXX_HXX #include -#include +#include -#include -#include +#include +#include #include diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index b47496af7b..93cf99912a 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -34,13 +34,13 @@ #define T8_TRANSITION_CONFORMAL_QUAD_CXX_HXX #include -#include +#include #include -#include -#include -#include +#include +#include +#include /** The structure holding a quadrilateral element in the default scheme. * We make this definition public for interoperability of element classes. diff --git a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx index a73a2bceef..34c9d29b85 100644 --- a/src/t8_schemes/t8_transition/t8_transition_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_cxx.hxx @@ -28,7 +28,7 @@ #ifndef T8_TRANSITION_CXX_HXX #define T8_TRANSITION_CXX_HXX -#include +#include /* This is the unique identifier for the transition function. */ From f2527dd8484df2d17db665e4c2daf054f65b9962 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 22 Jul 2024 16:34:30 +0200 Subject: [PATCH 42/55] Update CMakelists --- src/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ce6bfd55c4..ad5e732208 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -145,6 +145,10 @@ target_sources( T8 PRIVATE t8_schemes/t8_default/t8_default_tri/t8_dtri_connectivity.c t8_schemes/t8_default/t8_default_vertex/t8_default_vertex.cxx t8_schemes/t8_default/t8_default_vertex/t8_dvertex_bits.c + t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx + t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx + t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx + t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx t8_vtk/t8_vtk_polydata.cxx t8_vtk/t8_vtk_unstructured.cxx t8_vtk/t8_vtk_parallel.cxx From e5c0720af00aafa9521129685b24a729690f64ab Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Tue, 23 Jul 2024 12:15:06 +0200 Subject: [PATCH 43/55] update changed header file names --- .../t8_transition_conformal_hex.cxx | 12 ++++++------ .../t8_transition_conformal_hex_cxx.cxx | 2 +- .../t8_transition_conformal_quad.cxx | 4 ++-- .../t8_transition_conformal_quad_cxx.cxx | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx index c44ef70da5..f3005111d8 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex.cxx @@ -21,13 +21,13 @@ */ #include -#include +#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index daa738414e..4b9969cc31 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include "t8_transition_conformal_hex_cxx.hxx" #include diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx index 709983ac65..bfd482c488 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad.cxx @@ -24,8 +24,8 @@ #include #include -#include -#include +#include +#include #include diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index edc1a4e7a8..021354e61c 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -25,8 +25,8 @@ #include #include -#include -#include +#include +#include #include #include "t8.h" #include "t8_transition_conformal_quad_cxx.hxx" From b5a5dc4b2c7b4d685831d24b627c7ccb754fa43c Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Wed, 24 Jul 2024 16:41:34 +0200 Subject: [PATCH 44/55] fix memory bug because of wrong element size computation --- .../t8_transition_conformal_quad_cxx.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index 021354e61c..bb7910dd01 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -2350,7 +2350,7 @@ t8_subelement_scheme_quad_c::t8_element_to_string (const t8_element_t *elem, cha t8_subelement_scheme_quad_c::t8_subelement_scheme_quad_c (void) { eclass = T8_ECLASS_QUAD; - element_size = sizeof (t8_pquad_t); + element_size = sizeof (t8_quad_with_subelements); ts_context = sc_mempool_new (element_size); } From 2680045791f3b71d6ec1013caba826e886fd9363 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Wed, 24 Jul 2024 16:55:00 +0200 Subject: [PATCH 45/55] extend t8_element_reference_coords for multiple coordinates --- .../t8_transition_conformal_quad_cxx.cxx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index bb7910dd01..6d830560be 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -1374,7 +1374,6 @@ t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *el { T8_ASSERT (ref_coords != NULL); T8_ASSERT (out_coords != NULL); - T8_ASSERT (num_coords == 2); T8_ASSERT (t8_element_is_valid (elem)); static struct t8_default_scheme_quad_c default_quad_scheme; @@ -1401,14 +1400,21 @@ t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *el * * After that we use t8_geom_triangular_interpolation to compute the actual value. */ - const double barycentric_coeff[3] = {0, ref_coords[0] - ref_coords[1], ref_coords[1]}; constexpr int num_vertices = 3; // Should use t8_eclass_num_vertices[T8_ECLASS_TRIANGLE]; but is not constexpr constexpr int num_vertex_coords = num_vertices * 3; double vertex_coords[num_vertex_coords]; // Stores the triangle's vertices for (int ivertex = 0;ivertex < num_vertices;++ivertex) { t8_element_vertex_reference_coords (elem, ivertex, vertex_coords + 3*ivertex); } - t8_geom_triangular_interpolation (barycentric_coeff, vertex_coords, 3, 2, out_coords); + constexpr int dim = 2; + constexpr int dim_out = 3; + // For each incoming coordinate compute the barycentric coordinates and do the interpolation + for (int i = 0;i < num_coords;++i) { + const double ref_x = ref_coords[0 + dim * num_coords]; + const double ref_y = ref_coords[1 + dim * num_coords]; + const double barycentric_coeff[3] = {0, ref_x - ref_y, ref_y}; + t8_geom_triangular_interpolation (barycentric_coeff, vertex_coords, 3, 2, out_coords + i * dim_out); + } } } From a1e3919ba0640d4f0ca73847221c38719e845ae3 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 5 Aug 2024 12:54:00 +0200 Subject: [PATCH 46/55] fix coordinate computation - ref_coords always 3 dim --- .../t8_transition_conformal_quad_cxx.cxx | 19 +++++---- .../t8_transition_conformal_quad_cxx.hxx | 40 ++++--------------- 2 files changed, 18 insertions(+), 41 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index 6d830560be..eec0135609 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "t8.h" #include "t8_transition_conformal_quad_cxx.hxx" @@ -1368,14 +1367,15 @@ t8_subelement_scheme_quad_c::t8_element_vertex_integer_coords (const t8_element_ { SC_ABORT ("This function is not implemented for the given scheme.\n"); } + void t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) const { + T8_ASSERT (num_coords > 0); T8_ASSERT (ref_coords != NULL); T8_ASSERT (out_coords != NULL); T8_ASSERT (t8_element_is_valid (elem)); - static struct t8_default_scheme_quad_c default_quad_scheme; const t8_quad_with_subelements *element = (t8_quad_with_subelements *) elem; if (!t8_element_is_subelement (elem)) { @@ -1406,14 +1406,17 @@ t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *el for (int ivertex = 0;ivertex < num_vertices;++ivertex) { t8_element_vertex_reference_coords (elem, ivertex, vertex_coords + 3*ivertex); } - constexpr int dim = 2; - constexpr int dim_out = 3; + // For each incoming coordinate compute the barycentric coordinates and do the interpolation - for (int i = 0;i < num_coords;++i) { - const double ref_x = ref_coords[0 + dim * num_coords]; - const double ref_y = ref_coords[1 + dim * num_coords]; + for (size_t icoord = 0;icoord < num_coords;++icoord) { + // The ref_coords are always 3 dimensional - even though we do not use the 3rd entry. + // The out_coords are 2 dimensional. + const int offset_3d = icoord * 3; // offset for 3 dim ref_coords when iterating over points + const int offset_2d = icoord * 2; // offset for 2 dim out_coords when iterating over points + const double ref_x = ref_coords[0 + offset_3d]; + const double ref_y = ref_coords[1 + offset_3d]; const double barycentric_coeff[3] = {0, ref_x - ref_y, ref_y}; - t8_geom_triangular_interpolation (barycentric_coeff, vertex_coords, 3, 2, out_coords + i * dim_out); + t8_geom_triangular_interpolation (barycentric_coeff, vertex_coords, 3, 2, out_coords + offset_2d); } } } diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index 93cf99912a..e4b03eb49b 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -41,6 +41,7 @@ #include #include #include +#include /** The structure holding a quadrilateral element in the default scheme. * We make this definition public for interoperability of element classes. @@ -83,39 +84,6 @@ typedef struct #define T8_QUAD_TRANSITION_IS_IMPLEMENTED 1 #define T8_QUAD_TRANSITION_SCHEME_IS_CONFORMAL 1 -/** Return the toplevel dimension. */ -#define T8_QUAD_GET_TDIM(quad) ((int) (quad)->pad8) - -/** Return the direction of the third dimension. - * This is only valid to call if the toplevel dimension is three. - */ -#define T8_QUAD_GET_TNORMAL(quad) (T8_ASSERT (T8_QUAD_GET_TDIM (quad) == 3), ((int) (quad)->pad16)) - -/** Return the coordinate in the third dimension. - * This is only valid to call if the toplevel dimension is three. - */ -#define T8_QUAD_GET_TCOORD(quad) (T8_ASSERT (T8_QUAD_GET_TDIM (quad) == 3), ((int) (quad)->p.user_long)) - -/** Set the toplevel dimension of a quadrilateral. */ -#define T8_QUAD_SET_TDIM(quad, dim) \ - do { \ - T8_ASSERT ((dim) == 2 || (dim) == 3); \ - (quad)->pad8 = (int8_t) (dim); \ - } while (0) - -/** Set the direction of the third dimension. */ -#define T8_QUAD_SET_TNORMAL(quad, normal) \ - do { \ - T8_ASSERT ((normal) >= 0 && (normal) < 3); \ - (quad)->pad16 = (int16_t) (normal); \ - } while (0) - -/** Set the coordinate in the third dimension. */ -#define T8_QUAD_SET_TCOORD(quad, coord) \ - do { \ - (quad)->p.user_long = (long) (coord); \ - } while (0) - #if 0 /** Provide an implementation for the quadrilateral element class with subelements. */ t8_eclass_scheme_t *t8_subelement_scheme_new_quad (void); @@ -574,6 +542,12 @@ struct t8_subelement_scheme_quad_c: public t8_default_scheme_common_c int t8_element_subelement_values_are_valid (const t8_element_t *elem) const; #endif + + /** Default quad scheme which is used to query quad specific computations, + * for example in \ref t8_element_reference_coords + */ + struct t8_default_scheme_quad_c default_quad_scheme; }; #endif /* !T8_TRANSITION_QUAD_CXX_HXX */ + From c698527045b0f6685b2b42d6333ff5210c943b5d Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 5 Aug 2024 12:55:01 +0200 Subject: [PATCH 47/55] fix transition quad init --- .../t8_transition_conformal_quad_cxx.cxx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index eec0135609..66dfa155ee 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -2197,11 +2197,9 @@ t8_subelement_scheme_quad_c::t8_element_init (int length, t8_element_t *elem) co * set their quad to the level 0 quad with ID 0. */ p4est_quadrant_t *quad = &pquad_w_sub[elem_count].p4q; /* Set all values to 0 */ - for (int i = 0; i < length; i++) { - p4est_quadrant_set_morton (quad + i, 0, 0); - T8_QUAD_SET_TDIM (quad + i, 2); - T8_ASSERT (p4est_quadrant_is_extended (quad + i)); - } + p4est_quadrant_set_morton (quad, 0, 0); + T8_QUAD_SET_TDIM (quad, 2); + T8_ASSERT (p4est_quadrant_is_extended (quad)); #endif } } From 15bd1b2134ce58b9e4ad527ecfb580ab904f6fc3 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 5 Aug 2024 12:55:47 +0200 Subject: [PATCH 48/55] fix transition hex last desc --- .../t8_transition_conformal_hex_cxx.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 4b9969cc31..04f2e006f1 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1064,8 +1064,7 @@ t8_subelement_scheme_hex_c::t8_element_last_descendant (const t8_element_t *elem T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (t8_element_is_valid (desc)); T8_ASSERT (0 <= level && level <= P8EST_OLD_QMAXLEVEL); - // p8est_quadrant_last_descendant (q, r, level); - p8est_quadrant_last_descendant ((p8est_quadrant_t *) elem, (p8est_quadrant_t *) desc, level); + p8est_quadrant_last_descendant (q, r, level); /* We allow constructing a last descendant from a subelement. * Keep in mind, that transforming a hex element to a subelement does not change the From 6f0c735ba394deed53e7c18849be6869d189eb5f Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 5 Aug 2024 12:56:10 +0200 Subject: [PATCH 49/55] clean up transition hex --- .../t8_transition_conformal_hex_cxx.cxx | 4 +-- .../t8_transition_conformal_hex_cxx.hxx | 34 +------------------ 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 04f2e006f1..3abe2e0dc7 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -1746,7 +1746,7 @@ t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *ele int location[3] = {}; t8_element_get_location_of_subelement (elem, location); - for (int coord = 0; coord < num_coords; ++coord) { + for (size_t coord = 0; coord < num_coords; ++coord) { const size_t offset = coord * 3; out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; @@ -2364,7 +2364,7 @@ t8_subelement_scheme_hex_c::t8_element_get_location_of_subelement (const t8_elem * * These information are then saved in the location array which will be used by the element_vertex function, * to automatically determine the vertex coordinates of the given subelement. - * + */ /* 1) convert the transition type from a decimal to a binary representation */ int type = phex_w_sub->transition_type; diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index a790e44c45..592f699194 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -38,6 +38,7 @@ #include #include +#include #include @@ -88,39 +89,6 @@ typedef t8_hex_with_subelements t8_phex_sub_t; #define T8_HEX_TRANSITION_IS_IMPLEMENTED 1 #define T8_HEX_TRANSITION_SCHEME_IS_CONFORMAL 1 -/** Return the toplevel dimension. */ -// #define T8_QUAD_GET_TDIM(quad) ((int) (quad)->pad8) - -/** Return the direction of the third dimension. - * This is only valid to call if the toplevel dimension is three. - */ -// #define T8_QUAD_GET_TNORMAL(quad) \ -// ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ -// ((int) (quad)->pad16) ) - -/** Return the coordinate in the third dimension. - * This is only valid to call if the toplevel dimension is three. - */ -// #define T8_QUAD_GET_TCOORD(quad) \ -// ( T8_ASSERT (T8_QUAD_GET_TDIM(quad) == 3), \ -// ((int) (quad)->p.user_long) ) - -/** Set the toplevel dimension of a hexahedron. */ -#define T8_QUAD_SET_TDIM(quad, dim) \ - do { \ - T8_ASSERT ((dim) == 2 || (dim) == 3); \ - (quad)->pad8 = (int8_t) (dim); \ - } while (0) - -// /** Set the direction of the third dimension. */ -// #define T8_QUAD_SET_TNORMAL(quad,normal) \ -// do { T8_ASSERT ((normal) >= 0 && (normal) < 3); \ -// (quad)->pad16 = (int16_t) (normal); } while (0) - -// /** Set the coordinate in the third dimension. */ -// #define T8_QUAD_SET_TCOORD(quad,coord) \ -// do { (quad)->p.user_long = (long) (coord); } while (0) - #if 0 /** Provide an implementation for the hexahedral element class with subelements. */ t8_eclass_scheme_t *t8_subelement_scheme_new_hex (void); From 51b6c2bff2811bfc64e587e7229b4e4e847cb7c9 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Mon, 5 Aug 2024 12:59:04 +0200 Subject: [PATCH 50/55] indent --- .../t8_transition_conformal_quad_cxx.cxx | 16 ++++++++-------- .../t8_transition_conformal_quad_cxx.hxx | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index 66dfa155ee..917b0c59ec 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -1379,7 +1379,7 @@ t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *el const t8_quad_with_subelements *element = (t8_quad_with_subelements *) elem; if (!t8_element_is_subelement (elem)) { - const t8_element_t * quad = (const t8_element_t *)&element->p4q; + const t8_element_t *quad = (const t8_element_t *) &element->p4q; // We call the default quad reference coord function for the quad coordinates. // We could think about doing this in more cases. For that it would // be beneficial to store a t8_default_scheme_quad_c pointer as member variable @@ -1402,20 +1402,20 @@ t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *el */ constexpr int num_vertices = 3; // Should use t8_eclass_num_vertices[T8_ECLASS_TRIANGLE]; but is not constexpr constexpr int num_vertex_coords = num_vertices * 3; - double vertex_coords[num_vertex_coords]; // Stores the triangle's vertices - for (int ivertex = 0;ivertex < num_vertices;++ivertex) { - t8_element_vertex_reference_coords (elem, ivertex, vertex_coords + 3*ivertex); + double vertex_coords[num_vertex_coords]; // Stores the triangle's vertices + for (int ivertex = 0; ivertex < num_vertices; ++ivertex) { + t8_element_vertex_reference_coords (elem, ivertex, vertex_coords + 3 * ivertex); } // For each incoming coordinate compute the barycentric coordinates and do the interpolation - for (size_t icoord = 0;icoord < num_coords;++icoord) { + for (size_t icoord = 0; icoord < num_coords; ++icoord) { // The ref_coords are always 3 dimensional - even though we do not use the 3rd entry. // The out_coords are 2 dimensional. - const int offset_3d = icoord * 3; // offset for 3 dim ref_coords when iterating over points - const int offset_2d = icoord * 2; // offset for 2 dim out_coords when iterating over points + const int offset_3d = icoord * 3; // offset for 3 dim ref_coords when iterating over points + const int offset_2d = icoord * 2; // offset for 2 dim out_coords when iterating over points const double ref_x = ref_coords[0 + offset_3d]; const double ref_y = ref_coords[1 + offset_3d]; - const double barycentric_coeff[3] = {0, ref_x - ref_y, ref_y}; + const double barycentric_coeff[3] = { 0, ref_x - ref_y, ref_y }; t8_geom_triangular_interpolation (barycentric_coeff, vertex_coords, 3, 2, out_coords + offset_2d); } } diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index e4b03eb49b..840fb9a009 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -550,4 +550,3 @@ struct t8_subelement_scheme_quad_c: public t8_default_scheme_common_c }; #endif /* !T8_TRANSITION_QUAD_CXX_HXX */ - From c097d71061061bfcd1d8dc4447b8e8488284afe7 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Tue, 6 Aug 2024 11:44:55 +0200 Subject: [PATCH 51/55] Introduce int typedef for coordinates of quad subelements --- .../t8_transition_conformal_quad_cxx.cxx | 5 +++-- .../t8_transition_conformal_quad_cxx.hxx | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index 917b0c59ec..7fdb286b9c 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -1435,7 +1435,8 @@ t8_subelement_scheme_quad_c::t8_element_vertex_reference_coords (const t8_elemen } void -t8_subelement_scheme_quad_c::t8_element_vertex_coords (const t8_element_t *elem, int vertex, int coords[]) const +t8_subelement_scheme_quad_c::t8_element_vertex_coords (const t8_element_t *elem, int vertex, + t8_dquad_subelement_coord_t coords[]) const { const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q1 = &pquad_w_sub->p4q; @@ -1461,7 +1462,7 @@ t8_subelement_scheme_quad_c::t8_element_vertex_coords (const t8_element_t *elem, void t8_subelement_scheme_quad_c::t8_element_vertex_coords_of_subelement (const t8_element_t *elem, int vertex, - int coords[]) const + t8_dquad_subelement_coord_t coords[]) const { const t8_quad_with_subelements *pquad_w_sub = (const t8_quad_with_subelements *) elem; const p4est_quadrant_t *q1 = &pquad_w_sub->p4q; diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx index 840fb9a009..578b4ca637 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.hxx @@ -66,6 +66,9 @@ * Each transition cell consists of different subelements. The given example consists of 6 different subelements, whose ids range from 0 to 5. * A dummy variable will store the information, whether a given element is a subelement or a standard quad element. */ +/** Variable type for an integer valued coordinate of a quad (sub-)element. */ +typedef p4est_qcoord_t t8_dquad_subelement_coord_t; + typedef struct { /* p4est quadrant */ @@ -317,7 +320,8 @@ struct t8_subelement_scheme_quad_c: public t8_default_scheme_common_c /** Compute the integer coordinates of a given element vertex. */ virtual void - t8_element_vertex_coords (const t8_element_t *t, int vertex, int coords[]) const; + t8_element_vertex_coords (const t8_element_t *t, int vertex, t8_dquad_subelement_coord_t coords[]) const; + /** Compute the integer coordinates of a given element vertex. * The default scheme implements the Morton type SFCs. In these SFCs the * elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and @@ -329,7 +333,7 @@ struct t8_subelement_scheme_quad_c: public t8_default_scheme_common_c * whose entries will be filled with the coordinates of \a vertex. */ virtual void - t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, int coords[]) const; + t8_element_vertex_integer_coords (const t8_element_t *elem, int vertex, t8_dquad_subelement_coord_t coords[]) const; /** Convert a point in the reference space of an element to a point in the * reference space of the tree. From 20065562d64d6dfd4fa053b063245b56843667e7 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Tue, 6 Aug 2024 14:17:46 +0200 Subject: [PATCH 52/55] Fix interpolation. Use real coordinates not barycentric --- .../t8_transition_conformal_quad_cxx.cxx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index 7fdb286b9c..d3f921583b 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -1413,10 +1413,7 @@ t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *el // The out_coords are 2 dimensional. const int offset_3d = icoord * 3; // offset for 3 dim ref_coords when iterating over points const int offset_2d = icoord * 2; // offset for 2 dim out_coords when iterating over points - const double ref_x = ref_coords[0 + offset_3d]; - const double ref_y = ref_coords[1 + offset_3d]; - const double barycentric_coeff[3] = { 0, ref_x - ref_y, ref_y }; - t8_geom_triangular_interpolation (barycentric_coeff, vertex_coords, 3, 2, out_coords + offset_2d); + t8_geom_triangular_interpolation (ref_coords + offset_3d, vertex_coords, 2, 2, out_coords + offset_2d); } } } From a3fc59f06223a0d7e6da210a8237ec2299b18fee Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Tue, 6 Aug 2024 16:23:50 +0200 Subject: [PATCH 53/55] Fix is_leaf check for subelements --- src/t8_forest/t8_forest.cxx | 42 ++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/t8_forest/t8_forest.cxx b/src/t8_forest/t8_forest.cxx index c65c2dc14d..d748b30a43 100644 --- a/src/t8_forest/t8_forest.cxx +++ b/src/t8_forest/t8_forest.cxx @@ -2069,9 +2069,45 @@ t8_forest_element_is_leaf (const t8_forest_t forest, const t8_element_t *element /* The element was not found. */ return 0; } - /* An element was found but it may not be the candidate element. - * To identify whether the element was found, we compare these two. */ - const t8_element_t *check_element = t8_element_array_index_locidx (elements, search_result); + + /* An element was found but it may not be the candidate element. + * If our original query element is not a subelement, then we compare with the found element. + * + * Otherwise, if our query element is a subelement, then all subelements from the same element match + * the search and we need to query whether our element is contained in that set. + * If the query element is a leaf then the search_result may point to any other subelement resulting from the + * same element. + */ + t8_locidx_t check_index = search_result; + + if (scheme->t8_element_is_subelement (element)) { + const t8_element_t *check_subelement = t8_element_array_index_locidx (elements, search_result); + T8_ASSERT (check_subelement != NULL); + /* Our query element is a subelement. + * It has a subelement id A. + * If the check element at index "search_result" is not a subelement, + * then the element is not a leaf and we can return. + * If it is a subelement, then it has id B. + * If our query element is contained in the array, then + * it must be at index "search_result - B + A". + */ + const int query_subelement_id = scheme->t8_element_get_subelement_id (element); + if (!scheme->t8_element_is_subelement (check_subelement)) { + // The found element is not a subelement, thus our query element is not a leaf. + return 0; + } + const int check_subelement_id = scheme->t8_element_get_subelement_id (check_subelement); + // Compute the new index where our query element should be found. + check_index = search_result - check_subelement_id + query_subelement_id; + + if (t8_element_array_get_count (elements) <= (size_t) check_index) { + /* The element cannot be contained in the array. */ + return 0; + } + } + + /* Get the respective element from the array and compare with our query element. */ + const t8_element_t *check_element = t8_element_array_index_locidx (elements, check_index); T8_ASSERT (check_element != NULL); return (scheme->t8_element_equal (element, check_element)); } From 7520dc32e49e18014511d9475355520ccaaf1ad7 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Tue, 6 Aug 2024 16:27:16 +0200 Subject: [PATCH 54/55] add TODO comment in test --- test/t8_forest/t8_gtest_element_is_leaf.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/t8_forest/t8_gtest_element_is_leaf.cxx b/test/t8_forest/t8_gtest_element_is_leaf.cxx index 51d32755ae..393c0c7feb 100644 --- a/test/t8_forest/t8_gtest_element_is_leaf.cxx +++ b/test/t8_forest/t8_gtest_element_is_leaf.cxx @@ -34,6 +34,8 @@ * and that it returns false for the parent and the first child. */ +/* TODO: Implement a test for subelements as soon as subelement schemes are available. */ + /* Maximum uniform level for forest. */ #define T8_IS_LEAF_MAX_LVL 4 From d61176d4138ed7d9cba93dfa2830d62275894124 Mon Sep 17 00:00:00 2001 From: Johannes Holke Date: Wed, 7 Aug 2024 12:06:37 +0200 Subject: [PATCH 55/55] Fix subelement pyramid coordinate computation --- .../t8_transition_conformal_hex_cxx.cxx | 242 +++--------------- .../t8_transition_conformal_hex_cxx.hxx | 5 + .../t8_transition_conformal_quad_cxx.cxx | 23 +- 3 files changed, 47 insertions(+), 223 deletions(-) diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx index 3abe2e0dc7..45d302d08e 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.cxx @@ -29,6 +29,7 @@ #include #include #include +#include #include "t8_transition_conformal_hex_cxx.hxx" #include @@ -1714,222 +1715,49 @@ void t8_subelement_scheme_hex_c::t8_element_reference_coords (const t8_element_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) const { + T8_ASSERT (num_coords > 0); T8_ASSERT (ref_coords != NULL); + T8_ASSERT (out_coords != NULL); T8_ASSERT (t8_element_is_valid (elem)); + const t8_hex_with_subelements *element = (t8_hex_with_subelements *) elem; if (!t8_element_is_subelement (elem)) { - const p8est_quadrant_t *q1 = (const p8est_quadrant_t *) elem; - - /* Get the length of the quadrant */ - const p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); - - for (size_t coord = 0; coord < num_coords; ++coord) { - const size_t offset = 3 * coord; - /* Compute the x, y and z coordinates of the point depending on the - * reference coordinates */ - out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; - out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; - out_coords[offset + 2] = q1->z + ref_coords[offset + 2] * len; - - /* We divide the integer coordinates by the root length of the hex - * to obtain the reference coordinates. */ - out_coords[offset + 0] /= (double) P8EST_ROOT_LEN; - out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; - out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; - } + const t8_element_t *hex = (const t8_element_t *) &element->p8q; + // We call the default hex reference coord function for the hex coordinates. + default_hex_scheme.t8_element_reference_coords (hex, ref_coords, num_coords, out_coords); } else { - t8_hex_with_subelements *phex_w_sub = (t8_hex_with_subelements *) elem; - p8est_quadrant_t *q1 = &phex_w_sub->p8q; - p4est_qcoord_t len = P8EST_QUADRANT_LEN (q1->level); - /* get location information of the given subelement */ - int location[3] = {}; - t8_element_get_location_of_subelement (elem, location); - - for (size_t coord = 0; coord < num_coords; ++coord) { - const size_t offset = coord * 3; - out_coords[offset + 0] = q1->x + ref_coords[offset + 0] * len; - out_coords[offset + 1] = q1->y + ref_coords[offset + 1] * len; - out_coords[offset + 2] = q1->z + ref_coords[offset + 2] * len; + /* This element is a subelement and hence a pyramid. */ + T8_ASSERT (t8_element_shape (elem) == T8_ECLASS_PYRAMID); - //Set the apex to the center of the transition cell - if (ref_coords[0] == 1 && ref_coords[1] == 1 && ref_coords[2] == 1) { - out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); - out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); - out_coords[offset + 2] -= ref_coords[offset + 2] * (len / 2); - } - else { - if (location[0] == 0) { - //face 0 - //Add the x-coordinate to the z-coordinate in order to flip the base side of the pyramid to face f0 - out_coords[offset + 2] += ref_coords[offset + 0] * len; - //set x-coordinate to zero - out_coords[offset + 0] -= ref_coords[offset + 0] * len; - } - if (location[0] == 1) { - //Add one to the z-coordinate if the x-coordinate equals zero - out_coords[offset + 2] += (1 - 1 * ref_coords[offset + 0]) * len; - //set x-coordinate to one - out_coords[offset + 0] += (1 - 1 * ref_coords[offset + 0]) * len; - } - if (location[0] == 2) { - //Add one to the z-coordinate if the y-coordinate equals one - out_coords[offset + 2] += (ref_coords[offset + 1]) * len; - //set y-coordinate to zero - out_coords[offset + 1] -= (ref_coords[offset + 1]) * len; - } - if (location[0] == 3) { - //Add one to the z-coordinate if the y-coordinate equals zero - out_coords[offset + 2] += (1 - ref_coords[offset + 1]) * len; - //set y-coordinate to one - out_coords[offset + 1] += (1 - 1 * ref_coords[offset + 1]) * len; - } - //Nothing more to do for face 4 - if (location[0] == 5) { - //Add one to the z-coordinate - out_coords[offset + 2] += len; - } - //split - if (location[1] == 1) { - if (location[0] == 0) { - if ((location[2] & 2) == 0) { - //front - //scale the y coordinate if not zero - out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); - } - else { - //back - //scale the y coordinate if zero - out_coords[offset + 1] += (1 - ref_coords[offset + 1]) * (len / 2); - } - if ((location[2] & 1) == 0) { - //bottom - //scale the z coordinate if not zero and z is not zero if the x-coordinate of ref_coords is not zero. - out_coords[offset + 2] -= (ref_coords[offset + 0]) * (len / 2); - } - else { - //up - //scale the z coordinate if zero - out_coords[offset + 2] += (1 - 1 * ref_coords[offset + 0]) * (len / 2); - } - } - if (location[0] == 1) { - if ((location[2] & 2) == 0) { - //front - //scale the y coordinate if not zero - out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); - } - else { - //back - //scale the y coordinate if zero - out_coords[offset + 1] += (1 - ref_coords[offset + 1]) * (len / 2); - } - if ((location[2] & 1) == 0) { - //bottom - //scale the z coordinate if not zero and z is not zero if the x-coordinate of ref_coords is zero. - out_coords[offset + 2] -= (1 - ref_coords[offset + 0]) * (len / 2); - } - else { - //up - //scale the z coordinate if zero - out_coords[offset + 2] += (ref_coords[offset + 0]) * (len / 2); - } - } - if (location[0] == 2) { - if ((location[2] & 4) == 0) { - //left - //scale the x coordinate if not zero - out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); - } - else { - //right - //scale the x coordinate if zero - out_coords[offset + 0] += (1 - ref_coords[offset + 0]) * (len / 2); - } - if ((location[2] & 1) == 0) { - //bottom - //scale the z coordinate if not zero - out_coords[offset + 2] -= ref_coords[offset + 1] * (len / 2); - } - else { - //up - //scale the z coordinate if zero - out_coords[offset + 2] += (1 - ref_coords[offset + 1]) * (len / 2); - } - } - if (location[0] == 3) { - if ((location[2] & 4) == 0) { - //left - //scale the x coordinate if not zero - out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); - } - else { - //right - //scale the x coordinate if zero - out_coords[offset + 0] += (1 - ref_coords[offset + 0]) * (len / 2); - } - if ((location[2] & 1) == 0) { - //bottom - //scale the z coordinate if not zero - out_coords[offset + 2] -= (1 - ref_coords[offset + 1]) * (len / 2); - } - else { - //up - //scale the z coordinate if zero - out_coords[offset + 2] += (ref_coords[offset + 1]) * (len / 2); - } - } - - if (location[0] == 4) { - if ((location[2] & 4) == 0) { - //left - //scale the x coordinate if not zero - out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); - } - else { - //right - //scale the x coordinate if zero - out_coords[offset + 0] += (1 - ref_coords[offset + 0]) * (len / 2); - } - if ((location[2] & 2) == 0) { - //front - //scale the y coordinate if not zero - out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); - } - else { - //back - //scale the y coordinate if zero - out_coords[offset + 1] += (1 - 1 * ref_coords[offset + 1]) * (len / 2); - } - } - if (location[0] == 5) { - if ((location[2] & 4) == 0) { - //left - //scale the x coordinate if not zero - out_coords[offset + 0] -= ref_coords[offset + 0] * (len / 2); - } - else { - //right - //scale the x coordinate if zero - out_coords[offset + 0] += (1 - ref_coords[offset + 0]) * (len / 2); - } - if ((location[2] & 2) == 0) { - //front - //scale the y coordinate if not zero - out_coords[offset + 1] -= ref_coords[offset + 1] * (len / 2); - } - else { - //back - //scale the y coordinate if zero - out_coords[offset + 1] += (1 - 1 * ref_coords[offset + 1]) * (len / 2); - } - } - } + /* + * We use t8_geom_triangular_interpolation to compute the coordinates + * given the coordinates of the vertices. + * For this we consider the pyramid as a cube with 4 corners collapsed into one. + */ + constexpr int num_vertices = 5; // Should use t8_eclass_num_vertices[T8_ECLASS_TRIANGLE]; but is not constexpr + constexpr int num_vertex_coords = 8 * 3; // We need 8 corners since we use trilinear interpolation. + double vertex_coords[num_vertex_coords]; // Stores the pyramids vertices + for (int ivertex = 0; ivertex < num_vertices; ++ivertex) { + // Compute the coordinates of the 5 pyramid vertices. + t8_element_vertex_reference_coords (elem, ivertex, vertex_coords + 3 * ivertex); + } + /* Copy the values of the pyramids last vertex over to vertex_coords 5,6,7 + * in order to build a virtual cube where all top corners collapse onto one. + * We can then us the cubical linear interpolation function. */ + for (int ivertex = num_vertices; ivertex < 8; ++ivertex) { + for (int idim = 0; idim < 3; ++idim) { + vertex_coords[3 * ivertex + idim] = vertex_coords[3 * (num_vertices - 1) + idim]; } + } - out_coords[offset + 0] /= (double) P8EST_ROOT_LEN; - out_coords[offset + 1] /= (double) P8EST_ROOT_LEN; - out_coords[offset + 2] /= (double) P8EST_ROOT_LEN; + // For each incoming coordinate do the interpolation + for (size_t icoord = 0; icoord < num_coords; ++icoord) { + // The ref_coords are always 3 dimensional - even though we do not use the 3rd entry. + // The out_coords are 2 dimensional. + const int offset_ref = icoord * 3; // offset for 3 dim ref_coords when iterating over points + const int offset_out = icoord * 3; // offset for 3 dim out_coords when iterating over points + t8_geom_linear_interpolation (ref_coords + offset_ref, vertex_coords, 3, 3, out_coords + offset_out); } } } diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx index 592f699194..952d684cbe 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_hex/t8_transition_conformal_hex_cxx.hxx @@ -637,6 +637,11 @@ struct t8_subelement_scheme_hex_c: public t8_default_scheme_common_c t8_element_to_string (const t8_element_t *elem, char *debug_string, const int string_size) const; #endif + + /** Default hex scheme which is used to query hex specific computations, + * for example in \ref t8_element_reference_coords + */ + struct t8_default_scheme_hex_c default_hex_scheme; }; #endif /* !T8_TRANSITION_HEX_CXX_HXX */ diff --git a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx index d3f921583b..6264d45d4e 100644 --- a/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx +++ b/src/t8_schemes/t8_transition/t8_transition_conformal_quad/t8_transition_conformal_quad_cxx.cxx @@ -1381,24 +1381,15 @@ t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *el if (!t8_element_is_subelement (elem)) { const t8_element_t *quad = (const t8_element_t *) &element->p4q; // We call the default quad reference coord function for the quad coordinates. - // We could think about doing this in more cases. For that it would - // be beneficial to store a t8_default_scheme_quad_c pointer as member variable - // of the t8_subelement_scheme_quad_c class. default_quad_scheme.t8_element_reference_coords (quad, ref_coords, num_coords, out_coords); } else { /* This element is a subelement and hence a triangle. */ T8_ASSERT (t8_element_shape (elem) == T8_ECLASS_TRIANGLE); - /* We first convert the reference coordinates to barycentric - * coordinates. - * Since the reference triangle has vertices - * (0,0) (1,0) and (1,1) - * A vector (x,y) in that triangle has barycentric - * coordinates (0, x-y, y). - * This is since 0 * (0,0) + (x-y) * (1,0) + y * (1,1) = (0 + x - y + y, y) = (x,y) - * - * After that we use t8_geom_triangular_interpolation to compute the actual value. + /* + * We use t8_geom_triangular_interpolation to compute the coordinates + * given the coordinates of the triangle's vertices. */ constexpr int num_vertices = 3; // Should use t8_eclass_num_vertices[T8_ECLASS_TRIANGLE]; but is not constexpr constexpr int num_vertex_coords = num_vertices * 3; @@ -1407,13 +1398,13 @@ t8_subelement_scheme_quad_c::t8_element_reference_coords (const t8_element_t *el t8_element_vertex_reference_coords (elem, ivertex, vertex_coords + 3 * ivertex); } - // For each incoming coordinate compute the barycentric coordinates and do the interpolation + // For each incoming coordinate we do the interpolation for (size_t icoord = 0; icoord < num_coords; ++icoord) { // The ref_coords are always 3 dimensional - even though we do not use the 3rd entry. // The out_coords are 2 dimensional. - const int offset_3d = icoord * 3; // offset for 3 dim ref_coords when iterating over points - const int offset_2d = icoord * 2; // offset for 2 dim out_coords when iterating over points - t8_geom_triangular_interpolation (ref_coords + offset_3d, vertex_coords, 2, 2, out_coords + offset_2d); + const int offset_ref = icoord * 3; // offset for 3 dim ref_coords when iterating over points + const int offset_out = icoord * 2; // offset for 2 dim out_coords when iterating over points + t8_geom_triangular_interpolation (ref_coords + offset_ref, vertex_coords, 2, 2, out_coords + offset_out); } } }