LCOV - code coverage report
Current view: top level - src/efa - EFAEdge.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31653 (1b668c) with base bb0a08 Lines: 142 168 84.5 %
Date: 2025-11-03 17:08:14 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     3917529 : EFAEdge::EFAEdge(EFANode * node1, EFANode * node2) : _edge_node1(node1), _edge_node2(node2)
      17             : {
      18     3917529 :   _embedded_nodes.clear();
      19     3917529 :   _intersection_x.clear();
      20     3917529 :   _edge_interior_node = nullptr;
      21     3917529 :   consistencyCheck();
      22     3917529 : }
      23             : 
      24     2646120 : EFAEdge::EFAEdge(const EFAEdge & other_edge)
      25             : {
      26     2646120 :   _edge_node1 = other_edge._edge_node1;
      27     2646120 :   _edge_node2 = other_edge._edge_node2;
      28     2646120 :   _intersection_x = other_edge._intersection_x;
      29     2646120 :   _embedded_nodes = other_edge._embedded_nodes;
      30     2646120 :   consistencyCheck();
      31     2646120 : }
      32             : 
      33     6562849 : EFAEdge::~EFAEdge() // do not delete edge node - they will be deleted
      34             : {                   // in EFAelement's destructor
      35     6562849 : }
      36             : 
      37             : bool
      38    71442409 : EFAEdge::equivalent(const EFAEdge & other) const
      39             : {
      40             :   if (getSortedNodes() == other.getSortedNodes())
      41             :   {
      42             :     // For cut along the edge case
      43     5788627 :     if (isEmbeddedPermanent())
      44             :       return false;
      45             :     return true;
      46             :   }
      47             : 
      48             :   return false;
      49             : }
      50             : 
      51             : bool
      52    24755827 : EFAEdge::isEmbeddedPermanent() const
      53             : {
      54    24755915 :   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    29076140 : EFAEdge::containsEdge(const EFAEdge & other) const
      66             : {
      67    29076140 :   return containsNode(other._edge_node1) && containsNode(other._edge_node2);
      68             : }
      69             : 
      70             : bool
      71     7664957 : EFAEdge::getNodeMasters(EFANode * node,
      72             :                         std::vector<EFANode *> & master_nodes,
      73             :                         std::vector<double> & master_weights) const
      74             : {
      75     7664957 :   master_nodes.clear();
      76     7664957 :   master_weights.clear();
      77             :   bool masters_found = false;
      78     7664957 :   if (_edge_node1 == node || _edge_node2 == node)
      79             :   {
      80      636104 :     master_nodes.push_back(node);
      81      636104 :     master_weights.push_back(1.0);
      82      636104 :     masters_found = true;
      83             :   }
      84             :   else
      85             :   {
      86     7030779 :     for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
      87             :     {
      88     7030779 :       if (_embedded_nodes[i] == node)
      89             :       {
      90     7028853 :         master_nodes.push_back(_edge_node1);
      91     7028853 :         master_nodes.push_back(_edge_node2);
      92     7028853 :         master_weights.push_back(1.0 - _intersection_x[i]);
      93     7028853 :         master_weights.push_back(_intersection_x[i]);
      94             :         masters_found = true;
      95     7028853 :         break;
      96             :       }
      97             :     }
      98             :   }
      99     7664957 :   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       21466 : EFAEdge::addIntersection(double position, EFANode * embedded_node_tmp, EFANode * from_node)
     133             : {
     134       21466 :   _embedded_nodes.push_back(embedded_node_tmp);
     135       21466 :   if (from_node == _edge_node1)
     136       21466 :     _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       21466 : }
     142             : 
     143             : void
     144        1500 : EFAEdge::resetIntersection(double position, EFANode * embedded_node_tmp, EFANode * from_node)
     145             : {
     146        1500 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     147             :   {
     148        1500 :     if (_embedded_nodes[i] == embedded_node_tmp)
     149             :     {
     150        1500 :       if (from_node == _edge_node1)
     151        1500 :         _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        1500 : }
     160             : 
     161             : void
     162      156821 : EFAEdge::copyIntersection(const EFAEdge & other, unsigned int from_node_id)
     163             : {
     164      156821 :   _embedded_nodes.clear();
     165      156821 :   _intersection_x.clear();
     166      156821 :   _embedded_nodes = other._embedded_nodes;
     167      156821 :   if (from_node_id == 0)
     168      156821 :     _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      156821 :   if (_embedded_nodes.size() != _intersection_x.size())
     177           0 :     EFAError("in copyIntersection num emb_nodes must == num of inters_x");
     178      156821 : }
     179             : 
     180             : EFANode *
     181    30108134 : EFAEdge::getNode(unsigned int index) const
     182             : {
     183    30108134 :   if (index == 0)
     184    16080335 :     return _edge_node1;
     185    14027799 :   else if (index == 1)
     186    14027799 :     return _edge_node2;
     187             :   else
     188           0 :     EFAError("In getNode index out of bounds");
     189             : }
     190             : 
     191             : void
     192        9072 : EFAEdge::reverseNodes()
     193             : {
     194             :   std::swap(_edge_node1, _edge_node2);
     195        9072 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     196           0 :     _intersection_x[i] = 1.0 - _intersection_x[i];
     197        9072 : }
     198             : 
     199             : bool
     200     4214962 : EFAEdge::hasIntersection() const
     201             : {
     202             :   bool has = false;
     203     4214962 :   if (_edge_node1->parent() != nullptr)
     204       64814 :     has = has || _edge_node1->parent()->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT;
     205             : 
     206     4214962 :   if (_edge_node2->parent() != nullptr)
     207       65002 :     has = has || _edge_node2->parent()->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT;
     208             : 
     209     4214434 :   return has || _embedded_nodes.size() > 0;
     210             : }
     211             : 
     212             : bool
     213      219167 : EFAEdge::hasIntersectionAtPosition(double position, EFANode * from_node) const
     214             : {
     215             :   bool has_int = false;
     216      219167 :   if (hasIntersection())
     217             :   {
     218             :     double tmp_intersection_x = -1.0;
     219      193630 :     if (from_node == _edge_node1)
     220             :       tmp_intersection_x = position;
     221        3794 :     else if (from_node == _edge_node2)
     222        3794 :       tmp_intersection_x = 1.0 - position;
     223             :     else
     224           0 :       EFAError("In hasIntersectionAtPosition from_node does not exist on edge");
     225             : 
     226      193870 :     for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     227             :     {
     228      193654 :       if (std::abs(tmp_intersection_x - _intersection_x[i]) < Xfem::tol)
     229             :       {
     230             :         has_int = true;
     231             :         break;
     232             :       }
     233             :     }
     234             :   }
     235      219167 :   return has_int;
     236             : }
     237             : 
     238             : double
     239        1580 : EFAEdge::getIntersection(unsigned int emb_id, EFANode * from_node) const
     240             : {
     241        1580 :   if (from_node == _edge_node1)
     242        1580 :     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       10118 : EFAEdge::distanceFromNode1(EFANode * node) const
     251             : {
     252             :   double xi = -100.0;
     253       10118 :   if (_edge_node1 == node)
     254             :     xi = 0.0;
     255        7331 :   else if (_edge_node2 == node)
     256             :     xi = 1.0;
     257        3104 :   else if (isEmbeddedNode(node))
     258             :   {
     259        3104 :     unsigned int embedded_node_id = getEmbeddedNodeIndex(node);
     260        3104 :     xi = _intersection_x[embedded_node_id];
     261             :   }
     262             :   else
     263           0 :     EFAError("the given node is not found in the current edge");
     264       10118 :   return xi;
     265             : }
     266             : 
     267             : bool
     268   309745995 : EFAEdge::isEmbeddedNode(const EFANode * node) const
     269             : {
     270             :   bool is_emb = false;
     271   391275720 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     272             :   {
     273   118939068 :     if (_embedded_nodes[i] == node)
     274             :     {
     275             :       is_emb = true;
     276             :       break;
     277             :     }
     278             :   }
     279   309745995 :   return is_emb;
     280             : }
     281             : 
     282             : unsigned int
     283        3104 : EFAEdge::getEmbeddedNodeIndex(EFANode * node) const
     284             : {
     285             :   unsigned int index;
     286             :   bool have_index = false;
     287        3104 :   for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     288             :   {
     289        3104 :     if (_embedded_nodes[i] == node)
     290             :     {
     291             :       have_index = true;
     292             :       index = i;
     293             :       break;
     294             :     }
     295             :   }
     296        3104 :   if (!have_index)
     297           0 :     EFAError("In getEmbeddedNodeIndex, could not find index");
     298        3104 :   return index;
     299             : }
     300             : 
     301             : unsigned int
     302      193014 : EFAEdge::getEmbeddedNodeIndex(double position, EFANode * from_node) const
     303             : {
     304             :   bool have_index = false;
     305             :   unsigned int index;
     306      193014 :   if (hasIntersection())
     307             :   {
     308             :     double tmp_intersection_x = -1.0; // dist from edge_node1
     309      193014 :     if (from_node == _edge_node1)
     310             :       tmp_intersection_x = position;
     311        3794 :     else if (from_node == _edge_node2)
     312        3794 :       tmp_intersection_x = 1.0 - position;
     313             :     else
     314           0 :       EFAError("In getEmbeddedNodeIndex, from_node does not exist on edge");
     315             : 
     316      193038 :     for (unsigned int i = 0; i < _embedded_nodes.size(); ++i)
     317             :     {
     318      193038 :       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      193014 :   if (!have_index)
     327           0 :     EFAError("In getEmbeddedNodeIndex, could not find index");
     328      193014 :   return index;
     329             : }
     330             : 
     331             : EFANode *
     332      275779 : EFAEdge::getEmbeddedNode(unsigned int index) const
     333             : {
     334      275779 :   if (index < _embedded_nodes.size())
     335      275779 :     return _embedded_nodes[index];
     336             :   else
     337           0 :     EFAError("in getEmbeddedNode index out of bounds");
     338             : }
     339             : 
     340             : unsigned int
     341      506617 : EFAEdge::numEmbeddedNodes() const
     342             : {
     343      506617 :   return _embedded_nodes.size();
     344             : }
     345             : 
     346             : void
     347     6563649 : EFAEdge::consistencyCheck()
     348             : {
     349             :   bool consistent = true;
     350     7057609 :   if ((_edge_node1->category() == EFANode::N_CATEGORY_PERMANENT ||
     351    12674117 :        _edge_node1->category() == EFANode::N_CATEGORY_TEMP) &&
     352     6110468 :       _edge_node2->category() == EFANode::N_CATEGORY_LOCAL_INDEX)
     353             :     consistent = false;
     354     7057609 :   else if ((_edge_node2->category() == EFANode::N_CATEGORY_PERMANENT ||
     355    12674117 :             _edge_node2->category() == EFANode::N_CATEGORY_TEMP) &&
     356     6110468 :            _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     6563649 :   if (_embedded_nodes.size() != _intersection_x.size())
     361           0 :     EFAError("In consistencyCheck num of emb_nodes must be = num of inters_x");
     362     6563649 : }
     363             : 
     364             : void
     365     3466593 : EFAEdge::switchNode(EFANode * new_node, EFANode * old_node)
     366             : {
     367     3466593 :   if (_edge_node1 == old_node)
     368      319834 :     _edge_node1 = new_node;
     369     3146759 :   else if (_edge_node2 == old_node)
     370      319834 :     _edge_node2 = new_node;
     371     2826925 :   else if (isEmbeddedNode(old_node))
     372             :   {
     373           0 :     unsigned int id = getEmbeddedNodeIndex(old_node);
     374           0 :     _embedded_nodes[id] = new_node;
     375             :   }
     376     3466593 : }
     377             : 
     378             : bool
     379   346109342 : EFAEdge::containsNode(const EFANode * node) const
     380             : {
     381   346109342 :   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