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