LCOV - code coverage report
Current view: top level - src/efa - EFAEdge.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #32971 (54bef8) with base c6cf66 Lines: 142 168 84.5 %
Date: 2026-05-29 20:41:31 Functions: 27 27 100.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             : #include "EFAEdge.h"
      11             : 
      12             : #include "EFANode.h"
      13             : #include "EFAError.h"
      14             : #include "XFEMFuncs.h"
      15             : 
      16     6503569 : EFAEdge::EFAEdge(EFANode * node1, EFANode * node2) : _edge_node1(node1), _edge_node2(node2)
      17             : {
      18     6503569 :   _embedded_nodes.clear();
      19     6503569 :   _intersection_x.clear();
      20     6503569 :   _edge_interior_node = nullptr;
      21     6503569 :   consistencyCheck();
      22     6503569 : }
      23             : 
      24     4339468 : EFAEdge::EFAEdge(const EFAEdge & other_edge)
      25             : {
      26     4339468 :   _edge_node1 = other_edge._edge_node1;
      27     4339468 :   _edge_node2 = other_edge._edge_node2;
      28     4339468 :   _intersection_x = other_edge._intersection_x;
      29     4339468 :   _embedded_nodes = other_edge._embedded_nodes;
      30     4339468 :   consistencyCheck();
      31     4339468 : }
      32             : 
      33    10842237 : EFAEdge::~EFAEdge() // do not delete edge node - they will be deleted
      34             : {                   // in EFAelement's destructor
      35    10842237 : }
      36             : 
      37             : bool
      38   214088629 : EFAEdge::equivalent(const EFAEdge & other) const
      39             : {
      40             :   if (getSortedNodes() == other.getSortedNodes())
      41             :   {
      42             :     // For cut along the edge case
      43    15934799 :     if (isEmbeddedPermanent())
      44             :       return false;
      45             :     return true;
      46             :   }
      47             : 
      48             :   return false;
      49             : }
      50             : 
      51             : bool
      52    62688623 : EFAEdge::isEmbeddedPermanent() const
      53             : {
      54    62688711 :   return _edge_node1->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT &&
      55          88 :          _edge_node2->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT;
      56             : }
      57             : 
      58             : bool
      59          36 : EFAEdge::isPartialOverlap(const EFAEdge & other) const
      60             : {
      61          36 :   return containsEdge(other) || other.containsEdge(*this);
      62             : }
      63             : 
      64             : bool
      65    29829415 : EFAEdge::containsEdge(const EFAEdge & other) const
      66             : {
      67    29829415 :   return containsNode(other._edge_node1) && containsNode(other._edge_node2);
      68             : }
      69             : 
      70             : bool
      71     9473013 : EFAEdge::getNodeMasters(EFANode * node,
      72             :                         std::vector<EFANode *> & master_nodes,
      73             :                         std::vector<double> & master_weights) const
      74             : {
      75     9473013 :   master_nodes.clear();
      76     9473013 :   master_weights.clear();
      77             :   bool masters_found = false;
      78     9473013 :   if (_edge_node1 == node || _edge_node2 == node)
      79             :   {
      80      817890 :     master_nodes.push_back(node);
      81      817890 :     master_weights.push_back(1.0);
      82      817890 :     masters_found = true;
      83             :   }
      84             :   else
      85             :   {
      86     8657049 :     for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
      87             :     {
      88     8657049 :       if (_embedded_nodes[i] == node)
      89             :       {
      90     8655123 :         master_nodes.push_back(_edge_node1);
      91     8655123 :         master_nodes.push_back(_edge_node2);
      92     8655123 :         master_weights.push_back(1.0 - _intersection_x[i]);
      93     8655123 :         master_weights.push_back(_intersection_x[i]);
      94             :         masters_found = true;
      95     8655123 :         break;
      96             :       }
      97             :     }
      98             :   }
      99     9473013 :   return masters_found;
     100             : }
     101             : 
     102             : // TODO: Saving because I don't want to throw it away, but it needs more work to be used.
     103             : // bool
     104             : // EFAEdge::operator < (const edge_t & other) const
     105             : //{
     106             : //  node_t * this_min_node;
     107             : //  node_t * this_max_node;
     108             : //  node_t * other_min_node;
     109             : //  node_t * other_max_node;
     110             : //
     111             : //  int this_node1_unique_index = ((int) edge_node1->category + 1) * edge_node1->id;
     112             : //  int this_node2_unique_index = ((int) edge_node2->category + 1) * edge_node2->id;
     113             : //  int other_node1_unique_index = ((int) other.edge_node1->category + 1) * edge_node1->id;
     114             : //  int other_node2_unique_index = ((int) other.edge_node2->category + 1) * edge_node2->id;
     115             : //  int this_min_index = std::min(this_node1_unique_index, this_node2_unique_index);
     116             : //  int other_min_index = std::min(other_node1_unique_index, other_node2_unique_index);
     117             : //
     118             : //  if (this_min_index < other_min_index)
     119             : //    return true;
     120             : //  else if (this_min_index == other_min_index)
     121             : //  {
     122             : //    int this_max_index = std::max(this_node1_unique_index, this_node2_unique_index);
     123             : //    int other_max_index = std::max(other_node1_unique_index, other_node2_unique_index);
     124             : //
     125             : //    if (this_max_index < other_max_index)
     126             : //      return true;
     127             : //  }
     128             : //  return false;
     129             : //}
     130             : 
     131             : void
     132       24620 : EFAEdge::addIntersection(double position, EFANode * embedded_node_tmp, EFANode * from_node)
     133             : {
     134       24620 :   _embedded_nodes.push_back(embedded_node_tmp);
     135       24620 :   if (from_node == _edge_node1)
     136       24620 :     _intersection_x.push_back(position);
     137           0 :   else if (from_node == _edge_node2)
     138           0 :     _intersection_x.push_back(1.0 - position);
     139             :   else
     140           0 :     EFAError("In addIntersection from_node does not exist on edge");
     141       24620 : }
     142             : 
     143             : void
     144        2012 : EFAEdge::resetIntersection(double position, EFANode * embedded_node_tmp, EFANode * from_node)
     145             : {
     146        2012 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     147             :   {
     148        2012 :     if (_embedded_nodes[i] == embedded_node_tmp)
     149             :     {
     150        2012 :       if (from_node == _edge_node1)
     151        2012 :         _intersection_x[i] = position;
     152           0 :       else if (from_node == _edge_node2)
     153           0 :         _intersection_x[i] = 1.0 - position;
     154             :       else
     155           0 :         EFAError("In resetIntersection from_node does not exist on edge");
     156             :       break;
     157             :     }
     158             :   }
     159        2012 : }
     160             : 
     161             : void
     162      211341 : EFAEdge::copyIntersection(const EFAEdge & other, unsigned int from_node_id)
     163             : {
     164      211341 :   _embedded_nodes.clear();
     165      211341 :   _intersection_x.clear();
     166      211341 :   _embedded_nodes = other._embedded_nodes;
     167      211341 :   if (from_node_id == 0)
     168      211341 :     _intersection_x = other._intersection_x;
     169           0 :   else if (from_node_id == 1)
     170             :   {
     171           0 :     for (unsigned int i = 0; i < other.numEmbeddedNodes(); ++i)
     172           0 :       _intersection_x.push_back(1.0 - other._intersection_x[i]);
     173             :   }
     174             :   else
     175           0 :     EFAError("from_node_id out of bounds");
     176      211341 :   if (_embedded_nodes.size() != _intersection_x.size())
     177           0 :     EFAError("in copyIntersection num emb_nodes must == num of inters_x");
     178      211341 : }
     179             : 
     180             : EFANode *
     181    35464368 : EFAEdge::getNode(unsigned int index) const
     182             : {
     183    35464368 :   if (index == 0)
     184    19012003 :     return _edge_node1;
     185    16452365 :   else if (index == 1)
     186    16452365 :     return _edge_node2;
     187             :   else
     188           0 :     EFAError("In getNode index out of bounds");
     189             : }
     190             : 
     191             : void
     192       11056 : EFAEdge::reverseNodes()
     193             : {
     194             :   std::swap(_edge_node1, _edge_node2);
     195       11056 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     196           0 :     _intersection_x[i] = 1.0 - _intersection_x[i];
     197       11056 : }
     198             : 
     199             : bool
     200     6648392 : EFAEdge::hasIntersection() const
     201             : {
     202             :   bool has = false;
     203     6648392 :   if (_edge_node1->parent() != nullptr)
     204       76840 :     has = has || _edge_node1->parent()->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT;
     205             : 
     206     6648392 :   if (_edge_node2->parent() != nullptr)
     207       77032 :     has = has || _edge_node2->parent()->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT;
     208             : 
     209     6647864 :   return has || _embedded_nodes.size() > 0;
     210             : }
     211             : 
     212             : bool
     213      297485 : EFAEdge::hasIntersectionAtPosition(double position, EFANode * from_node) const
     214             : {
     215             :   bool has_int = false;
     216      297485 :   if (hasIntersection())
     217             :   {
     218             :     double tmp_intersection_x = -1.0;
     219      267962 :     if (from_node == _edge_node1)
     220             :       tmp_intersection_x = position;
     221        4670 :     else if (from_node == _edge_node2)
     222        4670 :       tmp_intersection_x = 1.0 - position;
     223             :     else
     224           0 :       EFAError("In hasIntersectionAtPosition from_node does not exist on edge");
     225             : 
     226      268202 :     for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     227             :     {
     228      267986 :       if (std::abs(tmp_intersection_x - _intersection_x[i]) < Xfem::tol)
     229             :       {
     230             :         has_int = true;
     231             :         break;
     232             :       }
     233             :     }
     234             :   }
     235      297485 :   return has_int;
     236             : }
     237             : 
     238             : double
     239        2252 : EFAEdge::getIntersection(unsigned int emb_id, EFANode * from_node) const
     240             : {
     241        2252 :   if (from_node == _edge_node1)
     242        2252 :     return _intersection_x[emb_id];
     243           0 :   else if (from_node == _edge_node2)
     244           0 :     return 1.0 - _intersection_x[emb_id];
     245             :   else
     246           0 :     EFAError("In getIntersection node not in edge");
     247             : }
     248             : 
     249             : double
     250       13166 : EFAEdge::distanceFromNode1(EFANode * node) const
     251             : {
     252             :   double xi = -100.0;
     253       13166 :   if (_edge_node1 == node)
     254             :     xi = 0.0;
     255        9395 :   else if (_edge_node2 == node)
     256             :     xi = 1.0;
     257        3672 :   else if (isEmbeddedNode(node))
     258             :   {
     259        3672 :     unsigned int embedded_node_id = getEmbeddedNodeIndex(node);
     260        3672 :     xi = _intersection_x[embedded_node_id];
     261             :   }
     262             :   else
     263           0 :     EFAError("the given node is not found in the current edge");
     264       13166 :   return xi;
     265             : }
     266             : 
     267             : bool
     268   468159898 : EFAEdge::isEmbeddedNode(const EFANode * node) const
     269             : {
     270             :   bool is_emb = false;
     271   589698845 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     272             :   {
     273   171688536 :     if (_embedded_nodes[i] == node)
     274             :     {
     275             :       is_emb = true;
     276             :       break;
     277             :     }
     278             :   }
     279   468159898 :   return is_emb;
     280             : }
     281             : 
     282             : unsigned int
     283        3672 : EFAEdge::getEmbeddedNodeIndex(EFANode * node) const
     284             : {
     285             :   unsigned int index;
     286             :   bool have_index = false;
     287        3672 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     288             :   {
     289        3672 :     if (_embedded_nodes[i] == node)
     290             :     {
     291             :       have_index = true;
     292             :       index = i;
     293             :       break;
     294             :     }
     295             :   }
     296        3672 :   if (!have_index)
     297           0 :     EFAError("In getEmbeddedNodeIndex, could not find index");
     298        3672 :   return index;
     299             : }
     300             : 
     301             : unsigned int
     302      267314 : EFAEdge::getEmbeddedNodeIndex(double position, EFANode * from_node) const
     303             : {
     304             :   bool have_index = false;
     305             :   unsigned int index;
     306      267314 :   if (hasIntersection())
     307             :   {
     308             :     double tmp_intersection_x = -1.0; // dist from edge_node1
     309      267314 :     if (from_node == _edge_node1)
     310             :       tmp_intersection_x = position;
     311        4670 :     else if (from_node == _edge_node2)
     312        4670 :       tmp_intersection_x = 1.0 - position;
     313             :     else
     314           0 :       EFAError("In getEmbeddedNodeIndex, from_node does not exist on edge");
     315             : 
     316      267338 :     for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     317             :     {
     318      267338 :       if (std::abs(tmp_intersection_x - _intersection_x[i]) < Xfem::tol)
     319             :       {
     320             :         have_index = true;
     321             :         index = i;
     322             :         break;
     323             :       }
     324             :     }
     325             :   }
     326      267314 :   if (!have_index)
     327           0 :     EFAError("In getEmbeddedNodeIndex, could not find index");
     328      267314 :   return index;
     329             : }
     330             : 
     331             : EFANode *
     332      363131 : EFAEdge::getEmbeddedNode(unsigned int index) const
     333             : {
     334      363131 :   if (index < _embedded_nodes.size())
     335      363131 :     return _embedded_nodes[index];
     336             :   else
     337           0 :     EFAError("in getEmbeddedNode index out of bounds");
     338             : }
     339             : 
     340             : unsigned int
     341      654865 : EFAEdge::numEmbeddedNodes() const
     342             : {
     343      654865 :   return _embedded_nodes.size();
     344             : }
     345             : 
     346             : void
     347    10843037 : EFAEdge::consistencyCheck()
     348             : {
     349             :   bool consistent = true;
     350    11522265 :   if ((_edge_node1->category() == EFANode::N_CATEGORY_PERMANENT ||
     351    21056697 :        _edge_node1->category() == EFANode::N_CATEGORY_TEMP) &&
     352    10213660 :       _edge_node2->category() == EFANode::N_CATEGORY_LOCAL_INDEX)
     353             :     consistent = false;
     354    11522265 :   else if ((_edge_node2->category() == EFANode::N_CATEGORY_PERMANENT ||
     355    21056697 :             _edge_node2->category() == EFANode::N_CATEGORY_TEMP) &&
     356    10213660 :            _edge_node1->category() == EFANode::N_CATEGORY_LOCAL_INDEX)
     357             :     consistent = false;
     358             :   if (!consistent)
     359           0 :     EFAError("In consistencyCheck nodes on edge are not consistent");
     360    10843037 :   if (_embedded_nodes.size() != _intersection_x.size())
     361           0 :     EFAError("In consistencyCheck num of emb_nodes must be = num of inters_x");
     362    10843037 : }
     363             : 
     364             : void
     365     4012257 : EFAEdge::switchNode(EFANode * new_node, EFANode * old_node)
     366             : {
     367     4012257 :   if (_edge_node1 == old_node)
     368      435446 :     _edge_node1 = new_node;
     369     3576811 :   else if (_edge_node2 == old_node)
     370      435446 :     _edge_node2 = new_node;
     371     3141365 :   else if (isEmbeddedNode(old_node))
     372             :   {
     373           0 :     unsigned int id = getEmbeddedNodeIndex(old_node);
     374           0 :     _embedded_nodes[id] = new_node;
     375             :   }
     376     4012257 : }
     377             : 
     378             : bool
     379   517427781 : EFAEdge::containsNode(const EFANode * node) const
     380             : {
     381   517427781 :   return _edge_node1 == node || _edge_node2 == node || isEmbeddedNode(node);
     382             : }
     383             : 
     384             : void
     385          72 : EFAEdge::removeEmbeddedNodes()
     386             : {
     387          72 :   _embedded_nodes.clear();
     388          72 :   _intersection_x.clear();
     389          72 : }
     390             : 
     391             : void
     392          79 : EFAEdge::removeEmbeddedNode(EFANode * node)
     393             : {
     394             :   unsigned int index = 0;
     395             :   bool node_found = false;
     396          79 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     397             :   {
     398          79 :     if (_embedded_nodes[i] == node)
     399             :     {
     400             :       index = i;
     401             :       node_found = true;
     402             :       break;
     403             :     }
     404             :   }
     405          79 :   if (node_found)
     406             :   {
     407          79 :     _embedded_nodes.erase(_embedded_nodes.begin() + index);
     408          79 :     _intersection_x.erase(_intersection_x.begin() + index);
     409             :   }
     410          79 : }

Generated by: LCOV version 1.14