LCOV - code coverage report
Current view: top level - src/efa - ElementFragmentAlgorithm.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31405 (292dce) with base fef103 Lines: 257 300 85.7 %
Date: 2025-09-04 07:58:55 Functions: 23 25 92.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : // TODO:
      11             : // Clean up error checking in (!found_edge)
      12             : // Save fragment for uncut element ahead of crack tip to avoid renumbering if only embedded node
      13             : // Add common code to compare neighbors & fragments (replace multiple set_intersection calls)
      14             : 
      15             : // Handle cases other than 0 or 2 cut edges/elem (include data structure to link cut edges with
      16             : // cracks?)
      17             : // Allow for more than one cut on an edge
      18             : // Support 2d higher order elements
      19             : // 3D propagation
      20             : // 3D branching
      21             : 
      22             : #include "ElementFragmentAlgorithm.h"
      23             : 
      24             : #include "EFANode.h"
      25             : #include "EFAElement3D.h"
      26             : #include "EFAElement2D.h"
      27             : #include "EFAFuncs.h"
      28             : #include "EFAError.h"
      29             : 
      30         452 : ElementFragmentAlgorithm::ElementFragmentAlgorithm(std::ostream & os) : _ostream(os) {}
      31             : 
      32         450 : ElementFragmentAlgorithm::~ElementFragmentAlgorithm()
      33             : {
      34             :   std::map<unsigned int, EFANode *>::iterator mit;
      35       83552 :   for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
      36             :   {
      37       83102 :     delete mit->second;
      38       83102 :     mit->second = nullptr;
      39             :   }
      40        6798 :   for (mit = _embedded_nodes.begin(); mit != _embedded_nodes.end(); ++mit)
      41             :   {
      42        6348 :     delete mit->second;
      43        6348 :     mit->second = nullptr;
      44             :   }
      45         510 :   for (mit = _embedded_permanent_nodes.begin(); mit != _embedded_permanent_nodes.end(); ++mit)
      46             :   {
      47          60 :     delete mit->second;
      48          60 :     mit->second = nullptr;
      49             :   }
      50         450 :   for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
      51             :   {
      52           0 :     delete mit->second;
      53           0 :     mit->second = nullptr;
      54             :   }
      55             :   std::map<unsigned int, EFAElement *>::iterator eit;
      56       47070 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
      57             :   {
      58       46620 :     delete eit->second;
      59       46620 :     eit->second = nullptr;
      60             :   }
      61         450 : }
      62             : 
      63             : unsigned int
      64           9 : ElementFragmentAlgorithm::add2DElements(std::vector<std::vector<unsigned int>> & quads)
      65             : {
      66             :   unsigned int first_id = 0;
      67           9 :   unsigned int num_nodes = quads[0].size();
      68             : 
      69           9 :   if (quads.size() == 0)
      70           0 :     EFAError("add2DElements called with empty vector of quads");
      71             : 
      72          41 :   for (unsigned int i = 0; i < quads.size(); ++i)
      73             :   {
      74          32 :     unsigned int new_elem_id = Efa::getNewID(_elements);
      75          32 :     EFAElement2D * newElem = new EFAElement2D(new_elem_id, num_nodes);
      76          32 :     _elements.insert(std::make_pair(new_elem_id, newElem));
      77             : 
      78          32 :     if (i == 0)
      79             :       first_id = new_elem_id;
      80             : 
      81         160 :     for (unsigned int j = 0; j < num_nodes; ++j)
      82             :     {
      83         128 :       EFANode * currNode = nullptr;
      84         128 :       std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quads[i][j]);
      85         128 :       if (mit == _permanent_nodes.end())
      86             :       {
      87          71 :         currNode = new EFANode(quads[i][j], EFANode::N_CATEGORY_PERMANENT);
      88          71 :         _permanent_nodes.insert(std::make_pair(quads[i][j], currNode));
      89             :       }
      90             :       else
      91          57 :         currNode = mit->second;
      92             : 
      93         128 :       newElem->setNode(j, currNode);
      94         128 :       _inverse_connectivity[currNode].insert(newElem);
      95             :     }
      96          32 :     newElem->createEdges();
      97             :   }
      98           9 :   return first_id;
      99             : }
     100             : 
     101             : EFAElement *
     102      385302 : ElementFragmentAlgorithm::add2DElement(const std::vector<unsigned int> & quad, unsigned int id)
     103             : {
     104      385302 :   unsigned int num_nodes = quad.size();
     105             : 
     106             :   std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
     107      385302 :   if (mit != _elements.end())
     108           0 :     EFAError("In add2DElement element with id: ", id, " already exists");
     109             : 
     110      385302 :   EFAElement2D * newElem = new EFAElement2D(id, num_nodes);
     111      385302 :   _elements.insert(std::make_pair(id, newElem));
     112             : 
     113     1995310 :   for (unsigned int j = 0; j < num_nodes; ++j)
     114             :   {
     115     1610008 :     EFANode * currNode = nullptr;
     116     1610008 :     std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quad[j]);
     117     1610008 :     if (mit == _permanent_nodes.end())
     118             :     {
     119      505594 :       currNode = new EFANode(quad[j], EFANode::N_CATEGORY_PERMANENT);
     120      505594 :       _permanent_nodes.insert(std::make_pair(quad[j], currNode));
     121             :     }
     122             :     else
     123     1104414 :       currNode = mit->second;
     124             : 
     125     1610008 :     newElem->setNode(j, currNode);
     126     1610008 :     _inverse_connectivity[currNode].insert(newElem);
     127             :   }
     128      385302 :   newElem->createEdges();
     129      385302 :   return newElem;
     130             : }
     131             : 
     132             : EFAElement *
     133       40763 : ElementFragmentAlgorithm::add3DElement(const std::vector<unsigned int> & quad, unsigned int id)
     134             : {
     135       40763 :   unsigned int num_nodes = quad.size();
     136             :   unsigned int num_faces = 0;
     137       40763 :   if (num_nodes == 8 || num_nodes == 20 || num_nodes == 27)
     138             :     num_faces = 6;
     139             :   else if (num_nodes == 4 || num_nodes == 10 || num_nodes == 14)
     140             :     num_faces = 4;
     141             :   else
     142           0 :     EFAError("In add3DElement element with id: ", id, " has invalid num_nodes");
     143             : 
     144             :   std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
     145       40763 :   if (mit != _elements.end())
     146           0 :     EFAError("In add3DElement element with id: ", id, " already exists");
     147             : 
     148       40763 :   EFAElement3D * newElem = new EFAElement3D(id, num_nodes, num_faces);
     149       40763 :   _elements.insert(std::make_pair(id, newElem));
     150             : 
     151      458007 :   for (unsigned int j = 0; j < num_nodes; ++j)
     152             :   {
     153      417244 :     EFANode * currNode = nullptr;
     154      417244 :     std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quad[j]);
     155      417244 :     if (mit == _permanent_nodes.end())
     156             :     {
     157      111982 :       currNode = new EFANode(quad[j], EFANode::N_CATEGORY_PERMANENT);
     158      111982 :       _permanent_nodes.insert(std::make_pair(quad[j], currNode));
     159             :     }
     160             :     else
     161      305262 :       currNode = mit->second;
     162             : 
     163      417244 :     newElem->setNode(j, currNode);
     164      417244 :     _inverse_connectivity[currNode].insert(newElem);
     165             :   }
     166       40763 :   newElem->createFaces();
     167       40763 :   return newElem;
     168             : }
     169             : 
     170             : void
     171        3210 : ElementFragmentAlgorithm::updateEdgeNeighbors()
     172             : {
     173             :   std::map<unsigned int, EFAElement *>::iterator eit;
     174      429654 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
     175             :   {
     176      426444 :     EFAElement * elem = eit->second;
     177      426444 :     elem->clearNeighbors();
     178             :   }
     179             : 
     180      429654 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
     181             :   {
     182      426444 :     EFAElement * curr_elem = eit->second;
     183      426444 :     curr_elem->setupNeighbors(_inverse_connectivity);
     184             :   } // loop over all elements
     185             : 
     186      429654 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
     187             :   {
     188      426444 :     EFAElement * curr_elem = eit->second;
     189      426444 :     curr_elem->neighborSanityCheck();
     190             :   }
     191        3210 : }
     192             : 
     193             : void
     194        3179 : ElementFragmentAlgorithm::initCrackTipTopology()
     195             : {
     196             :   _crack_tip_elements.clear(); // re-build CrackTipElements!
     197      429398 :   for (auto pair : _elements)
     198      426219 :     pair.second->initCrackTip(_crack_tip_elements); // CrackTipElements changed here
     199        3179 : }
     200             : 
     201             : void
     202       47183 : ElementFragmentAlgorithm::addElemEdgeIntersection(unsigned int elemid,
     203             :                                                   unsigned int edgeid,
     204             :                                                   double position)
     205             : {
     206             :   // this method is called when we are marking cut edges
     207             :   auto eit = _elements.find(elemid);
     208       47183 :   if (eit == _elements.end())
     209           0 :     EFAError("Could not find element with id: ", elemid, " in addEdgeIntersection");
     210             : 
     211       47183 :   EFAElement2D * curr_elem = dynamic_cast<EFAElement2D *>(eit->second);
     212       47183 :   if (!curr_elem)
     213           0 :     EFAError("addElemEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
     214       47183 :   curr_elem->addEdgeCut(edgeid, position, nullptr, _embedded_nodes, true);
     215       47183 : }
     216             : 
     217             : void
     218         346 : ElementFragmentAlgorithm::addElemNodeIntersection(unsigned int elemid, unsigned int nodeid)
     219             : {
     220             :   // this method is called when we are marking cut nodes
     221             :   auto eit = _elements.find(elemid);
     222         346 :   if (eit == _elements.end())
     223           0 :     EFAError("Could not find element with id: ", elemid, " in addElemNodeIntersection");
     224             : 
     225         346 :   EFAElement2D * curr_elem = dynamic_cast<EFAElement2D *>(eit->second);
     226         346 :   if (!curr_elem)
     227           0 :     EFAError("addElemNodeIntersection: elem ", elemid, " is not of type EFAelement2D");
     228             : 
     229             :   // Only add cut node when the curr_elem does not have any fragment
     230         346 :   if (curr_elem->numFragments() == 0)
     231         136 :     curr_elem->addNodeCut(nodeid, nullptr, _permanent_nodes, _embedded_permanent_nodes);
     232         346 : }
     233             : 
     234             : bool
     235       35290 : ElementFragmentAlgorithm::addFragEdgeIntersection(unsigned int elemid,
     236             :                                                   unsigned int frag_edge_id,
     237             :                                                   double position)
     238             : {
     239             :   // N.B. this method must be called after addEdgeIntersection
     240             :   auto eit = _elements.find(elemid);
     241       35290 :   if (eit == _elements.end())
     242           0 :     EFAError("Could not find element with id: ", elemid, " in addFragEdgeIntersection");
     243             : 
     244       35290 :   EFAElement2D * elem = dynamic_cast<EFAElement2D *>(eit->second);
     245       35290 :   if (!elem)
     246           0 :     EFAError("addFragEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
     247       35290 :   return elem->addFragmentEdgeCut(frag_edge_id, position, _embedded_nodes);
     248             : }
     249             : 
     250             : void
     251       15947 : ElementFragmentAlgorithm::addElemFaceIntersection(unsigned int elemid,
     252             :                                                   unsigned int faceid,
     253             :                                                   const std::vector<unsigned int> & edgeid,
     254             :                                                   const std::vector<double> & position)
     255             : {
     256             :   // this method is called when we are marking cut edges
     257             :   auto eit = _elements.find(elemid);
     258       15947 :   if (eit == _elements.end())
     259           0 :     EFAError("Could not find element with id: ", elemid, " in addEdgeIntersection");
     260             : 
     261       15947 :   EFAElement3D * curr_elem = dynamic_cast<EFAElement3D *>(eit->second);
     262       15947 :   if (!curr_elem)
     263           0 :     EFAError("addElemEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
     264             : 
     265             :   // add cuts to two face edges at the same time
     266       15947 :   curr_elem->addFaceEdgeCut(faceid, edgeid[0], position[0], nullptr, _embedded_nodes, true, true);
     267       15947 :   curr_elem->addFaceEdgeCut(faceid, edgeid[1], position[1], nullptr, _embedded_nodes, true, true);
     268       15947 : }
     269             : 
     270             : void
     271           0 : ElementFragmentAlgorithm::addFragFaceIntersection(
     272             :     unsigned int /*ElemID*/,
     273             :     unsigned int /*FragFaceID*/,
     274             :     const std::vector<unsigned int> & /*FragFaceEdgeID*/,
     275             :     const std::vector<double> & /*position*/)
     276             : {
     277             :   // TODO: need to finish this for 3D problems
     278           0 : }
     279             : 
     280             : void
     281        1675 : ElementFragmentAlgorithm::updatePhysicalLinksAndFragments()
     282             : {
     283             :   // loop over the elements in the mesh
     284             :   std::map<unsigned int, EFAElement *>::iterator eit;
     285      255194 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
     286             :   {
     287      253519 :     EFAElement * curr_elem = eit->second;
     288      253519 :     curr_elem->updateFragments(_crack_tip_elements, _embedded_nodes);
     289             :   } // loop over all elements
     290        1675 : }
     291             : 
     292             : void
     293        1676 : ElementFragmentAlgorithm::updateTopology(bool mergeUncutVirtualEdges)
     294             : {
     295             :   // If mergeUncutVirtualEdges=true, this algorithm replicates the
     296             :   // behavior of classical XFEM.  If false, it gives the behavior of
     297             :   // the Richardson et. al. (2011) paper
     298             : 
     299        1676 :   _new_nodes.clear();
     300        1676 :   _child_elements.clear();
     301        1676 :   _parent_elements.clear();
     302             : 
     303        1676 :   unsigned int first_new_node_id = Efa::getNewID(_permanent_nodes);
     304             : 
     305        1676 :   createChildElements();
     306        1676 :   connectFragments(mergeUncutVirtualEdges);
     307        1676 :   sanityCheck();
     308        1676 :   updateCrackTipElements();
     309             : 
     310      385628 :   for (const auto & [id, node] : _permanent_nodes)
     311      383952 :     if (id >= first_new_node_id)
     312       14771 :       _new_nodes.push_back(node);
     313             : 
     314        1676 :   clearPotentialIsolatedNodes(); // _new_nodes and _permanent_nodes may change here
     315        1676 : }
     316             : 
     317             : void
     318        3144 : ElementFragmentAlgorithm::reset()
     319             : {
     320        3144 :   _new_nodes.clear();
     321        3144 :   _child_elements.clear();
     322        3144 :   _parent_elements.clear();
     323             :   _crack_tip_elements.clear();
     324             :   _inverse_connectivity.clear();
     325             : 
     326             :   std::map<unsigned int, EFANode *>::iterator mit;
     327      552053 :   for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
     328             :   {
     329      548909 :     delete mit->second;
     330      548909 :     mit->second = nullptr;
     331             :   }
     332             :   _permanent_nodes.clear();
     333             : 
     334        3144 :   for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
     335             :   {
     336           0 :     delete mit->second;
     337           0 :     mit->second = nullptr;
     338             :   }
     339             :   _temp_nodes.clear();
     340             :   std::map<unsigned int, EFAElement *>::iterator eit;
     341      394382 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
     342             :   {
     343      391238 :     delete eit->second;
     344      391238 :     eit->second = nullptr;
     345             :   }
     346             :   _elements.clear();
     347        3144 : }
     348             : 
     349             : void
     350          35 : ElementFragmentAlgorithm::clearAncestry()
     351             : {
     352             :   _inverse_connectivity.clear();
     353         158 :   for (unsigned int i = 0; i < _parent_elements.size(); ++i)
     354             :   {
     355         123 :     if (!Efa::deleteFromMap(_elements, _parent_elements[i]))
     356           0 :       EFAError("Attempted to delete parent element: ",
     357             :                _parent_elements[i]->id(),
     358             :                " from _elements, but couldn't find it");
     359             :   }
     360          35 :   _parent_elements.clear();
     361             : 
     362             :   std::map<unsigned int, EFAElement *>::iterator eit;
     363         382 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
     364             :   {
     365         347 :     EFAElement * curr_elem = eit->second;
     366         347 :     curr_elem->clearParentAndChildren();
     367        2767 :     for (unsigned int j = 0; j < curr_elem->numNodes(); j++)
     368             :     {
     369        2420 :       EFANode * curr_node = curr_elem->getNode(j);
     370        2420 :       _inverse_connectivity[curr_node].insert(curr_elem);
     371             :     }
     372             :   }
     373             : 
     374             :   std::map<unsigned int, EFANode *>::iterator mit;
     375        1129 :   for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
     376        1094 :     mit->second->removeParent();
     377             : 
     378          35 :   for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
     379             :   {
     380           0 :     delete mit->second;
     381           0 :     mit->second = nullptr;
     382             :   }
     383             :   _temp_nodes.clear();
     384             : 
     385          35 :   _new_nodes.clear();
     386          35 :   _child_elements.clear();
     387             : 
     388             :   // TODO: Sanity check to make sure that there are no nodes that are not connected
     389             :   //      to an element -- there shouldn't be any
     390          35 : }
     391             : 
     392             : void
     393       42275 : ElementFragmentAlgorithm::restoreFragmentInfo(EFAElement * const elem,
     394             :                                               const EFAElement * const from_elem)
     395             : {
     396       42275 :   elem->restoreFragment(from_elem);
     397       42275 : }
     398             : 
     399             : void
     400        1676 : ElementFragmentAlgorithm::createChildElements()
     401             : {
     402             :   // temporary container for new elements -- will be merged with Elements
     403             :   std::map<unsigned int, EFAElement *> newChildElements;
     404             : 
     405             :   // loop over the original elements in the mesh
     406             :   std::map<unsigned int, EFAElement *>::iterator eit;
     407             :   std::map<unsigned int, EFAElement *>::iterator ElementsEnd = _elements.end();
     408      255198 :   for (eit = _elements.begin(); eit != ElementsEnd; ++eit)
     409             :   {
     410      253522 :     EFAElement * curr_elem = eit->second;
     411      253522 :     curr_elem->createChild(_crack_tip_elements,
     412      253522 :                            _elements,
     413             :                            newChildElements,
     414      253522 :                            _child_elements,
     415      253522 :                            _parent_elements,
     416      253522 :                            _temp_nodes);
     417             :   } // loop over elements
     418             :   // Merge newChildElements back in with Elements
     419        1676 :   _elements.insert(newChildElements.begin(), newChildElements.end());
     420        1676 : }
     421             : 
     422             : void
     423        1676 : ElementFragmentAlgorithm::connectFragments(bool mergeUncutVirtualEdges)
     424             : {
     425             :   // now perform the comparison on the children
     426       13760 :   for (unsigned int elem_iter = 0; elem_iter < _child_elements.size(); elem_iter++)
     427             :   {
     428       12084 :     EFAElement * childElem = _child_elements[elem_iter];
     429       12084 :     childElem->connectNeighbors(
     430       12084 :         _permanent_nodes, _temp_nodes, _inverse_connectivity, mergeUncutVirtualEdges);
     431       12084 :     childElem->updateFragmentNode();
     432             :   }
     433             : 
     434             :   // remove all deleted children
     435        1676 :   _child_elements.erase(std::remove(_child_elements.begin(), _child_elements.end(), nullptr),
     436             :                         _child_elements.end());
     437        1676 : }
     438             : 
     439             : void
     440        1676 : ElementFragmentAlgorithm::sanityCheck()
     441             : {
     442             :   // Make sure there are no remaining TempNodes
     443        1676 :   if (_temp_nodes.size() > 0)
     444             :   {
     445           0 :     _ostream << "_temp_nodes size > 0.  size=" << _temp_nodes.size() << std::endl;
     446           0 :     printMesh();
     447           0 :     throw std::runtime_error("_temp_nodes size > 0");
     448             :   }
     449        1676 : }
     450             : 
     451             : void
     452        1676 : ElementFragmentAlgorithm::updateCrackTipElements()
     453             : {
     454             :   std::set<EFAElement *>::iterator sit;
     455             :   // Delete all elements that were previously flagged as crack tip elements if they have
     456             :   // been split (and hence appear in ParentElements).
     457        8653 :   for (unsigned int i = 0; i < _parent_elements.size(); ++i)
     458             :   {
     459             :     sit = _crack_tip_elements.find(_parent_elements[i]);
     460        6977 :     if (sit != _crack_tip_elements.end())
     461         413 :       _crack_tip_elements.erase(sit);
     462             :   }
     463             : 
     464             :   // Go through new child elements to find elements that are newly at the crack tip due to
     465             :   // crack growth.
     466       13760 :   for (unsigned int elem_iter = 0; elem_iter < _child_elements.size(); elem_iter++)
     467             :   {
     468       12084 :     EFAElement * childElem = _child_elements[elem_iter];
     469       12084 :     if (childElem->isCrackTipElement())
     470         856 :       _crack_tip_elements.insert(childElem);
     471             :   } // loop over (new) child elements
     472             : 
     473             :   //_ostream << "Crack tip elements: ";
     474             :   // for (sit=CrackTipElements.begin(); sit!=CrackTipElements.end(); ++sit)
     475             :   //{
     476             :   //  _ostream << (*sit)->id<<" ";
     477             :   //}
     478             :   //_ostream << std::endl;
     479        1676 : }
     480             : 
     481             : void
     482          18 : ElementFragmentAlgorithm::printMesh()
     483             : {
     484          18 :   _ostream << "============================================================"
     485          18 :            << "==================================================" << std::endl;
     486          18 :   _ostream << "                                            CutElemMesh Data" << std::endl;
     487          18 :   _ostream << "============================================================"
     488          18 :            << "==================================================" << std::endl;
     489          18 :   _ostream << "Permanent Nodes:" << std::endl;
     490             :   std::map<unsigned int, EFANode *>::iterator mit;
     491             :   unsigned int counter = 0;
     492         834 :   for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
     493             :   {
     494         816 :     _ostream << "  " << mit->second->id();
     495         816 :     counter += 1;
     496         816 :     if (counter % 10 == 0)
     497          75 :       _ostream << std::endl;
     498             :   }
     499          18 :   _ostream << std::endl;
     500          18 :   _ostream << "Temp Nodes:" << std::endl;
     501             :   counter = 0;
     502          18 :   for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
     503             :   {
     504           0 :     _ostream << "  " << mit->second->id();
     505           0 :     counter += 1;
     506           0 :     if (counter % 10 == 0)
     507           0 :       _ostream << std::endl;
     508             :   }
     509          18 :   _ostream << std::endl;
     510          18 :   _ostream << "Embedded Nodes:" << std::endl;
     511             :   counter = 0;
     512         294 :   for (mit = _embedded_nodes.begin(); mit != _embedded_nodes.end(); ++mit)
     513             :   {
     514         276 :     _ostream << "  " << mit->second->id();
     515         276 :     counter += 1;
     516         276 :     if (counter % 10 == 0)
     517          18 :       _ostream << std::endl;
     518             :   }
     519          18 :   _ostream << std::endl;
     520          18 :   _ostream << "Embedded Permanent Nodes:" << std::endl;
     521             :   counter = 0;
     522          18 :   for (mit = _embedded_permanent_nodes.begin(); mit != _embedded_permanent_nodes.end(); ++mit)
     523             :   {
     524           0 :     _ostream << "  " << mit->second->id();
     525           0 :     counter += 1;
     526           0 :     if (counter % 10 == 0)
     527           0 :       _ostream << std::endl;
     528             :   }
     529          18 :   _ostream << std::endl;
     530          18 :   _ostream << "Parent Elements:" << std::endl;
     531             :   counter = 0;
     532          96 :   for (unsigned int i = 0; i < _parent_elements.size(); ++i)
     533             :   {
     534          78 :     _ostream << " " << _parent_elements[i]->id();
     535          78 :     counter += 1;
     536          78 :     if (counter % 10 == 0)
     537           3 :       _ostream << std::endl;
     538             :   }
     539          18 :   _ostream << std::endl;
     540          18 :   _ostream << "Child Elements:" << std::endl;
     541             :   counter = 0;
     542         153 :   for (unsigned int i = 0; i < _child_elements.size(); ++i)
     543             :   {
     544         135 :     _ostream << " " << _child_elements[i]->id();
     545         135 :     counter += 1;
     546         135 :     if (counter % 10 == 0)
     547           9 :       _ostream << std::endl;
     548             :   }
     549          18 :   _ostream << std::endl;
     550          18 :   _ostream << "Elements:" << std::endl;
     551          18 :   _ostream << "  id "
     552             :            << "|  nodes                "
     553             :            << "|  embedded nodes       "
     554             :            << "|  edge neighbors       "
     555             :            << "|  frag "
     556          18 :            << "|  frag link      ...   " << std::endl;
     557          18 :   _ostream << "------------------------------------------------------------"
     558          18 :            << "--------------------------------------------------" << std::endl;
     559             :   std::map<unsigned int, EFAElement *>::iterator eit;
     560         621 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
     561             :   {
     562         603 :     EFAElement * currElem = eit->second;
     563         603 :     currElem->printElement(_ostream);
     564             :   }
     565          18 : }
     566             : 
     567             : EFAElement *
     568      286134 : ElementFragmentAlgorithm::getElemByID(unsigned int id)
     569             : {
     570             :   std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
     571      286134 :   if (mit == _elements.end())
     572           0 :     EFAError("in getElemByID() could not find element: ", id);
     573      286134 :   return mit->second;
     574             : }
     575             : 
     576             : unsigned int
     577           0 : ElementFragmentAlgorithm::getElemIdByNodes(unsigned int * node_id)
     578             : {
     579             :   unsigned int elem_id = std::numeric_limits<unsigned int>::max();
     580             :   std::map<unsigned int, EFAElement *>::iterator eit;
     581           0 :   for (eit = _elements.begin(); eit != _elements.end(); ++eit)
     582             :   {
     583           0 :     EFAElement * curr_elem = eit->second;
     584             :     unsigned int counter = 0;
     585           0 :     for (unsigned int i = 0; i < curr_elem->numNodes(); ++i)
     586             :     {
     587           0 :       if (curr_elem->getNode(i)->id() == node_id[i])
     588           0 :         counter += 1;
     589             :     }
     590           0 :     if (counter == curr_elem->numNodes())
     591             :     {
     592           0 :       elem_id = curr_elem->id();
     593             :       break;
     594             :     }
     595             :   }
     596           0 :   return elem_id;
     597             : }
     598             : 
     599             : void
     600        1676 : ElementFragmentAlgorithm::clearPotentialIsolatedNodes()
     601             : {
     602             :   // compile a set of all child element nodes
     603             :   std::set<EFANode *> child_nodes;
     604       13760 :   for (const auto & child_element : _child_elements)
     605             :   {
     606       12084 :     const auto & nodes = child_element->getNodes();
     607       12084 :     child_nodes.insert(nodes.begin(), nodes.end());
     608             :   }
     609             : 
     610             :   // Collect all parent nodes that will be isolated
     611             :   std::map<EFANode *, EFANode *> isolate_parent_to_child;
     612       16447 :   for (unsigned int i = 0; i < _new_nodes.size(); ++i)
     613             :   {
     614       14771 :     EFANode * parent_node = _new_nodes[i]->parent();
     615       14771 :     if (!parent_node)
     616           0 :       EFAError("a new permanent node must have a parent node!");
     617             : 
     618             :     auto it = isolate_parent_to_child.lower_bound(parent_node);
     619       14771 :     if (it != isolate_parent_to_child.end() && it->first == parent_node)
     620         112 :       continue;
     621             : 
     622             :     if (child_nodes.count(parent_node) == 0)
     623         116 :       isolate_parent_to_child.emplace_hint(it, parent_node, _new_nodes[i]);
     624             :   }
     625             : 
     626             :   // For each isolated parent node, pick one of its child new node
     627             :   // Then, switch that child with its parent for all new elems
     628        1792 :   for (const auto [parent_node, child_node] : isolate_parent_to_child)
     629             :   {
     630        2468 :     for (unsigned int i = 0; i < _child_elements.size(); ++i)
     631        2352 :       if (_child_elements[i]->containsNode(child_node))
     632         116 :         _child_elements[i]->switchNode(parent_node, child_node, true);
     633             : 
     634         116 :     _new_nodes.erase(std::remove(_new_nodes.begin(), _new_nodes.end(), child_node),
     635             :                      _new_nodes.end());
     636         116 :     Efa::deleteFromMap(_permanent_nodes, child_node);
     637             :   }
     638        1676 : }

Generated by: LCOV version 1.14