LCOV - code coverage report
Current view: top level - src/efa - EFAElement.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31405 (292dce) with base fef103 Lines: 113 152 74.3 %
Date: 2025-09-04 07:58:55 Functions: 21 27 77.8 %
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             : #include "EFAElement.h"
      11             : 
      12             : #include "EFANode.h"
      13             : #include "EFAError.h"
      14             : #include "EFAFuncs.h"
      15             : 
      16      450039 : EFAElement::EFAElement(unsigned int eid, unsigned int n_nodes)
      17      450039 :   : _id(eid),
      18      450039 :     _num_nodes(n_nodes),
      19      900078 :     _nodes(_num_nodes, nullptr),
      20      450039 :     _parent(nullptr),
      21      450039 :     _crack_tip_split_element(false)
      22             : {
      23      450039 : }
      24             : 
      25      449839 : EFAElement::~EFAElement() {}
      26             : 
      27             : unsigned int
      28       44236 : EFAElement::id() const
      29             : {
      30       44236 :   return _id;
      31             : }
      32             : 
      33             : unsigned int
      34     3126058 : EFAElement::numNodes() const
      35             : {
      36     3126058 :   return _num_nodes;
      37             : }
      38             : 
      39             : void
      40     2096564 : EFAElement::setNode(unsigned int node_id, EFANode * node)
      41             : {
      42     2096564 :   _nodes[node_id] = node;
      43     2096564 : }
      44             : 
      45             : EFANode *
      46     9707632 : EFAElement::getNode(unsigned int node_id) const
      47             : {
      48     9707632 :   return _nodes[node_id];
      49             : }
      50             : 
      51             : bool
      52        2352 : EFAElement::containsNode(EFANode * node) const
      53             : {
      54       14884 :   for (const auto element_node : _nodes)
      55       12648 :     if (element_node == node)
      56             :       return true;
      57             :   return false;
      58             : }
      59             : 
      60             : void
      61           0 : EFAElement::printNodes(std::ostream & ostream) const
      62             : {
      63           0 :   ostream << "***** nodes for element " << _id << " *****" << std::endl;
      64           0 :   for (unsigned int i = 0; i < _num_nodes; ++i)
      65           0 :     ostream << "addr " << _nodes[i] << ", ID " << _nodes[i]->idCatString() << ", category "
      66           0 :             << _nodes[i]->category() << std::endl;
      67           0 : }
      68             : 
      69             : EFANode *
      70      120616 : EFAElement::createLocalNodeFromGlobalNode(const EFANode * global_node) const
      71             : {
      72             :   // Given a global node, create a new local node
      73      120828 :   if (global_node->category() != EFANode::N_CATEGORY_PERMANENT &&
      74      120828 :       global_node->category() != EFANode::N_CATEGORY_TEMP &&
      75         212 :       global_node->category() != EFANode::N_CATEGORY_EMBEDDED_PERMANENT)
      76           0 :     EFAError("In createLocalNodeFromGlobalNode node is not global");
      77             : 
      78             :   EFANode * new_local_node = nullptr;
      79             :   unsigned int inode = 0;
      80      435764 :   for (; inode < _nodes.size(); ++inode)
      81             :   {
      82      435764 :     if (_nodes[inode] == global_node)
      83             :     {
      84      120616 :       new_local_node = new EFANode(inode, EFANode::N_CATEGORY_LOCAL_INDEX);
      85             :       break;
      86             :     }
      87             :   }
      88             :   if (!new_local_node)
      89           0 :     EFAError("In createLocalNodeFromGlobalNode could not find global node");
      90             : 
      91      120616 :   return new_local_node;
      92             : }
      93             : 
      94             : EFANode *
      95           0 : EFAElement::getGlobalNodeFromLocalNode(const EFANode * local_node) const
      96             : {
      97             :   // Given a local node, find the global node corresponding to that node
      98           0 :   if (local_node->category() != EFANode::N_CATEGORY_LOCAL_INDEX)
      99           0 :     EFAError("In getGlobalNodeFromLocalNode node passed in is not local");
     100             : 
     101           0 :   EFANode * global_node = _nodes[local_node->id()];
     102             : 
     103           0 :   if (global_node->category() != EFANode::N_CATEGORY_PERMANENT &&
     104           0 :       global_node->category() != EFANode::N_CATEGORY_TEMP)
     105           0 :     EFAError("In getGlobalNodeFromLocalNode, the node stored by the element is not global");
     106             : 
     107           0 :   return global_node;
     108             : }
     109             : 
     110             : unsigned int
     111      275744 : EFAElement::getLocalNodeIndex(EFANode * node) const
     112             : {
     113      768426 :   for (unsigned int i = 0; i < _num_nodes; ++i)
     114             :   {
     115      768426 :     if (_nodes[i] == node)
     116      275744 :       return i;
     117             :   }
     118           0 :   EFAError("In EFAelement::getLocalNodeIndex, cannot find the given node");
     119             : }
     120             : 
     121             : void
     122        5072 : EFAElement::setCrackTipSplit()
     123             : {
     124        5072 :   _crack_tip_split_element = true;
     125        5072 : }
     126             : 
     127             : bool
     128        2011 : EFAElement::isCrackTipSplit() const
     129             : {
     130        2011 :   return _crack_tip_split_element;
     131             : }
     132             : 
     133             : unsigned int
     134           0 : EFAElement::numCrackTipNeighbors() const
     135             : {
     136           0 :   return _crack_tip_neighbors.size();
     137             : }
     138             : 
     139             : unsigned int
     140           0 : EFAElement::getCrackTipNeighbor(unsigned int index) const
     141             : {
     142           0 :   if (index < _crack_tip_neighbors.size())
     143           0 :     return _crack_tip_neighbors[index];
     144             :   else
     145           0 :     EFAError("in getCrackTipNeighbor index out of bounds");
     146             : }
     147             : 
     148             : void
     149        5072 : EFAElement::addCrackTipNeighbor(EFAElement * neighbor_elem)
     150             : {
     151             :   // Find out what side the specified element is on, and add it as a crack tip neighbor
     152             :   // element for that side.
     153        5072 :   unsigned int neighbor_index = getNeighborIndex(neighbor_elem);
     154             :   bool crack_tip_neighbor_exist = false;
     155        5488 :   for (unsigned int i = 0; i < _crack_tip_neighbors.size(); ++i)
     156             :   {
     157         420 :     if (_crack_tip_neighbors[i] == neighbor_index)
     158             :     {
     159             :       crack_tip_neighbor_exist = true;
     160             :       break;
     161             :     }
     162             :   }
     163        5072 :   if (!crack_tip_neighbor_exist)
     164        5068 :     _crack_tip_neighbors.push_back(neighbor_index);
     165        5072 : }
     166             : 
     167             : EFAElement *
     168       24900 : EFAElement::getParent() const
     169             : {
     170       24900 :   return _parent;
     171             : }
     172             : 
     173             : EFAElement *
     174      980624 : EFAElement::getChild(unsigned int child_id) const
     175             : {
     176      980624 :   if (child_id < _children.size())
     177      980624 :     return _children[child_id];
     178             :   else
     179           0 :     EFAError("child_id out of bounds");
     180             : }
     181             : 
     182             : void
     183       12084 : EFAElement::setParent(EFAElement * parent)
     184             : {
     185       12084 :   _parent = parent;
     186       12084 : }
     187             : 
     188             : unsigned int
     189     1722082 : EFAElement::numChildren() const
     190             : {
     191     1722082 :   return _children.size();
     192             : }
     193             : 
     194             : void
     195           0 : EFAElement::addChild(EFAElement * child)
     196             : {
     197           0 :   _children.push_back(child);
     198           0 : }
     199             : 
     200             : void
     201         347 : EFAElement::clearParentAndChildren()
     202             : {
     203         347 :   _parent = nullptr;
     204         347 :   _children.clear();
     205         347 : }
     206             : 
     207             : void
     208      426444 : EFAElement::findGeneralNeighbors(
     209             :     const std::map<EFANode *, std::set<EFAElement *>> & inverse_connectivity)
     210             : {
     211      426444 :   _general_neighbors.clear();
     212             :   std::set<EFAElement *> patch_elements;
     213     2456244 :   for (unsigned int inode = 0; inode < _num_nodes; ++inode)
     214             :   {
     215     2029800 :     auto it = inverse_connectivity.find(_nodes[inode]);
     216     2029800 :     if (it != inverse_connectivity.end())
     217     2029800 :       patch_elements.insert(it->second.begin(), it->second.end());
     218             :   }
     219             : 
     220             :   std::set<EFAElement *>::iterator eit2;
     221     5107908 :   for (eit2 = patch_elements.begin(); eit2 != patch_elements.end(); ++eit2)
     222             :   {
     223     4681464 :     EFAElement * neigh_elem = *eit2;
     224     4681464 :     if (neigh_elem != this)
     225     4255020 :       _general_neighbors.push_back(neigh_elem);
     226             :   }
     227      426444 : }
     228             : 
     229             : EFAElement *
     230      685416 : EFAElement::getGeneralNeighbor(unsigned int index) const
     231             : {
     232      685416 :   return _general_neighbors[index];
     233             : }
     234             : 
     235             : unsigned int
     236      712325 : EFAElement::numGeneralNeighbors() const
     237             : {
     238      712325 :   return _general_neighbors.size();
     239             : }
     240             : 
     241             : void
     242       42851 : EFAElement::mergeNodes(EFANode *& childNode,
     243             :                        EFANode *& childOfNeighborNode,
     244             :                        EFAElement * childOfNeighborElem,
     245             :                        std::map<unsigned int, EFANode *> & PermanentNodes,
     246             :                        std::map<unsigned int, EFANode *> & TempNodes)
     247             : {
     248             :   // Important: this must be run only on child elements that were just created
     249       42851 :   if (!_parent)
     250           0 :     EFAError("no getParent element for child element ", _id, " in mergeNodes");
     251             : 
     252             :   EFAElement * childElem = this;
     253       42851 :   if (childNode != childOfNeighborNode)
     254             :   {
     255       17255 :     if (childNode->category() == EFANode::N_CATEGORY_PERMANENT)
     256             :     {
     257        5764 :       if (childOfNeighborNode->category() == EFANode::N_CATEGORY_PERMANENT)
     258             :       {
     259         258 :         if (childOfNeighborNode->parent() == childNode) // merge into childNode
     260             :         {
     261          17 :           childOfNeighborElem->switchNode(childNode, childOfNeighborNode, true);
     262          17 :           if (!Efa::deleteFromMap(PermanentNodes, childOfNeighborNode))
     263             :           {
     264           0 :             EFAError("Attempted to delete node: ",
     265             :                      childOfNeighborNode->id(),
     266             :                      " from PermanentNodes, but couldn't find it");
     267             :           }
     268          17 :           childOfNeighborNode = childNode;
     269             :         }
     270         241 :         else if (childNode->parent() == childOfNeighborNode) // merge into childOfNeighborNode
     271             :         {
     272         125 :           childElem->switchNode(childOfNeighborNode, childNode, true);
     273         125 :           if (!Efa::deleteFromMap(PermanentNodes, childNode))
     274             :           {
     275           0 :             EFAError("Attempted to delete node: ",
     276             :                      childNode->id(),
     277             :                      " from PermanentNodes, but couldn't find it");
     278             :           }
     279         125 :           childNode = childOfNeighborNode;
     280             :         }
     281         232 :         else if (childNode->parent() != nullptr &&
     282         116 :                  childNode->parent() == childOfNeighborNode->parent())
     283             :         {
     284             :           // merge into childNode if both nodes are child permanent
     285         116 :           childOfNeighborElem->switchNode(childNode, childOfNeighborNode, true);
     286         116 :           if (!Efa::deleteFromMap(PermanentNodes,
     287             :                                   childOfNeighborNode)) // delete childOfNeighborNode
     288             :           {
     289           0 :             EFAError("Attempted to delete node: ",
     290             :                      childOfNeighborNode->id(),
     291             :                      " from PermanentNodes, but couldn't find it");
     292             :           }
     293         116 :           childOfNeighborNode = childNode;
     294             :         }
     295             :         else
     296             :         {
     297           0 :           EFAError("Attempting to merge nodes: ",
     298             :                    childNode->id(),
     299             :                    " and ",
     300             :                    childOfNeighborNode->id(),
     301             :                    " but both are permanent themselves");
     302             :         }
     303             :       }
     304             :       else
     305             :       {
     306        9203 :         if (childOfNeighborNode->parent() != childNode &&
     307        3697 :             childOfNeighborNode->parent() != childNode->parent())
     308             :         {
     309           0 :           EFAError("Attempting to merge nodes ",
     310             :                    childOfNeighborNode->idCatString(),
     311             :                    " and ",
     312             :                    childNode->idCatString(),
     313             :                    " but neither the 2nd node nor its parent is parent of the 1st");
     314             :         }
     315        5506 :         childOfNeighborElem->switchNode(childNode, childOfNeighborNode, true);
     316        5506 :         if (!Efa::deleteFromMap(TempNodes, childOfNeighborNode))
     317           0 :           EFAError("Attempted to delete node: ",
     318             :                    childOfNeighborNode->id(),
     319             :                    " from TempNodes, but couldn't find it");
     320        5506 :         childOfNeighborNode = childNode;
     321             :       }
     322             :     }
     323       11491 :     else if (childOfNeighborNode->category() == EFANode::N_CATEGORY_PERMANENT)
     324             :     {
     325        2451 :       if (childNode->parent() != childOfNeighborNode &&
     326         498 :           childNode->parent() != childOfNeighborNode->parent())
     327             :       {
     328           0 :         EFAError("Attempting to merge nodes ",
     329             :                  childNode->id(),
     330             :                  " and ",
     331             :                  childOfNeighborNode->id(),
     332             :                  " but neither the 2nd node nor its parent is parent of the 1st");
     333             :       }
     334        1953 :       childElem->switchNode(childOfNeighborNode, childNode, true);
     335        1953 :       if (!Efa::deleteFromMap(TempNodes, childNode))
     336           0 :         EFAError(
     337             :             "Attempted to delete node: ", childNode->id(), " from TempNodes, but couldn't find it");
     338        1953 :       childNode = childOfNeighborNode;
     339             :     }
     340             :     else // both nodes are temporary -- create new permanent node and delete temporary nodes
     341             :     {
     342        9538 :       unsigned int new_node_id = Efa::getNewID(PermanentNodes);
     343             :       EFANode * newNode =
     344        9538 :           new EFANode(new_node_id, EFANode::N_CATEGORY_PERMANENT, childNode->parent());
     345        9538 :       PermanentNodes.insert(std::make_pair(new_node_id, newNode));
     346             : 
     347        9538 :       childOfNeighborElem->switchNode(newNode, childOfNeighborNode, true);
     348        9538 :       childElem->switchNode(newNode, childNode, true);
     349             : 
     350        9538 :       if (childNode->parent() != childOfNeighborNode->parent())
     351             :       {
     352           0 :         EFAError("Attempting to merge nodes ",
     353             :                  childNode->id(),
     354             :                  " and ",
     355             :                  childOfNeighborNode->id(),
     356             :                  " but they don't share a common parent");
     357             :       }
     358             : 
     359        9538 :       if (!Efa::deleteFromMap(TempNodes, childOfNeighborNode))
     360           0 :         EFAError("Attempted to delete node: ",
     361             :                  childOfNeighborNode->id(),
     362             :                  " from TempNodes, but couldn't find it");
     363        9538 :       if (!Efa::deleteFromMap(TempNodes, childNode))
     364           0 :         EFAError(
     365             :             "Attempted to delete node: ", childNode->id(), " from TempNodes, but couldn't find it");
     366        9538 :       childOfNeighborNode = newNode;
     367        9538 :       childNode = newNode;
     368             :     }
     369             :   }
     370       42851 : }

Generated by: LCOV version 1.14