Xyst test code coverage report
Current view: top level - Inciter/AMR - refinement.hpp (source / functions) Hit Total Coverage
Commit: e489e3468f2b950872163df1285c13fa7a355e8c Lines: 152 230 66.1 %
Date: 2024-11-20 18:16:45 Functions: 15 22 68.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 82 182 45.1 %

           Branch data     Line data    Source code
       1                 :            : #ifndef AMR_refinement_h
       2                 :            : #define AMR_refinement_h
       3                 :            : 
       4                 :            : #include <algorithm>
       5                 :            : 
       6                 :            : #include "Compiler.hpp"
       7                 :            : #include "tet_store.hpp"
       8                 :            : #include "node_connectivity.hpp"
       9                 :            : 
      10                 :            : // TODO: make this have a base class to support multiple generator schemes
      11                 :            : // using the policy design pattern
      12                 :            : 
      13                 :            : #if defined(__clang__)
      14                 :            :   #pragma clang diagnostic push
      15                 :            :   #pragma clang diagnostic ignored "-Wunused-but-set-variable"
      16                 :            : #elif defined(STRICT_GNUC)
      17                 :            :   #pragma GCC diagnostic push
      18                 :            :   #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
      19                 :            : #endif
      20                 :            : 
      21                 :            : namespace AMR {
      22                 :            : 
      23                 :          0 :     class refinement_t {
      24                 :            :         private:
      25                 :            : 
      26                 :            :             size_t DEFAULT_REFINEMENT_LEVEL = 0; //TODO: Is this in the right place?
      27                 :            :             size_t MIN_REFINEMENT_LEVEL = DEFAULT_REFINEMENT_LEVEL;
      28                 :            :             // list of "intermediate" edges to be deleted
      29                 :            :             std::set< edge_t > delete_list;
      30                 :            : 
      31                 :            :         public:
      32                 :            : 
      33                 :            :             //! Default constructor for migration
      34                 :       4994 :             refinement_t() {}
      35                 :            : 
      36                 :            :             //! Constructor taking a user-specified max refinement level
      37                 :       2468 :             refinement_t( size_t u_mrl ) :
      38         [ +  - ]:       2468 :               MAX_REFINEMENT_LEVEL( u_mrl ) {}
      39                 :            : 
      40                 :            :             size_t MAX_REFINEMENT_LEVEL;
      41                 :            : 
      42                 :            :             // TODO: Document this
      43                 :            :             child_id_list_t generate_child_ids( tet_store_t& tet_store, size_t parent_id, size_t count = MAX_CHILDREN)
      44                 :            :             {
      45                 :            :                 //return morton_id_generator_t::get_children_ids(parent_id);
      46                 :            :                 return tet_store.generate_child_ids(parent_id, count);
      47                 :            :             }
      48                 :            : 
      49                 :            :             /**
      50                 :            :              * @brief function to detect when an invalid refinement is
      51                 :            :              * invoked
      52                 :            :              *
      53                 :            :              * @param tet_store Tet store to use
      54                 :            :              * @param tet_id Id the of the tet which will be refined
      55                 :            :              *
      56                 :            :              * @return A bool stating if the tet can be validly refined
      57                 :            :              */
      58                 :            :             bool check_allowed_refinement( tet_store_t& tet_store, size_t tet_id)
      59                 :            :             {
      60                 :            :                 Refinement_State& master_element = tet_store.data(tet_id);
      61                 :            : 
      62                 :            :                 // These asserts mean we never actually try refine a 1:2 or 1:4
      63                 :            :                 assert( master_element.refinement_case !=
      64                 :            :                         Refinement_Case::one_to_two);
      65                 :            :                 assert( master_element.refinement_case !=
      66                 :            :                         Refinement_Case::one_to_four);
      67                 :            : 
      68                 :            :                 // cppcheck-suppress assertWithSideEffect
      69                 :            :                 assert( tet_store.is_active(tet_id) );
      70                 :            : 
      71                 :            :                 // Check this won't take us past the max refinement level
      72 [ +  + ][ +  - ]:      23213 :                 if (master_element.refinement_level >= MAX_REFINEMENT_LEVEL)
                 [ +  - ]
      73                 :            :                 {
      74                 :            :                     return false;
      75                 :            :                 }
      76                 :            : 
      77                 :            :                 // If we got here, we didn't detect anything which tells us not
      78                 :            :                 // to refine
      79                 :            :                 return true;
      80                 :            :             }
      81                 :            : 
      82                 :            :             /**
      83                 :            :              * @brief Method which takes a tet id, and deduces the other
      84                 :            :              * parameters needed to perform a 1:2
      85                 :            :              *
      86                 :            :              * @param tet_store Tet store to use
      87                 :            :              * @param node_connectivity Mesh node connectivity (graph)
      88                 :            :              * @param tet_id The id to refine 1:2
      89                 :            :              */
      90                 :        130 :             void refine_one_to_two( tet_store_t& tet_store, node_connectivity_t& node_connectivity, size_t tet_id)
      91                 :            :             {
      92                 :        130 :                 edge_list_t edge_list = tet_store.generate_edge_keys(tet_id);
      93                 :        130 :                 node_pair_t nodes = find_single_refinement_nodes(tet_store,edge_list);
      94                 :        130 :                 refine_one_to_two( tet_store, node_connectivity, tet_id, nodes[0], nodes[1]);
      95                 :        130 :             }
      96                 :            : 
      97                 :            : /*
      98                 :            :             //! @brief Method which takes a tet id, and transforms arguments
      99                 :            :             //!   into the form needed for the main 1:2 refinement method
     100                 :            :             //! @param tet_id The id to refine 1:2
     101                 :            :             void refine_one_to_two(
     102                 :            :                     size_t tet_id,
     103                 :            :                     std::string edge_key
     104                 :            :             )
     105                 :            :             {
     106                 :            :                 std::vector<std::string> nodes = util::split(edge_key,KEY_DELIM);
     107                 :            :                 size_t edge_node_A_id =  std::stoul (nodes[0],nullptr,0);
     108                 :            :                 size_t edge_node_B_id =  std::stoul (nodes[1],nullptr,0);
     109                 :            :                 refine_one_to_two( tet_id, edge_node_A_id, edge_node_B_id);
     110                 :            :             }
     111                 :            : */
     112                 :            :             /**
     113                 :            :              * @brief Refine a given tet id into 2 children.
     114                 :            :              * NOTE: Does not do any validity checking (currently?)
     115                 :            :              *
     116                 :            :              * @param tet_store Tet store to use
     117                 :            :              * @param node_connectivity Mesh node connectivity (graph)
     118                 :            :              * @param tet_id Id of tet to refine
     119                 :            :              * @param edge_node_A_id The first node of id of the edge which
     120                 :            :              * will be split
     121                 :            :              * @param edge_node_B_id The second node of id of the
     122                 :            :              * edge which will be split
     123                 :            :              */
     124                 :        130 :             void refine_one_to_two(
     125                 :            :                     tet_store_t& tet_store,
     126                 :            :                     node_connectivity_t& node_connectivity,
     127                 :            :                     size_t tet_id,
     128                 :            :                     size_t edge_node_A_id,
     129                 :            :                     size_t edge_node_B_id
     130                 :            :             )
     131                 :            :             {
     132                 :            : 
     133                 :            :                 trace_out << "refine_one_to_two" << std::endl;
     134                 :          0 :                 if (!check_allowed_refinement(tet_store,tet_id)) return;
     135                 :            : 
     136                 :        130 :                 tet_t original_tet = tet_store.get(tet_id);
     137                 :            : 
     138                 :            :                 //coordinate_t original_tet_c = node_connectivity->id_to_coordinate(id);
     139                 :            : 
     140                 :        130 :                 size_t new_node_id = node_connectivity.add( edge_node_A_id, edge_node_B_id );
     141                 :            : 
     142                 :            :                 /// Split existing tet into two new tets
     143                 :            : 
     144                 :            :                 // The two new tets will be the same, but for each an edge will
     145                 :            :                 // be cut, losing an edge  replaced by E
     146                 :            : 
     147                 :            :                 tet_t new_tet1;
     148                 :            :                 tet_t new_tet2;
     149                 :            : 
     150                 :            :                 // Create a new tet that is based on the original
     151                 :            :                 copy_tet(&new_tet1, &original_tet);
     152                 :            : 
     153                 :            :                 // Replace all node ids in tet that were pointing to A with new_node_id
     154                 :            :                 replace_node(&new_tet1, edge_node_A_id, new_node_id);
     155                 :            : 
     156                 :            :                 // Create a new tet that is based on the original
     157                 :            :                 copy_tet(&new_tet2, &original_tet);
     158                 :            : 
     159                 :            :                 // Replace all node ids in tet that were pointing to B with new_node_id
     160                 :            :                 replace_node(&new_tet2, edge_node_B_id, new_node_id);
     161                 :            : 
     162                 :            :                 // Now, update the edge list
     163                 :            : 
     164                 :            :                 // Generate edges for split
     165                 :        130 :                 tet_store.edge_store.split(edge_node_A_id, edge_node_B_id, new_node_id,
     166                 :            :                         Edge_Lock_Case::intermediate);
     167                 :            : 
     168                 :            :                 child_id_list_t child_list = generate_child_ids(tet_store,tet_id, 2);
     169                 :            : 
     170                 :        130 :                 size_t first_child_id = child_list[0];
     171                 :        130 :                 size_t second_child_id = child_list[1];
     172                 :            : 
     173                 :            :                 // Add the two new tets to the system
     174                 :            :                 size_t new_tet_id = first_child_id;
     175         [ +  - ]:        130 :                 tet_store.add(
     176                 :            :                         first_child_id,
     177                 :            :                         new_tet1,
     178                 :            :                         Refinement_Case::one_to_two,
     179                 :            :                         tet_id
     180                 :            :                 );
     181                 :            : 
     182                 :            :                 //size_t new_tet_id2 = second_child_id;
     183         [ +  - ]:        130 :                 tet_store.add(
     184                 :            :                         second_child_id,
     185                 :            :                         new_tet2,
     186                 :            :                         Refinement_Case::one_to_two,
     187                 :            :                         tet_id
     188                 :            :                 );
     189                 :            : 
     190                 :            :                 //trace_out << "1:2 DOING REFINE OF " << tet_id << ". Adding " << child_list[0] << " and " << child_list[1] << std::endl;
     191                 :            : 
     192                 :            :                 // This call is only needed to add a single edge, from the new
     193                 :            :                 // node to the node on the normal to that face, but avoids
     194                 :            :                 // directly calculating which nodes that is
     195         [ +  - ]:        130 :                 tet_store.generate_edges(new_tet_id);
     196                 :            : 
     197                 :            :                 // Currently we lock one per tet, around the split node. We
     198                 :            :                 // also need to lock the two "arms" which come out from it
     199                 :            :                 //lock_edges_from_node(new_tet_id, new_node_id, Edge_Lock_Case::intermediate);
     200                 :            :                 //lock_edges_from_node(new_tet_id2, new_node_id, Edge_Lock_Case::intermediate);
     201                 :            : 
     202                 :            :                 // Deactivate parent tet?
     203                 :            :                 tet_store.deactivate(tet_id);
     204                 :            :                 //lock_edges_from_node(new_node_id, Edge_Lock_Case::intermediate);
     205                 :            :                 trace_out << "Adding " << new_node_id << " to intermediate list " << std::endl;
     206                 :            :                 tet_store.intermediate_list.insert(new_node_id);
     207                 :            :             }
     208                 :            : 
     209                 :            :             /**
     210                 :            :              * @brief Method which takes a tet id, and deduces the other
     211                 :            :              * parameters needed to perform a 1:4
     212                 :            :              *
     213                 :            :              * @param tet_store Tet store to use
     214                 :            :              * @param node_connectivity Mesh node connectivity (graph)
     215                 :            :              * @param tet_id The id to refine 1:4
     216                 :            :             */
     217                 :        176 :             void refine_one_to_four( tet_store_t& tet_store,
     218                 :            :                     node_connectivity_t& node_connectivity, size_t tet_id)
     219                 :            :             {
     220                 :            :                 trace_out << "do refine 1:4 " << std::endl;
     221                 :            :                 //bool face_refine = false;
     222                 :            :                 size_t face_refine_id = 0; // FIXME: Does this need a better default
     223                 :        176 :                 face_list_t face_list = tet_store.generate_face_lists(tet_id);
     224                 :            : 
     225                 :            :                 // Iterate over each face
     226         [ +  - ]:        512 :                 for (size_t face = 0; face < NUM_TET_FACES; face++)
     227                 :            :                 {
     228                 :            :                     int num_face_refine_edges = 0;
     229                 :            : 
     230                 :        512 :                     face_ids_t face_ids = face_list[face];
     231                 :            :                     trace_out << "face ids " <<
     232                 :            :                         face_ids[0] << ", " <<
     233                 :            :                         face_ids[1] << ", " <<
     234                 :            :                         face_ids[2] << ", " <<
     235                 :            :                         std::endl;
     236                 :            : 
     237                 :        512 :                     edge_list_t face_edge_list = AMR::edge_store_t::generate_keys_from_face_ids(face_ids);
     238                 :            :                     // For this face list, see which ones need refining
     239                 :            :                     trace_out << "Looping to " << NUM_FACE_NODES << std::endl;
     240         [ +  + ]:       2048 :                     for (size_t k = 0; k < NUM_FACE_NODES; k++)
     241                 :            :                     {
     242                 :            :                         trace_out << "nodes " << k << std::endl;
     243                 :            : 
     244                 :       1536 :                         edge_t edge = face_edge_list[k];
     245 [ +  - ][ +  + ]:       1536 :                         if (tet_store.edge_store.get(edge).needs_refining == 1)
     246                 :            :                         {
     247                 :        864 :                             num_face_refine_edges++;
     248                 :            :                             trace_out << "Ref " << edge << " Num face => " << num_face_refine_edges << std::endl;
     249                 :            :                         }
     250                 :            : 
     251                 :            :                         // Check for locked edges
     252                 :            :                             // This case only cares about faces with no locks
     253         [ -  + ]:       1536 :                         if (tet_store.edge_store.lock_case(edge) != Edge_Lock_Case::unlocked)
     254                 :            :                         {
     255                 :            :                             // Abort this face
     256                 :            :                             trace_out << "Face has lock it's not this one " << face << std::endl;
     257                 :            :                             num_face_refine_edges = 0;
     258                 :          0 :                             break;
     259                 :            :                         }
     260                 :            :                         trace_out << "Num face => " << num_face_refine_edges << std::endl;
     261                 :            :                     }
     262         [ +  + ]:        512 :                     if (num_face_refine_edges >= 2)
     263                 :            :                     {
     264                 :            :                         assert(num_face_refine_edges < 4);
     265                 :            :                         //face_refine = true;
     266                 :            :                         trace_out << "Accepting face " << face << std::endl;
     267                 :            :                         face_refine_id = face;
     268                 :        176 :                         break;
     269                 :            :                     }
     270                 :            :                 }
     271                 :            : 
     272                 :        176 :                 tet_t tet = tet_store.get(tet_id);
     273                 :            :                 size_t opposite_offset = AMR::node_connectivity_t::face_list_opposite(face_list, face_refine_id);
     274                 :        176 :                 size_t opposite_id = tet[opposite_offset];
     275                 :            : 
     276                 :            :                 trace_out << "1:4 tet mark id " << tet_id << std::endl;
     277                 :            :                 trace_out << "opposite offset " << opposite_offset << std::endl;
     278                 :            :                 trace_out << "opposite id " << opposite_id << std::endl;
     279                 :            :                 trace_out << "face refine id " << face_refine_id << std::endl;
     280                 :            :                 trace_out << "face list 0 " << face_list[face_refine_id][0] << std::endl;
     281                 :            :                 trace_out << "face list 1 " << face_list[face_refine_id][1] << std::endl;
     282                 :            :                 trace_out << "face list 2 " << face_list[face_refine_id][2] << std::endl;
     283                 :            : 
     284                 :        176 :                 refine_one_to_four(tet_store, node_connectivity, tet_id, face_list[face_refine_id], opposite_id);
     285                 :        176 :             }
     286                 :            : 
     287                 :            :             /**
     288                 :            :              * @brief Method which takes a tet id, and deduces the other
     289                 :            :              * parameters needed to perform a 1:4, as a part of an 8:4 deref
     290                 :            :              *
     291                 :            :              * @param tet_store Tet store to use
     292                 :            :              * @param node_connectivity Mesh node connectivity (graph)
     293                 :            :              * @param tet_id The id to refine 1:4
     294                 :            :              * @param kept_edges Vector of edges to keep after deref-ref
     295                 :            :             */
     296                 :          0 :             void deref_refine_one_to_four( tet_store_t& tet_store,
     297                 :            :                     node_connectivity_t& node_connectivity, size_t tet_id,
     298                 :            :                     std::vector< edge_t >& kept_edges)
     299                 :            :             {
     300                 :            :                 trace_out << "do refine 1:4 " << std::endl;
     301                 :            :                 //bool face_refine = false;
     302                 :            :                 size_t face_refine_id = 0; // FIXME: Does this need a better default
     303                 :          0 :                 face_list_t face_list = tet_store.generate_face_lists(tet_id);
     304                 :            : 
     305                 :            :                 // Iterate over each face
     306         [ -  - ]:          0 :                 for (size_t face = 0; face < NUM_TET_FACES; face++)
     307                 :            :                 {
     308                 :            :                     int num_face_refine_edges = 0;
     309                 :            : 
     310                 :          0 :                     face_ids_t face_ids = face_list[face];
     311                 :            :                     trace_out << "face ids " <<
     312                 :            :                         face_ids[0] << ", " <<
     313                 :            :                         face_ids[1] << ", " <<
     314                 :            :                         face_ids[2] << ", " <<
     315                 :            :                         std::endl;
     316                 :            : 
     317                 :          0 :                     edge_list_t face_edge_list = AMR::edge_store_t::generate_keys_from_face_ids(face_ids);
     318                 :            :                     // For this face list, see which ones need refining
     319                 :            :                     trace_out << "Looping to " << NUM_FACE_NODES << std::endl;
     320         [ -  - ]:          0 :                     for (size_t k = 0; k < NUM_FACE_NODES; k++)
     321                 :            :                     {
     322                 :          0 :                         edge_t edge = face_edge_list[k];
     323                 :            :                         trace_out << "edge-nodes " << edge.get_data()[0] << "-"
     324                 :            :                           << edge.get_data()[1] << std::endl;
     325                 :            : 
     326 [ -  - ][ -  - ]:          0 :                         if (tet_store.edge_store.get(edge).needs_refining == 2)
     327                 :            :                         {
     328                 :          0 :                             num_face_refine_edges++;
     329                 :            :                             trace_out << "Ref " << edge << " Num face => " << num_face_refine_edges << std::endl;
     330                 :            :                         }
     331                 :            : 
     332                 :            :                         // Check for locked edges
     333                 :            :                             // This case only cares about faces with no locks
     334         [ -  - ]:          0 :                         if (tet_store.edge_store.lock_case(edge) != Edge_Lock_Case::unlocked)
     335                 :            :                         {
     336                 :            :                             // Abort this face
     337                 :            :                             trace_out << "Face has lock it's not this one " << face << std::endl;
     338                 :            :                             num_face_refine_edges = 0;
     339                 :          0 :                             break;
     340                 :            :                         }
     341                 :            :                         trace_out << "Num face => " << num_face_refine_edges << std::endl;
     342                 :            :                     }
     343         [ -  - ]:          0 :                     if (num_face_refine_edges >= 2)
     344                 :            :                     {
     345                 :            :                         assert(num_face_refine_edges < 4);
     346                 :            :                         //face_refine = true;
     347                 :            :                         trace_out << "Accepting face " << face << std::endl;
     348                 :            :                         face_refine_id = face;
     349                 :          0 :                         break;
     350                 :            :                     }
     351                 :            :                 }
     352                 :            : 
     353                 :          0 :                 tet_t tet = tet_store.get(tet_id);
     354                 :            :                 size_t opposite_offset = AMR::node_connectivity_t::face_list_opposite(face_list, face_refine_id);
     355                 :          0 :                 size_t opposite_id = tet[opposite_offset];
     356                 :            : 
     357                 :            :                 trace_out << "1:4 tet mark id " << tet_id << std::endl;
     358                 :            :                 trace_out << "opposite offset " << opposite_offset << std::endl;
     359                 :            :                 trace_out << "opposite id " << opposite_id << std::endl;
     360                 :            :                 trace_out << "face refine id " << face_refine_id << std::endl;
     361                 :            :                 trace_out << "face list 0 " << face_list[face_refine_id][0] << std::endl;
     362                 :            :                 trace_out << "face list 1 " << face_list[face_refine_id][1] << std::endl;
     363                 :            :                 trace_out << "face list 2 " << face_list[face_refine_id][2] << std::endl;
     364                 :            : 
     365                 :            :                 // store edges that should not be removed due to the deref-ref
     366                 :            :                 auto kept_edge_list = AMR::edge_store_t::
     367                 :          0 :                   generate_keys_from_face_ids(face_list[face_refine_id]);
     368         [ -  - ]:          0 :                 for (size_t i=0; i<3; ++i) {
     369                 :          0 :                   kept_edges.push_back(kept_edge_list[i]);
     370                 :            :                 }
     371                 :            : 
     372                 :          0 :                 refine_one_to_four(tet_store, node_connectivity, tet_id, face_list[face_refine_id], opposite_id);
     373                 :          0 :             }
     374                 :            : 
     375                 :            :             /**
     376                 :            :              * @brief Refine a given tet id into 4 children.
     377                 :            :              * NOTE: Does not do any validity checking (currently?)
     378                 :            :              *
     379                 :            :              * @param tet_store Tet store to use
     380                 :            :              * @param node_connectivity Mesh node connectivity (graph)
     381                 :            :              * @param tet_id The id of the tet to refine
     382                 :            :              * @param face_ids The ids which make the face to be split
     383                 :            :              * @param opposite_id The remaining id which is "opposite" the
     384                 :            :              * split face
     385                 :            :              */
     386                 :        176 :             void refine_one_to_four(
     387                 :            :                     tet_store_t& tet_store,
     388                 :            :                     node_connectivity_t& node_connectivity,
     389                 :            :                     size_t tet_id,
     390                 :            :                     std::array<size_t, NUM_FACE_NODES> face_ids,
     391                 :            :                     size_t opposite_id
     392                 :            :             )
     393                 :            :             {
     394                 :            : 
     395                 :            :                 trace_out << "refine_one_to_four" << std::endl;
     396                 :          0 :                 if (!check_allowed_refinement(tet_store,tet_id)) return;
     397                 :            : 
     398                 :            :                 trace_out << "Refining tet_id " << tet_id <<
     399                 :            :                     " 1:4 opposite edge " << opposite_id << std::endl;
     400                 :            : 
     401                 :        176 :                 tet_t t = tet_store.get(tet_id);
     402                 :            :                 trace_out  << "Tet has nodes " <<
     403                 :            :                     t[0] << ", " <<
     404                 :            :                     t[1] << ", " <<
     405                 :            :                     t[2] << ", " <<
     406                 :            :                     t[3] << ", " <<
     407                 :            :                     std::endl;
     408                 :            : 
     409                 :            :                 trace_out << "face_ids " <<
     410                 :            :                     face_ids[0] << ", " <<
     411                 :            :                     face_ids[1] << ", " <<
     412                 :            :                     face_ids[2] << ", " <<
     413                 :            :                     std::endl;
     414                 :            : 
     415                 :        176 :                 size_t A = face_ids[0];
     416                 :        176 :                 size_t B = face_ids[1];
     417                 :        176 :                 size_t C = face_ids[2];
     418                 :            :                 size_t D = opposite_id;
     419                 :            : 
     420                 :            :                 trace_out <<
     421                 :            :                     " A " << A <<
     422                 :            :                     " B " << B <<
     423                 :            :                     " C " << C <<
     424                 :            :                     " D " << D <<
     425                 :            :                     std::endl;
     426                 :            : 
     427                 :            :                 // Make new nodes
     428                 :            :                 //coordinate_t AB_mid = node_connectivity->find_mid_point(A, B);
     429                 :        176 :                 size_t AB = node_connectivity.add(A,B);
     430                 :            : 
     431                 :            :                 //coordinate_t AC_mid = node_connectivity->find_mid_point(A, C);
     432                 :        176 :                 size_t AC = node_connectivity.add(A,C);
     433                 :            : 
     434                 :            :                 //coordinate_t BC_mid = node_connectivity->find_mid_point(B, C);
     435                 :        176 :                 size_t BC = node_connectivity.add(B,C);
     436                 :            : 
     437                 :            :                 // Use nodes to update edges
     438                 :            :                 // All added edges will be locked due to containing intermediate points
     439                 :            :                 // Split Outer face  edges
     440                 :        176 :                 tet_store.edge_store.split(A, C, AC, Edge_Lock_Case::intermediate);
     441                 :            :                 tet_store.edge_store.split(A, B, AB, Edge_Lock_Case::intermediate);
     442                 :            :                 tet_store.edge_store.split(B, C, BC, Edge_Lock_Case::intermediate);
     443                 :            : 
     444                 :            :                 // Connect D to intermediate points
     445                 :        176 :                 tet_store.edge_store.generate(D, AC, Edge_Lock_Case::intermediate);
     446                 :        176 :                 tet_store.edge_store.generate(D, BC, Edge_Lock_Case::intermediate);
     447                 :        176 :                 tet_store.edge_store.generate(D, AB, Edge_Lock_Case::intermediate);
     448                 :            :                 // Connect inner edges
     449                 :        176 :                 tet_store.edge_store.generate(AC, BC, Edge_Lock_Case::intermediate);
     450                 :        176 :                 tet_store.edge_store.generate(AC, AB, Edge_Lock_Case::intermediate);
     451                 :        176 :                 tet_store.edge_store.generate(AB, BC, Edge_Lock_Case::intermediate);
     452                 :            : 
     453                 :            :                 // Make new Tets
     454                 :            :                 //  This is just the node opposite the face plus each pair
     455                 :            :                 //  of the news nodes, and the old corner
     456                 :            :                 //  FIXME: How to find that near corner programatically?
     457                 :            : 
     458                 :            :                 // Hard coded solution
     459                 :            :                 // A AC AB D
     460                 :            :                 // AC AB BC D
     461                 :            :                 // AC BC C D
     462                 :            :                 // AB B BC D
     463                 :            : 
     464                 :            :                 size_t num_children = 4;
     465                 :            :                 child_id_list_t child = generate_child_ids(tet_store,tet_id, num_children);
     466                 :            : 
     467                 :            :                 // Outsides
     468         [ +  - ]:        176 :                 tet_store.add(child[0], {{A,  AB, AC, D}}, Refinement_Case::one_to_four, tet_id);
     469         [ +  - ]:        176 :                 tet_store.add(child[2], {{AC, BC, C,  D}}, Refinement_Case::one_to_four, tet_id);
     470         [ +  - ]:        176 :                 tet_store.add(child[3], {{AB, B,  BC, D}}, Refinement_Case::one_to_four, tet_id);
     471                 :            : 
     472                 :            :                 // Center
     473                 :        176 :                 size_t center_id = child[1]; // 1 to preserve Jacobian order
     474 [ +  - ][ +  - ]:        176 :                 tet_store.add(center_id, {{AC, AB, BC, D}}, Refinement_Case::one_to_four, tet_id);
     475                 :            : 
     476                 :            : 
     477                 :            :                 // TODO: replace this with a more concise way to lock the correct edges
     478                 :            : 
     479                 :        176 :                 tet_store.add_center(center_id);
     480                 :            :                 /*
     481                 :            :                 lock_edges_from_node(child[0], AB, Edge_Lock_Case::intermediate);
     482                 :            :                 lock_edges_from_node(child[0], AC, Edge_Lock_Case::intermediate);
     483                 :            :                 lock_edges_from_node(child[2], AC, Edge_Lock_Case::intermediate);
     484                 :            :                 lock_edges_from_node(child[2], BC, Edge_Lock_Case::intermediate);
     485                 :            :                 lock_edges_from_node(child[3], AB, Edge_Lock_Case::intermediate);
     486                 :            :                 lock_edges_from_node(child[3], BC, Edge_Lock_Case::intermediate);
     487                 :            :                 lock_edges_from_node(center_id, AC, Edge_Lock_Case::intermediate);
     488                 :            :                 lock_edges_from_node(center_id, AB, Edge_Lock_Case::intermediate);
     489                 :            :                 lock_edges_from_node(center_id, BC, Edge_Lock_Case::intermediate);
     490                 :            :                 */
     491                 :            : 
     492                 :            : 
     493                 :            :                 tet_store.deactivate(tet_id);
     494                 :            : 
     495                 :            :                 //trace_out << "1:4 DOING REFINE OF " << tet_id << ". Adding "
     496                 :            :                     // << child[0] << ", "
     497                 :            :                     // << child[1] << ", "
     498                 :            :                     // << child[2] << ", "
     499                 :            :                     // << child[3]
     500                 :            :                     // << std::endl;
     501                 :            : 
     502                 :            :                 /*
     503                 :            :                 lock_edges_from_node(AB, Edge_Lock_Case::intermediate);
     504                 :            :                 lock_edges_from_node(AC, Edge_Lock_Case::intermediate);
     505                 :            :                 lock_edges_from_node(BC, Edge_Lock_Case::intermediate);
     506                 :            :                 */
     507                 :            : 
     508                 :            :                 trace_out << "Adding " << AB << " to intermediate list " << std::endl;
     509                 :            :                 tet_store.intermediate_list.insert(AB);
     510                 :            :                 trace_out << "Adding " << AC << " to intermediate list " << std::endl;
     511                 :            :                 tet_store.intermediate_list.insert(AC);
     512                 :            :                 trace_out << "Adding " << BC << " to intermediate list " << std::endl;
     513                 :            :                 tet_store.intermediate_list.insert(BC);
     514                 :            : 
     515                 :            :             }
     516                 :            : 
     517                 :            :             /**
     518                 :            :              * @brief Refine a given tet id into 8 children.
     519                 :            :              * NOTE: Does not do any validity checking (currently?)
     520                 :            :              *
     521                 :            :              * @param tet_store Tet store to use
     522                 :            :              * @param node_connectivity Mesh node connectivity (graph)
     523                 :            :              * @param tet_id Id of tet to refine
     524                 :            :              */
     525                 :      22907 :             void refine_one_to_eight( tet_store_t& tet_store,
     526                 :            :                     node_connectivity_t& node_connectivity, size_t tet_id)
     527                 :            :             {
     528                 :            : 
     529                 :            :                 trace_out << "refine_one_to_eight" << std::endl;
     530                 :       9024 :                 if (!check_allowed_refinement(tet_store,tet_id)) return;
     531                 :            : 
     532                 :            :                 // Split every edge into two
     533                 :            :                 // Makes 4 tets out of the old corners and 3 near mid-points
     534                 :            :                 // Make 4 out of the midpoints
     535                 :            : 
     536                 :            :                 // For Tet {ABCD} need to know all (non-repeating) node pairs
     537                 :            :                 // {AB} {AC} {AD} {BC} {BD} {CD}
     538                 :            :                 // This can either be hard coded, or generated with a 2d loop
     539                 :            :                 // The loop would just be i=0..4, j=i..4
     540                 :            :                 //
     541                 :            : 
     542                 :            : 
     543                 :      13883 :                 tet_t tet = tet_store.get(tet_id);
     544                 :            : 
     545                 :            :                 size_t A = tet[0];
     546                 :            :                 size_t B = tet[1];
     547                 :            :                 size_t C = tet[2];
     548                 :            :                 size_t D = tet[3];
     549                 :            : 
     550                 :            :                 trace_out << "A " << A << " B " << B << " C " << C << " D " << D
     551                 :            :                     << std::endl;
     552                 :            : 
     553                 :            :                 // Generate pairs of nodes (i.e edges)
     554                 :            :                 // Hard coding for now, can swap out for loop
     555                 :            :                 //coordinate_t AB_mid = node_connectivity->find_mid_point(A,B);
     556                 :      13883 :                 size_t AB = node_connectivity.add(A,B);
     557                 :            : 
     558                 :            :                 //coordinate_t AC_mid = node_connectivity->find_mid_point(A,C);
     559                 :      13883 :                 size_t AC = node_connectivity.add(A,C);
     560                 :            : 
     561                 :            :                 //coordinate_t AD_mid = node_connectivity->find_mid_point(A,D);
     562                 :      13883 :                 size_t AD = node_connectivity.add(A,D);
     563                 :            : 
     564                 :            :                 //coordinate_t BC_mid = node_connectivity->find_mid_point(B,C);
     565                 :      13883 :                 size_t BC = node_connectivity.add(B,C);
     566                 :            : 
     567                 :            :                 //coordinate_t BD_mid = node_connectivity->find_mid_point(B,D);
     568                 :      13883 :                 size_t BD = node_connectivity.add(B,D);
     569                 :            : 
     570                 :            :                 //coordinate_t CD_mid = node_connectivity->find_mid_point(C,D);
     571                 :      13883 :                 size_t CD = node_connectivity.add(C,D);
     572                 :            : 
     573                 :            :                 // Update edges
     574                 :            : 
     575                 :      13883 :                 tet_store.edge_store.split(A, C, AC, Edge_Lock_Case::unlocked);
     576                 :            :                 tet_store.edge_store.split(A, B, AB, Edge_Lock_Case::unlocked);
     577                 :            :                 tet_store.edge_store.split(A, D, AD, Edge_Lock_Case::unlocked);
     578                 :            :                 tet_store.edge_store.split(B, C, BC, Edge_Lock_Case::unlocked);
     579                 :            :                 tet_store.edge_store.split(B, D, BD, Edge_Lock_Case::unlocked);
     580                 :            :                 tet_store.edge_store.split(C, D, CD, Edge_Lock_Case::unlocked);
     581                 :            : 
     582                 :            : 
     583                 :            :                 // Outside edges for face ABC
     584                 :      13883 :                 tet_store.edge_store.generate(AC, BC, Edge_Lock_Case::unlocked);
     585                 :      13883 :                 tet_store.edge_store.generate(AC, AB, Edge_Lock_Case::unlocked);
     586                 :      13883 :                 tet_store.edge_store.generate(AB, BC, Edge_Lock_Case::unlocked);
     587                 :            : 
     588                 :            :                 // Outside edges for face ACD
     589                 :      13883 :                 tet_store.edge_store.generate(AC, AD, Edge_Lock_Case::unlocked);
     590                 :      13883 :                 tet_store.edge_store.generate(AD, CD, Edge_Lock_Case::unlocked);
     591                 :      13883 :                 tet_store.edge_store.generate(AC, CD, Edge_Lock_Case::unlocked);
     592                 :            : 
     593                 :            :                 // Outside edges for face BCD
     594                 :      13883 :                 tet_store.edge_store.generate(BD, CD, Edge_Lock_Case::unlocked);
     595                 :      13883 :                 tet_store.edge_store.generate(BD, BC, Edge_Lock_Case::unlocked);
     596                 :      13883 :                 tet_store.edge_store.generate(CD, BC, Edge_Lock_Case::unlocked);
     597                 :            : 
     598                 :            :                 // Outside edges for face ABD
     599                 :      13883 :                  tet_store.edge_store.generate(AD, BD, Edge_Lock_Case::unlocked);
     600                 :      13883 :                 tet_store.edge_store.generate(AB, AD, Edge_Lock_Case::unlocked);
     601                 :      13883 :                 tet_store.edge_store.generate(AB, BD, Edge_Lock_Case::unlocked);
     602                 :            : 
     603                 :            :                 // Interior Edges
     604                 :      13883 :                    tet_store.edge_store.generate(AC, BD, Edge_Lock_Case::unlocked);
     605                 :      13883 :                 tet_store.edge_store.generate(CD, AD, Edge_Lock_Case::unlocked);
     606                 :            : 
     607                 :            :                 // Add the new tets
     608                 :            :                 //
     609                 :            :                 // External
     610                 :            :                 // A AB AC AD - A
     611                 :            :                 // B BA BC BD - B
     612                 :            :                 // C CA CB CD - C
     613                 :            :                 // D DA DB DC - D
     614                 :            :                 // -
     615                 :            :                 // Internal (for a face BDC, it's the intermediate and mid opposite)
     616                 :            :                 // BC CD DB AC - BDC
     617                 :            :                 // AB BD AD AC - ABD
     618                 :            :                 // AB AC BC BD - ABC
     619                 :            :                 // AC AD CD BD - ACD
     620                 :            :                 //
     621                 :            : 
     622                 :            :                 // TODO: This is actually generating IDs not trying to get them
     623                 :            :                 child_id_list_t child = generate_child_ids(tet_store,tet_id);
     624                 :            : 
     625                 :            :                 // This order should give a positive Jacobian
     626         [ +  - ]:      13883 :                 tet_store.add(child[0], {{A, AB, AC, AD}}, Refinement_Case::one_to_eight, tet_id);
     627         [ +  - ]:      13883 :                 tet_store.add(child[1], {{B, BC, AB, BD}}, Refinement_Case::one_to_eight, tet_id);
     628         [ +  - ]:      13883 :                 tet_store.add(child[2], {{C, AC, BC, CD}}, Refinement_Case::one_to_eight, tet_id);
     629         [ +  - ]:      13883 :                 tet_store.add(child[3], {{D, AD, CD, BD}}, Refinement_Case::one_to_eight, tet_id);
     630                 :            : 
     631         [ +  - ]:      13883 :                 tet_store.add(child[4], {{BC, CD, AC, BD}}, Refinement_Case::one_to_eight, tet_id);
     632         [ +  - ]:      13883 :                 tet_store.add(child[5], {{AB, BD, AC, AD}}, Refinement_Case::one_to_eight, tet_id);
     633         [ +  - ]:      13883 :                 tet_store.add(child[6], {{AB, BC, AC, BD}}, Refinement_Case::one_to_eight, tet_id);
     634         [ +  - ]:      13883 :                 tet_store.add(child[7], {{AC, BD, CD, AD}}, Refinement_Case::one_to_eight, tet_id);
     635                 :            : 
     636                 :            :                 tet_store.deactivate(tet_id);
     637                 :            : 
     638                 :            :                 //trace_out << "1:8 DOING REFINE OF " << tet_id << ". "
     639                 :            :                     // << child[0] << ", "
     640                 :            :                     // << child[1] << ", "
     641                 :            :                     // << child[2] << ", "
     642                 :            :                     // << child[3] << ", "
     643                 :            :                     // << child[4] << ", "
     644                 :            :                     // << child[5] << ", "
     645                 :            :                     // << child[6] << ", "
     646                 :            :                     // << child[7]
     647                 :            :                     // << std::endl;
     648                 :            : 
     649                 :            :             }
     650                 :            : 
     651                 :            :             // This is just a simple assignment, but I wanted to abstract it
     652                 :            :             // for if we change the underlying type to something which a simple
     653                 :            :             // assignment is no longer safe
     654                 :            :             /**
     655                 :            :              * @brief Function to duplicate (deep copy) a tet. Useful for when
     656                 :            :              * you want to make a tet that's very similar to an existing one
     657                 :            :              *
     658                 :            :              * @param out The tet to store the copy
     659                 :            :              * @param original The tet to copy the data from
     660                 :            :              */
     661                 :            :             void copy_tet(tet_t* out, tet_t* original)
     662                 :            :             {
     663                 :            :                 // NOTE: This will do a deep copy, so is safer than it may look
     664                 :        260 :                 *out = *original;
     665                 :            :             }
     666                 :            : 
     667                 :            :             // This is just a std::replace, but may need to be more complicated
     668                 :            :             // in the future?
     669                 :            :             /**
     670                 :            :              * @brief function to take an existing list of tet ids and
     671                 :            :              * replace one. This can be useful for when you want to build very
     672                 :            :              * similar tets which share nodes
     673                 :            :              *
     674                 :            :              * @param tet Tet to perform operation on
     675                 :            :              * @param remove Element to be replaced
     676                 :            :              * @param add Element to replace with
     677                 :            :              */
     678                 :            :             void replace_node(tet_t* tet, size_t remove, size_t add)
     679                 :            :             {
     680                 :            :                 std::replace(tet->begin(), tet->end(), remove, add);
     681                 :            :             }
     682                 :            : 
     683                 :            :             /**
     684                 :            :              * @brief Function to find out slot in the x,y,z data arrays a tet lives
     685                 :            :              *
     686                 :            :              * // NOTE: this is _currently_ trivial, but will be nice if we for
     687                 :            :              * example swap data stores to a map
     688                 :            :              *
     689                 :            :              * @param tet_store Tet store to use
     690                 :            :              * @param tet tet of the tet to look for
     691                 :            :              * @param element offset into that tet to look at
     692                 :            :              *
     693                 :            :              * @return tet into data arrays the tet lives
     694                 :            :              */
     695                 :            :             // TODO: Move this (or rename?)
     696                 :            :             size_t tet_id_to_node_id( tet_store_t& tet_store, size_t tet, size_t element) {
     697                 :            :                 return tet_store.get(tet)[element];
     698                 :            :             }
     699                 :            : 
     700                 :            :             /**
     701                 :            :              * @brief Function to find the nodes which make up the
     702                 :            :              * single (or first?º edge which needs to be refined in an given
     703                 :            :              * edge_list
     704                 :            :              *
     705                 :            :              * @param tet_store Tet store to use
     706                 :            :              * @param edge_list The edge list to search for a refinement edge
     707                 :            :              *
     708                 :            :              * @return The node pair which represent the edge which needs
     709                 :            :              * refining
     710                 :            :              */
     711                 :        130 :             node_pair_t find_single_refinement_nodes( tet_store_t& tet_store, edge_list_t edge_list)
     712                 :            :             {
     713                 :            :                 node_pair_t returned_nodes;
     714                 :            :                 bool found_break = false;
     715         [ +  - ]:        528 :                 for (size_t k = 0; k < NUM_TET_EDGES; k++)
     716                 :            :                 {
     717                 :        528 :                     edge_t edge = edge_list[k];
     718                 :            : 
     719         [ +  + ]:        528 :                     if (tet_store.edge_store.get(edge).needs_refining == 1)
     720                 :            :                     {
     721                 :            :                         returned_nodes[0] = edge.first();
     722                 :            :                         returned_nodes[1] = edge.second();
     723                 :            : 
     724                 :            :                         trace_out << "1:2 needs to be split on " <<
     725                 :            :                             returned_nodes[0] << " and " <<
     726                 :            :                             returned_nodes[1] << std::endl;
     727                 :            : 
     728                 :            :                         found_break = true;
     729                 :            :                         break;
     730                 :            :                     }
     731                 :            :                 }
     732                 :            : 
     733                 :            :                 assert(found_break);
     734                 :            : 
     735                 :        130 :                 return returned_nodes;
     736                 :            :             }
     737                 :            : 
     738                 :         71 :             void lock_intermediates(
     739                 :            :                     tet_store_t& tet_store,
     740                 :            :                     const std::unordered_set<size_t>& intermediate_list,
     741                 :            :                     Edge_Lock_Case lock_case
     742                 :            :                 )
     743                 :            :             {
     744                 :            :                 // Loop over all edges
     745                 :            :                 // If the edge is in the intermediate_list, deal with it
     746         [ +  + ]:     325007 :                 for (const auto& p : tet_store.edge_store.edges)
     747                 :            :                 {
     748                 :     324936 :                     auto e = p.first;
     749                 :     324936 :                     size_t k1 = e.first();
     750         [ +  + ]:     324936 :                     size_t k2 = e.second();
     751                 :            :                     // Can we make this double search cheaper?
     752                 :            :                     if (
     753                 :            :                             (intermediate_list.count(k1)) ||
     754                 :            :                             (intermediate_list.count(k2))
     755                 :            :                        )
     756                 :            :                     {
     757                 :            :                         trace_out << "Locking intermediate " << e << " from " << k1 << " and " << k2 << std::endl;
     758                 :       2732 :                         tet_store.edge_store.get(e).lock_case = lock_case;
     759                 :       2732 :                         tet_store.edge_store.get(e).needs_refining = 0;
     760                 :            :                     }
     761                 :            :                 }
     762                 :            : 
     763                 :         71 :             }
     764                 :            : 
     765                 :            :             // TODO: remove this, it's horrible and not efficient.
     766                 :            :             // WARNING: THIS GOES OVER ALL TETS!!!!
     767                 :            :             void lock_edges_from_node(
     768                 :            :                     tet_store_t& tet_store,
     769                 :            :                     size_t node_id,
     770                 :            :                     Edge_Lock_Case lock_case
     771                 :            :             )
     772                 :            :             {
     773                 :            :                 // Iterate over edges of ALL tet
     774                 :            :                 for (const auto& kv : tet_store.tets)
     775                 :            :                 {
     776                 :            :                     size_t tet_id = kv.first;
     777                 :            :                     edge_list_t edge_list = tet_store.generate_edge_keys(tet_id);
     778                 :            :                     for (size_t k = 0; k < NUM_TET_EDGES; k++)
     779                 :            :                     {
     780                 :            :                         // If it contains that node id, mark it using lock_case
     781                 :            :                         edge_t edge = edge_list[k];
     782                 :            : 
     783                 :            :                         size_t edge_node_A_id = edge.first();
     784                 :            :                         size_t edge_node_B_id = edge.second();
     785                 :            : 
     786                 :            :                         if ((edge_node_A_id == node_id) || (edge_node_B_id == node_id)) {
     787                 :            :                             trace_out << " found node in " << edge_node_A_id << " - " << edge_node_B_id << " set to " << lock_case << std::endl;
     788                 :            :                             tet_store.edge_store.get(edge).lock_case = lock_case;
     789                 :            :                             tet_store.edge_store.get(edge).needs_refining = 0;
     790                 :            :                         }
     791                 :            :                     }
     792                 :            :                 }
     793                 :            :             }
     794                 :            : //            void lock_edges_from_node(
     795                 :            : //                    tet_store_t& tet_store,
     796                 :            : //                    size_t tet_id,
     797                 :            : //                    size_t node_id,
     798                 :            : //                    Edge_Lock_Case lock_case
     799                 :            : //            )
     800                 :            : //            {
     801                 :            : //                // Iterate over edges of of tet
     802                 :            : //                edge_list_t edge_list = tet_store.generate_edge_keys(tet_id);
     803                 :            : //                for (size_t k = 0; k < NUM_TET_EDGES; k++)
     804                 :            : //                {
     805                 :            : //                    // If it contains that node id, mark it using lock_case
     806                 :            : //                    edge_t edge = edge_list[k];
     807                 :            : //
     808                 :            : //                    size_t edge_node_A_id = edge.first();
     809                 :            : //                    size_t edge_node_B_id = edge.second();
     810                 :            : //
     811                 :            : //                    if ((edge_node_A_id == node_id) || (edge_node_B_id == node_id)) {
     812                 :            : //                        tet_store.edge_store.get(edge).lock_case = lock_case;
     813                 :            : //                    }
     814                 :            : //                }
     815                 :            : //            }
     816                 :            : 
     817                 :            : 
     818                 :            :             ///// DEREFINEMENT STARTS HERE /////
     819                 :            :             /**
     820                 :            :              * @brief Function to iterate over children and remove them
     821                 :            :              *
     822                 :            :              * @param tet_store Tet store to use
     823                 :            :              * @param parent_id Id of the parent for whom you will delete the
     824                 :            :              * children
     825                 :            :              */
     826                 :       6280 :             void derefine_children(tet_store_t& tet_store, size_t parent_id)
     827                 :            :             {
     828                 :            :                 // For a given tet_id, find and delete its children
     829                 :            :                 Refinement_State& parent = tet_store.data(parent_id);
     830         [ +  + ]:      55036 :                 for (auto c : parent.children)
     831                 :            :                 {
     832                 :      48756 :                     tet_store.erase(c);
     833                 :            :                     //tet_store.deactivate(c);
     834                 :            : 
     835                 :            :                     /*
     836                 :            :                     auto children = tet_store.data(c).children;
     837                 :            :                     // Debug printing
     838                 :            :                     std::cout << "tet " << c << "has ";
     839                 :            :                     for (auto child : children)
     840                 :            :                     {
     841                 :            :                         std::cout << " _child " << child;
     842                 :            :                     }
     843                 :            :                     std::cout << std::endl;
     844                 :            :                     */
     845                 :            :                 }
     846                 :            :                 parent.children.clear();
     847                 :       6280 :             }
     848                 :            : 
     849                 :            :             /**
     850                 :            :              * @brief Common code for derefinement. Deactives the children and
     851                 :            :              * actives the parent
     852                 :            :              *
     853                 :            :              * @param tet_store Tet store to use
     854                 :            :              * @param parent_id The id of the parent
     855                 :            :              */
     856                 :            :             void generic_derefine(tet_store_t& tet_store, size_t parent_id)
     857                 :            :             {
     858                 :        306 :                 derefine_children(tet_store,parent_id);
     859                 :       6280 :                 tet_store.activate(parent_id);
     860                 :            :             }
     861                 :            : 
     862                 :            :             /**
     863                 :            :              * @brief Perform 2->1 derefinement on tet
     864                 :            :              *
     865                 :            :              * @param tet_store Tet store to use
     866                 :            :              * @param parent_id The id of the parent
     867                 :            :              */
     868                 :        130 :             void derefine_two_to_one(tet_store_t& tet_store, node_connectivity_t&, size_t parent_id)
     869                 :            :             {
     870                 :            :                 //if (!check_allowed_derefinement(tet_store,parent_id)) return;
     871                 :            :                 // build a delete-list of edges/intermediates first, mesh_adapter
     872                 :            :                 // deletes edges from this list later
     873                 :        130 :                 determine_deletelist_of_intermediates(tet_store, parent_id);
     874                 :            :                 generic_derefine(tet_store,parent_id);
     875                 :        130 :             }
     876                 :            : 
     877                 :            :             /**
     878                 :            :              * @brief Perform 4->1 derefinement on tet
     879                 :            :              *
     880                 :            :              * @param tet_store Tet store to use
     881                 :            :              * @param parent_id The id of the parent
     882                 :            :              */
     883                 :        176 :             void derefine_four_to_one(tet_store_t& tet_store, node_connectivity_t&, size_t parent_id)
     884                 :            :             {
     885                 :            :                 //if (!check_allowed_derefinement(tet_store,parent_id)) return;
     886                 :            :                 // build a delete-list of edges/intermediates first, mesh_adapter
     887                 :            :                 // deletes edges from this list later
     888                 :        176 :                 determine_deletelist_of_intermediates(tet_store, parent_id);
     889                 :            :                 generic_derefine(tet_store,parent_id);
     890                 :        176 :             }
     891                 :            : 
     892                 :            :             /**
     893                 :            :              * @brief Perform 8->1 derefinement on tet
     894                 :            :              *
     895                 :            :              * @param tet_store Tet store to use
     896                 :            :              * @param parent_id The id of the parent
     897                 :            :              */
     898                 :       5974 :             void derefine_eight_to_one(tet_store_t& tet_store, node_connectivity_t&, size_t parent_id)
     899                 :            :             {
     900                 :            :                 //if (!check_allowed_derefinement(tet_store,parent_id)) return;
     901                 :            : 
     902                 :            :                 generic_derefine(tet_store,parent_id);
     903                 :            : 
     904                 :            :                 // TODO: Do we delete the nodes? Do we even have nodes?
     905                 :            : 
     906                 :            :                 // Delete the center edges
     907                 :            :                     // If edge isn't in the parent, delete it? Is there a better way?
     908                 :       5974 :                 edge_list_t parent_edges = tet_store.generate_edge_keys(parent_id);
     909                 :            : 
     910                 :            :                 Refinement_State& parent = tet_store.data(parent_id);
     911         [ -  + ]:       5974 :                 for (auto c : parent.children)
     912                 :            :                 {
     913                 :          0 :                     edge_list_t child_edges = tet_store.generate_edge_keys(c);
     914                 :            :                     // build a delete-list of non-matching edges first, then
     915                 :            :                     // mesh_adapter deletes edges from this list later
     916                 :          0 :                     determine_deletelist_of_non_matching_edges(child_edges, parent_edges);
     917                 :            :                 }
     918                 :       5974 :             }
     919                 :            : 
     920                 :            :             // TODO: Document This.
     921                 :          0 :             void derefine_four_to_two(tet_store_t& tet_store, node_connectivity_t& node_connectivity, size_t parent_id)
     922                 :            :             {
     923                 :            :                 //if (!check_allowed_derefinement(tet_store,parent_id)) return;
     924                 :            : 
     925                 :            :                 // A 4:2 (implemented as a 4:1 + 1:2) keeps three child edges,
     926                 :            :                 // two of which are from the 1:2 splitting. The third edge
     927                 :            :                 // connects the opposite parent node with the intermediate node
     928                 :            :                 // (of the 1:2 splitting). Figure out which is this edge, and
     929                 :            :                 // remove it from the delete list.
     930                 :            :                 // 1. first store the possible edges that connect parent nodes
     931                 :            :                 //    with the intermediate node of the 1:2. There are 2
     932                 :            :                 //    possibilities, because we can already eliminate the
     933                 :            :                 //    parents of the intermediate node.
     934                 :          0 :                 auto edge = find_edge_not_derefined(tet_store,
     935                 :            :                   node_connectivity, parent_id);
     936                 :            : 
     937                 :            :                 std::array< edge_t, 2 > int_par_edges;
     938                 :          0 :                 auto parent_tet = tet_store.get(parent_id);
     939                 :          0 :                 auto npnode = node_connectivity.data().at(edge.get_data());
     940                 :            :                 size_t icount(0);
     941         [ -  - ]:          0 :                 for (size_t i=0; i<NUM_TET_NODES; ++i) {
     942 [ -  - ][ -  - ]:          0 :                   if (parent_tet[i] != edge.first() &&
     943                 :            :                     parent_tet[i] != edge.second()) {
     944                 :          0 :                     int_par_edges[icount] = edge_t(parent_tet[i], npnode);
     945                 :          0 :                     ++icount;
     946                 :            :                   }
     947                 :            :                 }
     948                 :            :                 assert(icount == 2);
     949                 :            : 
     950                 :            :                 // 2. find which one of these edges is present in the 4 children
     951                 :          0 :                 child_id_list_t children = tet_store.data(parent_id).children;
     952                 :            :                 bool ipedge_set = false;
     953                 :            :                 edge_t int_par_edge;
     954         [ -  - ]:          0 :                 for (size_t i=0; i<children.size(); i++) {
     955         [ -  - ]:          0 :                   edge_list_t chedge_list = tet_store.generate_edge_keys(children[i]);
     956                 :            :                   // Check each edge, and compare with possible edges
     957         [ -  - ]:          0 :                   for (size_t k=0; k<NUM_TET_EDGES; k++) {
     958         [ -  - ]:          0 :                     for (const auto& ipedge : int_par_edges) {
     959                 :            :                       if (chedge_list[k] == ipedge) {
     960                 :          0 :                         int_par_edge = ipedge;
     961                 :            :                         ipedge_set = true;
     962                 :          0 :                         break;
     963                 :            :                       }
     964                 :            :                     }
     965                 :            :                   }
     966                 :            :                 }
     967                 :            :                 assert(ipedge_set);
     968                 :            : 
     969         [ -  - ]:          0 :                 derefine_four_to_one(tet_store, node_connectivity, parent_id);
     970         [ -  - ]:          0 :                 refine_one_to_two( tet_store, node_connectivity, parent_id,
     971                 :            :                   edge.first(), edge.second() );
     972                 :            : 
     973                 :            :                 // remove edge not derefined from delete list
     974                 :            :                 delete_list.erase(int_par_edge);
     975                 :            :                 std::vector< edge_t > parent_edges;
     976         [ -  - ]:          0 :                 parent_edges.push_back(edge);
     977         [ -  - ]:          0 :                 remove_from_deletelist(node_connectivity, parent_edges);
     978                 :          0 :             }
     979                 :            : 
     980                 :            :             // TODO: Document This.
     981                 :          0 :             void derefine_eight_to_two(tet_store_t& tet_store, node_connectivity_t& node_connectivity, size_t parent_id)
     982                 :            :             {
     983                 :            :                 //if (!check_allowed_derefinement(tet_store,parent_id)) return;
     984                 :            : 
     985                 :          0 :                 auto edge = find_edge_not_derefined(tet_store,
     986                 :            :                   node_connectivity, parent_id);
     987                 :          0 :                 derefine_eight_to_one(tet_store, node_connectivity, parent_id);
     988                 :          0 :                 refine_one_to_two( tet_store, node_connectivity, parent_id,
     989                 :            :                   edge.first(), edge.second() );
     990                 :            :                 // remove edge not derefined from delete list
     991                 :            :                 std::vector< edge_t > parent_edges;
     992         [ -  - ]:          0 :                 parent_edges.push_back(edge);
     993         [ -  - ]:          0 :                 remove_from_deletelist(node_connectivity, parent_edges);
     994                 :          0 :             }
     995                 :            : 
     996                 :            :             // TODO: Document This.
     997                 :          0 :             void derefine_eight_to_four(tet_store_t& tet_store, node_connectivity_t& node_connectivity, size_t parent_id)
     998                 :            :             {
     999                 :            :                 //if (!check_allowed_derefinement(tet_store,parent_id)) return;
    1000                 :            :                 // TODO: think about if the logic for these derefs are right
    1001                 :          0 :                 derefine_eight_to_one(tet_store, node_connectivity, parent_id);
    1002                 :            :                 std::vector< edge_t > kept_edges;
    1003         [ -  - ]:          0 :                 deref_refine_one_to_four( tet_store, node_connectivity,
    1004                 :            :                   parent_id, kept_edges);
    1005                 :            :                 // remove edge not derefined from delete list
    1006         [ -  - ]:          0 :                 remove_from_deletelist(node_connectivity, kept_edges);
    1007                 :          0 :             }
    1008                 :            : 
    1009                 :            :             /**
    1010                 :            :              * @brief Loop over children and determine delete-list of all intermediate edges
    1011                 :            :              *
    1012                 :            :              * @param tet_store Tet store to use
    1013                 :            :              * @param parent_id Id of parent
    1014                 :            :              */
    1015                 :        306 :             void determine_deletelist_of_intermediates(tet_store_t& tet_store, size_t parent_id)
    1016                 :            :             {
    1017                 :            :                 Refinement_State& parent = tet_store.data(parent_id);
    1018                 :        306 :                 auto parent_edges = tet_store.generate_edge_keys(parent_id);
    1019                 :            :                 std::set< edge_t > parent_edge_set;
    1020 [ +  - ][ +  + ]:       2142 :                 for (auto pe:parent_edges) parent_edge_set.insert(pe);
    1021         [ +  + ]:       1270 :                 for (auto c : parent.children)
    1022                 :            :                 {
    1023         [ +  - ]:        964 :                     edge_list_t edge_list = tet_store.generate_edge_keys(c);
    1024         [ +  + ]:       6748 :                     for (size_t k = 0; k < NUM_TET_EDGES; k++)
    1025                 :            :                     {
    1026         [ -  + ]:       5784 :                         edge_t edge = edge_list[k];
    1027                 :            :                         // accept this code may try delete an edge which has already gone
    1028         [ +  + ]:       5784 :                         if (tet_store.edge_store.exists(edge)) {
    1029                 :            :                             if (parent_edge_set.count(edge) == 0)
    1030                 :            :                             {
    1031                 :            :                                 trace_out << "child " << c << " adding to delete list: "
    1032                 :            :                                   << edge.first() << " - " << edge.second() << std::endl;
    1033                 :            :                                 delete_list.insert(edge);
    1034                 :            :                             }
    1035                 :            :                         }
    1036                 :            :                     }
    1037                 :            :                 }
    1038                 :        306 :             }
    1039                 :            : 
    1040                 :            :             /**
    1041                 :            :              * @brief Remove 'intermediate' edges (based on parent edges) from
    1042                 :            :              *   delete list
    1043                 :            :              *
    1044                 :            :              * @param node_connectivity Node connectivity data structure
    1045                 :            :              * @param parent_edges List of parent edges whose 'child' edges need
    1046                 :            :              *   to be removed from the delete list
    1047                 :            :              */
    1048                 :          0 :             void remove_from_deletelist(
    1049                 :            :               node_connectivity_t& node_connectivity,
    1050                 :            :               const std::vector< edge_t >& parent_edges )
    1051                 :            :             {
    1052         [ -  - ]:          0 :               for (const auto& edge:parent_edges) {
    1053         [ -  - ]:          0 :                 auto npnode = node_connectivity.data().at(edge.get_data());
    1054         [ -  - ]:          0 :                 edge_t e1(edge.first(),npnode);
    1055                 :          0 :                 edge_t e2(edge.second(),npnode);
    1056                 :            :                 delete_list.erase(e1);
    1057                 :            :                 delete_list.erase(e2);
    1058                 :            :               }
    1059                 :          0 :             }
    1060                 :            : 
    1061                 :            :             /**
    1062                 :            :              * @brief Deletes the intermediate edge in the delete list for derefinement
    1063                 :            :              *
    1064                 :            :              * @param tet_store Tet store to use
    1065                 :            :              */
    1066                 :         24 :             void delete_intermediates_of_children(tet_store_t& tet_store)
    1067                 :            :             {
    1068         [ +  + ]:       1586 :               for (const auto& edge : delete_list) {
    1069                 :       1562 :                 tet_store.edge_store.erase(edge);
    1070                 :            :                 tet_store.intermediate_list.erase(edge.get_data()[0]);
    1071                 :            :                 tet_store.intermediate_list.erase(edge.get_data()[1]);
    1072                 :            :               }
    1073                 :            : 
    1074                 :            :               delete_list.clear();
    1075                 :         24 :             }
    1076                 :            : 
    1077                 :            :             /**
    1078                 :            :              * @brief If edge in candidate is not present in basis, add edge
    1079                 :            :              * (candidate) to delete list
    1080                 :            :              *
    1081                 :            :              * @param candidate The edge list which is to be searched and deleted
    1082                 :            :              * @param basis The edge list to check against
    1083                 :            :              */
    1084                 :          0 :             void determine_deletelist_of_non_matching_edges(edge_list_t candidate,
    1085                 :            :               edge_list_t basis)
    1086                 :            :             {
    1087                 :            :                 trace_out << "Looking for edges to delete" << std::endl;
    1088                 :            : 
    1089                 :            :                 // TODO: Sanity check this now we changed to edge_t
    1090                 :            : 
    1091                 :            :                 // Loop over the edges in each child. Look over the basis and
    1092                 :            :                 // if we can't find it, delete it
    1093         [ -  - ]:          0 :                 for (size_t k = 0; k < NUM_TET_EDGES; k++)
    1094                 :            :                 {
    1095                 :          0 :                     edge_t search_key = candidate[k];
    1096                 :            : 
    1097                 :            :                     // Search the basis for it
    1098                 :            :                     bool found_it = false;
    1099                 :            : 
    1100         [ -  - ]:          0 :                     for (size_t l = 0; l < NUM_TET_EDGES; l++)
    1101                 :            :                     {
    1102         [ -  - ]:          0 :                         edge_t key = basis[l];
    1103                 :            :                         if (search_key == key)
    1104                 :            :                         {
    1105                 :            :                             found_it = true;
    1106                 :            :                         }
    1107                 :            :                     }
    1108                 :            : 
    1109                 :            :                     // If we didn't find it, delete it
    1110         [ -  - ]:          0 :                     if (!found_it)
    1111                 :            :                     {
    1112                 :            :                         // Delete it
    1113                 :            :                         //tet_store.edge_store.erase(search_key);
    1114                 :            :                         trace_out << "adding to delete list: "
    1115                 :            :                           << search_key.first() << " - " << search_key.second()
    1116                 :            :                           << std::endl;
    1117                 :            :                         delete_list.insert(search_key);
    1118                 :            :                     }
    1119                 :            :                 }
    1120                 :          0 :             }
    1121                 :            : 
    1122                 :            : 
    1123                 :            :             /**
    1124                 :            :              * @brief function to detect when an invalid derefinement is
    1125                 :            :              * invoked
    1126                 :            :              *
    1127                 :            :              * @param tet_store Tet store to use
    1128                 :            :              * @param tet_id Id the of the tet which will be de-refined
    1129                 :            :              *
    1130                 :            :              * @return A bool stating if the tet can be validly de-refined
    1131                 :            :              */
    1132                 :            :             bool check_allowed_derefinement( tet_store_t& tet_store, size_t tet_id)
    1133                 :            :             {
    1134                 :            :                 Refinement_State& master_element = tet_store.data(tet_id);
    1135                 :            : 
    1136                 :            :                 // Check this won't take us past the max refinement level
    1137                 :            :                 if (master_element.refinement_level <= MIN_REFINEMENT_LEVEL)
    1138                 :            :                 {
    1139                 :            :                     return false;
    1140                 :            :                 }
    1141                 :            : 
    1142                 :            :                 // If we got here, we didn't detect anything which tells us not
    1143                 :            :                 // to
    1144                 :            :                 return true;
    1145                 :            :             }
    1146                 :            : 
    1147                 :            : 
    1148                 :            :             // HERE BE DRAGONS! THIS IS DANGEROUS IF YOU USE IT WRONG
    1149                 :            :             // For every child of parent_id, set his children to our won
    1150                 :            :             // TODO: set a flag for the curious user to know we trashed the children
    1151                 :            :             void overwrite_children(
    1152                 :            :                     tet_store_t& tet_store,
    1153                 :            :                     const child_id_list_t& to_be_replaced,
    1154                 :            :                     const child_id_list_t& replace_with
    1155                 :            :             )
    1156                 :            :             {
    1157                 :            :                 for (auto c : to_be_replaced)
    1158                 :            :                 {
    1159                 :            :                     tet_store.data(c).children = replace_with;
    1160                 :            :                 }
    1161                 :            :             }
    1162                 :            : 
    1163                 :            :             /**
    1164                 :            :              * @brief function to detect which edge should not get derefined
    1165                 :            :              *
    1166                 :            :              * @param tet_store Tet store to use
    1167                 :            :              * @param node_connectivity Node connectivity to use
    1168                 :            :              * @param tet_id Id the of the tet which will be de-refined
    1169                 :            :              *
    1170                 :            :              * @return Array of size two containing nodes of required edge
    1171                 :            :              */
    1172                 :          0 :             edge_t find_edge_not_derefined(
    1173                 :            :               tet_store_t& tet_store,
    1174                 :            :               node_connectivity_t& node_connectivity,
    1175                 :            :               size_t tet_id)
    1176                 :            :             {
    1177                 :            :               // 2 nonparent nodes set to derefine for a 4:2
    1178                 :            :               // 5 nonparent nodes set to derefine for an 8:2
    1179                 :            :               // will have 2 or 5 nonparent nodes set to deref; Figure out which
    1180                 :            :               // edge is the one that is not set to deref
    1181                 :            : 
    1182                 :          0 :               auto derefine_node_set = find_derefine_node_set(tet_store, tet_id);
    1183                 :            : 
    1184                 :            :               //// Do number of points
    1185                 :            :               //std::unordered_set<size_t> derefine_node_set;
    1186                 :            : 
    1187                 :            :               // Find the set of nodes which are not in the parent
    1188                 :            :               std::unordered_set<size_t> non_parent_nodes =
    1189         [ -  - ]:          0 :                 child_exclusive_nodes(tet_store, tet_id);
    1190                 :            : 
    1191                 :            :               // from the above non_parent_nodes set and derefine_node_set,
    1192                 :            :               // figureout which node should be removed
    1193                 :            :               std::size_t ed_A(0), ed_B(0);
    1194 [ -  - ][ -  - ]:          0 :               for (auto npn:non_parent_nodes) {
    1195                 :            :                 if (derefine_node_set.count(npn) == 0) {
    1196                 :            :                   // we've found the node that should not be removed, now we
    1197                 :            :                   // need to find the edge it belongs to
    1198                 :          0 :                   auto nonderef_edge = node_connectivity.get(npn);
    1199                 :            :                   ed_A = nonderef_edge[0];
    1200                 :            :                   ed_B = nonderef_edge[1];
    1201                 :            :                   //std::cout << "do-not-deref-APAN " << "A " << nd_edge[0]
    1202                 :            :                   //        << " B " << nd_edge[1] << std::endl;
    1203                 :            :                 }
    1204                 :            :               }
    1205                 :            : 
    1206                 :            :               assert(ed_A!=ed_B);
    1207                 :          0 :               edge_t nd_edge(ed_A, ed_B);
    1208                 :          0 :               return nd_edge;
    1209                 :            :             }
    1210                 :            : 
    1211                 :            :             /**
    1212                 :            :              * @brief function to detect what intermediate/non-parent nodes are
    1213                 :            :              *   marked for derefinement
    1214                 :            :              *
    1215                 :            :              * @param tet_store Tet store to use
    1216                 :            :              * @param tet_id Id of the tet which will be de-refined
    1217                 :            :              *
    1218                 :            :              * @return Set of nodes of marked for derefinement
    1219                 :            :              */
    1220                 :      14212 :             std::unordered_set< size_t > find_derefine_node_set(
    1221                 :            :               tet_store_t& tet_store,
    1222                 :            :               size_t tet_id)
    1223                 :            :             {
    1224                 :            :               // Set of nodes which are not in the parent
    1225                 :            :               std::unordered_set<size_t> non_parent_nodes =
    1226                 :      14212 :                 child_exclusive_nodes(tet_store, tet_id);
    1227                 :            :               std::unordered_set<size_t> derefine_node_set, unmarked_deref_node_set,
    1228                 :            :                 final_deref_node_set;
    1229                 :            : 
    1230         [ +  - ]:      14212 :               child_id_list_t children = tet_store.data(tet_id).children;
    1231                 :            : 
    1232                 :            :               // Look at children
    1233                 :            :               trace_out << tet_id << " Looping over " << children.size() << "children" << std::endl;
    1234         [ +  + ]:     123632 :               for (size_t i = 0; i < children.size(); i++)
    1235                 :            :               {
    1236                 :            :                   trace_out << "child: " << children[i] << std::endl;
    1237                 :            :                   // TODO: Is this in element or tet ids?
    1238         [ +  - ]:     109420 :                   edge_list_t edge_list = tet_store.generate_edge_keys(children[i]);
    1239         [ +  + ]:     765940 :                   for (size_t k = 0; k < NUM_TET_EDGES; k++)
    1240                 :            :                   {
    1241                 :     656520 :                       edge_t edge = edge_list[k];
    1242                 :            :                       // TODO: where do we makr the edges that need to be derefed? parent of child?
    1243                 :            :                       // Check each node, see if its an intermediate
    1244                 :     656520 :                       size_t A = edge.first();
    1245         [ +  + ]:     656520 :                       size_t B = edge.second();
    1246                 :            :                       trace_out << "checking edge for deref " << A << " - " << B << std::endl;
    1247                 :            : 
    1248                 :            :                       //if (tet_store.is_intermediate(A))
    1249                 :            :                       if (non_parent_nodes.count(A) )
    1250                 :            :                       {
    1251 [ +  - ][ +  + ]:     482964 :                         if (tet_store.edge_store.get(edge).needs_derefining) {
    1252                 :            :                           trace_out << "Adding " << A << std::endl;
    1253                 :            :                           derefine_node_set.insert(A);
    1254                 :            :                         }
    1255                 :            :                         else {
    1256                 :            :                           unmarked_deref_node_set.insert(A);
    1257                 :            :                           //trace_out << "NOT added " << A << std::endl;
    1258                 :            :                         }
    1259                 :            :                       }
    1260                 :            : 
    1261                 :            :                       //if (tet_store.is_intermediate(B))
    1262                 :            :                       if (non_parent_nodes.count(B))
    1263                 :            :                       {
    1264 [ +  - ][ +  + ]:     652746 :                         if (tet_store.edge_store.get(edge).needs_derefining) {
    1265                 :            :                           trace_out << "Adding " << B << std::endl;
    1266                 :            :                           derefine_node_set.insert(B);
    1267                 :            :                         }
    1268                 :            :                         else {
    1269                 :            :                           unmarked_deref_node_set.insert(B);
    1270                 :            :                           //trace_out << "NOT added " << B << std::endl;
    1271                 :            :                         }
    1272                 :            :                       }
    1273                 :            :                   }
    1274                 :            :               }
    1275                 :            : 
    1276                 :            :               //trace_out << "marked for deref: " << derefine_node_set.size() << std::endl;
    1277                 :            :               //trace_out << "NOT marked for deref: " << unmarked_deref_node_set.size() << std::endl;
    1278                 :            : 
    1279                 :            :               // remove nodes that are unmarked for derefinement
    1280 [ +  + ][ +  + ]:      95470 :               for (auto drnode : derefine_node_set) {
    1281                 :            :                 if (unmarked_deref_node_set.count(drnode) == 0) {
    1282                 :            :                   final_deref_node_set.insert(drnode);
    1283                 :            :                   trace_out << "Final deref node " << drnode << std::endl;
    1284                 :            :                 }
    1285                 :            :               }
    1286                 :            : 
    1287                 :            :               derefine_node_set = final_deref_node_set;
    1288                 :      14212 :               return derefine_node_set;
    1289                 :            :             }
    1290                 :            : 
    1291                 :            : 
    1292         [ +  - ]:      28424 :             std::unordered_set<size_t> child_exclusive_nodes(tet_store_t& tet_store,
    1293                 :            :               size_t tet_id)
    1294                 :            :             {
    1295                 :            :               std::unordered_set<size_t> non_parent_nodes;
    1296                 :            : 
    1297                 :            :               // array
    1298         [ +  - ]:      28424 :               auto parent_tet = tet_store.get(tet_id);
    1299                 :            : 
    1300                 :            :               // convert to set
    1301         [ +  - ]:      28424 :               std::unordered_set<size_t> parent_set(begin(parent_tet), end(parent_tet));
    1302                 :            : 
    1303         [ +  - ]:      28424 :               child_id_list_t children = tet_store.data(tet_id).children;
    1304         [ +  + ]:     247264 :               for (size_t i = 0; i < children.size(); i++)
    1305                 :            :               {
    1306         [ +  - ]:     218840 :                       auto child_tet = tet_store.get( children[i] );
    1307                 :            : 
    1308                 :            :                       // Look at nodes, if not present add to set
    1309         [ +  + ]:    1094200 :                       for (std::size_t j = 0; j < NUM_TET_NODES; j++)
    1310                 :            :                       {
    1311         [ +  + ]:     875360 :                               auto node = child_tet[j];
    1312                 :            :                               if (parent_set.count(node) == 0)
    1313                 :            :                               {
    1314                 :            :                                       non_parent_nodes.insert(node);
    1315                 :            :                               }
    1316                 :            :                       }
    1317                 :            :               }
    1318                 :            : 
    1319                 :            :               trace_out <<" Found " << non_parent_nodes.size() << " non parent nodes " << std::endl;
    1320                 :      28424 :               return non_parent_nodes;
    1321                 :            : 
    1322                 :            :             }
    1323                 :            :     };
    1324                 :            : }
    1325                 :            : 
    1326                 :            : #if defined(__clang__)
    1327                 :            :   #pragma clang diagnostic pop
    1328                 :            : #elif defined(STRICT_GNUC)
    1329                 :            :   #pragma GCC diagnostic pop
    1330                 :            : #endif
    1331                 :            : 
    1332                 :            : #endif // guard

Generated by: LCOV version 1.16