LCOV - code coverage report
Current view: top level - src/base - XFEMCutElem2D.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31405 (292dce) with base fef103 Lines: 226 257 87.9 %
Date: 2025-09-04 07:58:55 Functions: 15 16 93.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 "XFEMCutElem2D.h"
      11             : 
      12             : #include "EFANode.h"
      13             : #include "EFAEdge.h"
      14             : #include "EFAFragment2D.h"
      15             : #include "XFEMFuncs.h"
      16             : #include "MooseError.h"
      17             : 
      18             : #include "libmesh/mesh.h"
      19             : #include "libmesh/elem.h"
      20             : #include "libmesh/node.h"
      21             : #include "libmesh/petsc_macro.h"
      22             : #include "petscblaslapack.h"
      23             : 
      24        9298 : XFEMCutElem2D::XFEMCutElem2D(Elem * elem,
      25             :                              const EFAElement2D * const CEMelem,
      26             :                              unsigned int n_qpoints,
      27        9298 :                              unsigned int n_sides)
      28        9298 :   : XFEMCutElem(elem, n_qpoints, n_sides), _efa_elem2d(CEMelem, true)
      29             : {
      30        9298 :   computePhysicalVolumeFraction();
      31        9298 : }
      32             : 
      33       18596 : XFEMCutElem2D::~XFEMCutElem2D() {}
      34             : 
      35             : Point
      36     4227238 : XFEMCutElem2D::getNodeCoordinates(EFANode * CEMnode, MeshBase * displaced_mesh) const
      37             : {
      38             :   Point node_coor(0.0, 0.0, 0.0);
      39             :   std::vector<EFANode *> master_nodes;
      40             :   std::vector<Point> master_points;
      41             :   std::vector<double> master_weights;
      42             : 
      43     4227238 :   _efa_elem2d.getMasterInfo(CEMnode, master_nodes, master_weights);
      44    12321762 :   for (unsigned int i = 0; i < master_nodes.size(); ++i)
      45             :   {
      46     8094524 :     if (master_nodes[i]->category() == EFANode::N_CATEGORY_LOCAL_INDEX)
      47             :     {
      48     8094524 :       Node * node = _nodes[master_nodes[i]->id()];
      49     8094524 :       if (displaced_mesh)
      50     5719292 :         node = displaced_mesh->node_ptr(node->id());
      51     8094524 :       Point node_p((*node)(0), (*node)(1), 0.0);
      52     8094524 :       master_points.push_back(node_p);
      53             :     }
      54             :     else
      55           0 :       mooseError("master nodes must be local");
      56             :   }
      57    12321762 :   for (unsigned int i = 0; i < master_nodes.size(); ++i)
      58             :     node_coor += master_weights[i] * master_points[i];
      59     4227238 :   return node_coor;
      60     4227238 : }
      61             : 
      62             : void
      63       92665 : XFEMCutElem2D::computePhysicalVolumeFraction()
      64             : {
      65             :   Real frag_vol = 0.0;
      66             : 
      67             :   // Calculate area of entire element and fragment using the formula:
      68             :   // A = 1/2 sum_{i=0}^{n-1} (x_i y_{i+1} - x_{i+1} y{i})
      69             : 
      70      453274 :   for (unsigned int i = 0; i < _efa_elem2d.getFragment(0)->numEdges(); ++i)
      71             :   {
      72      360609 :     Point edge_p1 = getNodeCoordinates(_efa_elem2d.getFragmentEdge(0, i)->getNode(0));
      73      360609 :     Point edge_p2 = getNodeCoordinates(_efa_elem2d.getFragmentEdge(0, i)->getNode(1));
      74      360609 :     frag_vol += 0.5 * (edge_p1(0) - edge_p2(0)) * (edge_p1(1) + edge_p2(1));
      75             :   }
      76       92665 :   _physical_volfrac = frag_vol / _elem_volume;
      77       92665 : }
      78             : 
      79             : void
      80          18 : XFEMCutElem2D::computePhysicalFaceAreaFraction(unsigned int side)
      81             : {
      82             :   Real frag_surf = 0.0;
      83             : 
      84          18 :   EFAEdge * edge = _efa_elem2d.getEdge(side);
      85             : 
      86          42 :   for (unsigned int i = 0; i < _efa_elem2d.getFragment(0)->numEdges(); ++i)
      87             :   {
      88          42 :     EFANode * node_1 = _efa_elem2d.getFragmentEdge(0, i)->getNode(0);
      89          42 :     EFANode * node_2 = _efa_elem2d.getFragmentEdge(0, i)->getNode(1);
      90             : 
      91             :     /// find a fragment edge which is covered by element side
      92          42 :     if (edge->containsNode(node_1) && edge->containsNode(node_2))
      93             :     {
      94          18 :       Point edge_p1 = getNodeCoordinates(node_1);
      95          18 :       Point edge_p2 = getNodeCoordinates(node_2);
      96          18 :       frag_surf = (edge_p1 - edge_p2).norm();
      97          18 :       _physical_areafrac[side] = frag_surf / _elem_side_area[side];
      98             :       return;
      99             :     }
     100             :   }
     101           0 :   _physical_areafrac[side] = 1.0;
     102             : }
     103             : 
     104             : void
     105         348 : XFEMCutElem2D::computeMomentFittingWeights()
     106             : {
     107             :   // Purpose: calculate new weights via moment-fitting method
     108         348 :   std::vector<Point> elem_nodes(_n_nodes, Point(0.0, 0.0, 0.0));
     109             :   std::vector<std::vector<Real>> wsg;
     110             : 
     111        1740 :   for (unsigned int i = 0; i < _n_nodes; ++i)
     112        1392 :     elem_nodes[i] = (*_nodes[i]);
     113             : 
     114         348 :   if (_efa_elem2d.isPartial() && _n_qpoints <= 6) // ONLY work for <= 6 q_points
     115             :   {
     116             :     std::vector<std::vector<Real>> tsg;
     117         348 :     getPhysicalQuadraturePoints(tsg); // get tsg - QPs within partial element
     118         348 :     solveMomentFitting(
     119             :         _n_nodes, _n_qpoints, elem_nodes, tsg, wsg); // get wsg - QPs from moment-fitting
     120         348 :     _new_weights.resize(wsg.size(), 1.0);
     121        1776 :     for (unsigned int i = 0; i < wsg.size(); ++i)
     122        1428 :       _new_weights[i] = wsg[i][2]; // weight multiplier
     123         348 :   }
     124             :   else
     125           0 :     _new_weights.resize(_n_qpoints, _physical_volfrac);
     126         348 : }
     127             : 
     128             : Point
     129      486576 : XFEMCutElem2D::getCutPlaneOrigin(unsigned int plane_id, MeshBase * displaced_mesh) const
     130             : {
     131             :   Point orig(0.0, 0.0, 0.0);
     132             :   std::vector<std::vector<EFANode *>> cut_line_nodes;
     133     2387062 :   for (unsigned int i = 0; i < _efa_elem2d.getFragment(0)->numEdges(); ++i)
     134             :   {
     135     1900486 :     if (_efa_elem2d.getFragment(0)->isEdgeInterior(i))
     136             :     {
     137      490644 :       std::vector<EFANode *> node_line(2, nullptr);
     138      490644 :       node_line[0] = _efa_elem2d.getFragmentEdge(0, i)->getNode(0);
     139      490644 :       node_line[1] = _efa_elem2d.getFragmentEdge(0, i)->getNode(1);
     140      490644 :       cut_line_nodes.push_back(node_line);
     141      490644 :     }
     142             :   }
     143      486576 :   if (cut_line_nodes.size() == 0)
     144           0 :     mooseError("no cut line found in this element");
     145      486576 :   if (plane_id < cut_line_nodes.size()) // valid plane_id
     146      331254 :     orig = getNodeCoordinates(cut_line_nodes[plane_id][0], displaced_mesh);
     147      486576 :   return orig;
     148      486576 : }
     149             : 
     150             : Point
     151     1113278 : XFEMCutElem2D::getCutPlaneNormal(unsigned int plane_id, MeshBase * displaced_mesh) const
     152             : {
     153             :   Point normal(0.0, 0.0, 0.0);
     154             :   std::vector<std::vector<EFANode *>> cut_line_nodes;
     155     5500892 :   for (unsigned int i = 0; i < _efa_elem2d.getFragment(0)->numEdges(); ++i)
     156             :   {
     157     4387614 :     if (_efa_elem2d.getFragment(0)->isEdgeInterior(i))
     158             :     {
     159     1117346 :       std::vector<EFANode *> node_line(2, nullptr);
     160     1117346 :       node_line[0] = _efa_elem2d.getFragmentEdge(0, i)->getNode(0);
     161     1117346 :       node_line[1] = _efa_elem2d.getFragmentEdge(0, i)->getNode(1);
     162     1117346 :       cut_line_nodes.push_back(node_line);
     163     1117346 :     }
     164             :   }
     165     1113278 :   if (cut_line_nodes.size() == 0)
     166           0 :     mooseError("no cut line found in this element");
     167     1113278 :   if (plane_id < cut_line_nodes.size()) // valid plane_id
     168             :   {
     169      957956 :     Point cut_line_p1 = getNodeCoordinates(cut_line_nodes[plane_id][0], displaced_mesh);
     170      957956 :     Point cut_line_p2 = getNodeCoordinates(cut_line_nodes[plane_id][1], displaced_mesh);
     171             :     Point cut_line = cut_line_p2 - cut_line_p1;
     172      957956 :     Real len = std::sqrt(cut_line.norm_sq());
     173             :     cut_line /= len;
     174      957956 :     normal = Point(cut_line(1), -cut_line(0), 0.0);
     175             :   }
     176     1113278 :   return normal;
     177     1113278 : }
     178             : 
     179             : void
     180        2011 : XFEMCutElem2D::getCrackTipOriginAndDirection(unsigned tip_id,
     181             :                                              Point & origin,
     182             :                                              Point & direction) const
     183             : {
     184             :   // TODO: two cut plane case is not working
     185             :   std::vector<EFANode *> cut_line_nodes;
     186       10033 :   for (unsigned int i = 0; i < _efa_elem2d.getFragment(0)->numEdges(); ++i)
     187             :   {
     188        8022 :     if (_efa_elem2d.getFragment(0)->isEdgeInterior(i))
     189             :     {
     190        2011 :       std::vector<EFANode *> node_line(2, nullptr);
     191        2011 :       node_line[0] = _efa_elem2d.getFragmentEdge(0, i)->getNode(0);
     192        2011 :       node_line[1] = _efa_elem2d.getFragmentEdge(0, i)->getNode(1);
     193        2011 :       if (node_line[1]->id() == tip_id)
     194             :       {
     195         987 :         cut_line_nodes.push_back(node_line[0]);
     196         987 :         cut_line_nodes.push_back(node_line[1]);
     197             :       }
     198        1024 :       else if (node_line[0]->id() == tip_id)
     199             :       {
     200        1024 :         node_line[1] = node_line[0];
     201        1024 :         node_line[0] = _efa_elem2d.getFragmentEdge(0, i)->getNode(1);
     202        1024 :         cut_line_nodes.push_back(node_line[0]);
     203        1024 :         cut_line_nodes.push_back(node_line[1]);
     204             :       }
     205        2011 :     }
     206             :   }
     207        2011 :   if (cut_line_nodes.size() == 0)
     208           0 :     mooseError("no cut line found in this element");
     209             : 
     210        2011 :   Point cut_line_p1 = getNodeCoordinates(cut_line_nodes[0]);
     211        2011 :   Point cut_line_p2 = getNodeCoordinates(cut_line_nodes[1]);
     212             :   Point cut_line = cut_line_p2 - cut_line_p1;
     213        2011 :   Real len = std::sqrt(cut_line.norm_sq());
     214             :   cut_line /= len;
     215        2011 :   origin = cut_line_p2;
     216        2011 :   direction = Point(cut_line(0), cut_line(1), 0.0);
     217        2011 : }
     218             : 
     219             : void
     220           0 : XFEMCutElem2D::getFragmentFaces(std::vector<std::vector<Point>> & frag_faces,
     221             :                                 MeshBase * displaced_mesh) const
     222             : {
     223           0 :   frag_faces.clear();
     224           0 :   for (unsigned int i = 0; i < _efa_elem2d.getFragment(0)->numEdges(); ++i)
     225             :   {
     226           0 :     std::vector<Point> edge_points(2, Point(0.0, 0.0, 0.0));
     227           0 :     edge_points[0] =
     228           0 :         getNodeCoordinates(_efa_elem2d.getFragmentEdge(0, i)->getNode(0), displaced_mesh);
     229           0 :     edge_points[1] =
     230           0 :         getNodeCoordinates(_efa_elem2d.getFragmentEdge(0, i)->getNode(1), displaced_mesh);
     231           0 :     frag_faces.push_back(edge_points);
     232           0 :   }
     233           0 : }
     234             : 
     235             : const EFAElement *
     236     1298225 : XFEMCutElem2D::getEFAElement() const
     237             : {
     238     1298225 :   return &_efa_elem2d;
     239             : }
     240             : 
     241             : unsigned int
     242      171864 : XFEMCutElem2D::numCutPlanes() const
     243             : {
     244             :   unsigned int counter = 0;
     245      859426 :   for (unsigned int i = 0; i < _efa_elem2d.getFragment(0)->numEdges(); ++i)
     246      687562 :     if (_efa_elem2d.getFragment(0)->isEdgeInterior(i))
     247      171864 :       counter += 1;
     248      171864 :   return counter;
     249             : }
     250             : 
     251             : void
     252         348 : XFEMCutElem2D::getPhysicalQuadraturePoints(std::vector<std::vector<Real>> & tsg)
     253             : {
     254             :   // Get the coords for parial element nodes
     255         348 :   EFAFragment2D * frag = _efa_elem2d.getFragment(0);
     256         348 :   unsigned int nnd_pe = frag->numEdges();
     257         348 :   std::vector<Point> frag_points(nnd_pe, Point(0.0, 0.0, 0.0)); // nodal coord of partial elem
     258         348 :   Real jac = 0.0;
     259             : 
     260        1740 :   for (unsigned int j = 0; j < nnd_pe; ++j)
     261        1392 :     frag_points[j] = getNodeCoordinates(frag->getEdge(j)->getNode(0));
     262             : 
     263             :   // Get centroid coords for partial elements
     264             :   Point xcrd(0.0, 0.0, 0.0);
     265        1740 :   for (unsigned int j = 0; j < nnd_pe; ++j)
     266        1392 :     xcrd += frag_points[j];
     267         348 :   xcrd *= (1.0 / nnd_pe);
     268             : 
     269             :   // Get tsg - the physical coords of Gaussian Q-points for partial elements
     270         348 :   if ((nnd_pe == 3) || (nnd_pe == 4)) // partial element is a triangle or quad
     271             :   {
     272             :     std::vector<std::vector<Real>> sg2;
     273         276 :     std::vector<std::vector<Real>> shape(nnd_pe, std::vector<Real>(3, 0.0));
     274         276 :     Xfem::stdQuadr2D(nnd_pe, 2, sg2);
     275        1308 :     for (unsigned int l = 0; l < sg2.size(); ++l)
     276             :     {
     277        1032 :       Xfem::shapeFunc2D(nnd_pe, sg2[l], frag_points, shape, jac, true); // Get shape
     278        1032 :       std::vector<Real> tsg_line(3, 0.0);
     279        4944 :       for (unsigned int k = 0; k < nnd_pe; ++k)
     280             :       {
     281        3912 :         tsg_line[0] += shape[k][2] * frag_points[k](0);
     282        3912 :         tsg_line[1] += shape[k][2] * frag_points[k](1);
     283             :       }
     284        1032 :       if (nnd_pe == 3)                 // tri partial elem
     285         216 :         tsg_line[2] = sg2[l][3] * jac; // total weights
     286             :       else                             // quad partial elem
     287         816 :         tsg_line[2] = sg2[l][2] * jac; // total weights
     288        1032 :       tsg.push_back(tsg_line);
     289        1032 :     }
     290         276 :   }
     291          72 :   else if (nnd_pe >= 5) // partial element is a polygon
     292             :   {
     293         432 :     for (unsigned int j = 0; j < nnd_pe; ++j) // loop all sub-tris
     294             :     {
     295         360 :       std::vector<std::vector<Real>> shape(3, std::vector<Real>(3, 0.0));
     296         360 :       std::vector<Point> subtri_points(3, Point(0.0, 0.0, 0.0)); // sub-tri nodal coords
     297             : 
     298         360 :       int jplus1 = j < nnd_pe - 1 ? j + 1 : 0;
     299         360 :       subtri_points[0] = xcrd;
     300         360 :       subtri_points[1] = frag_points[j];
     301         360 :       subtri_points[2] = frag_points[jplus1];
     302             : 
     303             :       std::vector<std::vector<Real>> sg2;
     304         360 :       Xfem::stdQuadr2D(3, 2, sg2);                  // get sg2
     305        1440 :       for (unsigned int l = 0; l < sg2.size(); ++l) // loop all int pts on a sub-tri
     306             :       {
     307        1080 :         Xfem::shapeFunc2D(3, sg2[l], subtri_points, shape, jac, true); // Get shape
     308        1080 :         std::vector<Real> tsg_line(3, 0.0);
     309        4320 :         for (unsigned int k = 0; k < 3; ++k) // loop sub-tri nodes
     310             :         {
     311        3240 :           tsg_line[0] += shape[k][2] * subtri_points[k](0);
     312        3240 :           tsg_line[1] += shape[k][2] * subtri_points[k](1);
     313             :         }
     314        1080 :         tsg_line[2] = sg2[l][3] * jac;
     315        1080 :         tsg.push_back(tsg_line);
     316        1080 :       }
     317         360 :     }
     318             :   }
     319             :   else
     320           0 :     mooseError("Invalid partial element!");
     321         348 : }
     322             : 
     323             : void
     324         348 : XFEMCutElem2D::solveMomentFitting(unsigned int nen,
     325             :                                   unsigned int nqp,
     326             :                                   std::vector<Point> & elem_nodes,
     327             :                                   std::vector<std::vector<Real>> & tsg,
     328             :                                   std::vector<std::vector<Real>> & wsg)
     329             : {
     330             :   // Get physical coords for the new six-point rule
     331         348 :   std::vector<std::vector<Real>> shape(nen, std::vector<Real>(3, 0.0));
     332             :   std::vector<std::vector<Real>> wss;
     333             : 
     334         348 :   if (nen == 4)
     335             :   {
     336         348 :     wss.resize(_qp_points.size());
     337        1776 :     for (unsigned int i = 0; i < _qp_points.size(); i++)
     338             :     {
     339        1428 :       wss[i].resize(3);
     340        1428 :       wss[i][0] = _qp_points[i](0);
     341        1428 :       wss[i][1] = _qp_points[i](1);
     342        1428 :       wss[i][2] = _qp_weights[i];
     343             :     }
     344             :   }
     345           0 :   else if (nen == 3)
     346             :   {
     347           0 :     wss.resize(_qp_points.size());
     348           0 :     for (unsigned int i = 0; i < _qp_points.size(); i++)
     349             :     {
     350           0 :       wss[i].resize(4);
     351           0 :       wss[i][0] = _qp_points[i](0);
     352           0 :       wss[i][1] = _qp_points[i](1);
     353           0 :       wss[i][2] = 1.0 - _qp_points[i](0) - _qp_points[i](1);
     354           0 :       wss[i][3] = _qp_weights[i];
     355             :     }
     356             :   }
     357             :   else
     358           0 :     mooseError("Invalid element");
     359             : 
     360         348 :   wsg.resize(wss.size());
     361        1776 :   for (unsigned int i = 0; i < wsg.size(); ++i)
     362        1428 :     wsg[i].resize(3, 0.0);
     363         348 :   Real jac = 0.0;
     364         348 :   std::vector<Real> old_weights(wss.size(), 0.0);
     365             : 
     366        1776 :   for (unsigned int l = 0; l < wsg.size(); ++l)
     367             :   {
     368        1428 :     Xfem::shapeFunc2D(nen, wss[l], elem_nodes, shape, jac, true); // Get shape
     369        1428 :     if (nen == 4)                                                 // 2D quad elem
     370        1428 :       old_weights[l] = wss[l][2] * jac;                           // weights for total element
     371             :     else if (nen == 3)                                            // 2D triangle elem
     372           0 :       old_weights[l] = wss[l][3] * jac;
     373             :     else
     374             :       mooseError("Invalid element!");
     375        7140 :     for (unsigned int k = 0; k < nen; ++k) // physical coords of Q-pts
     376             :     {
     377        5712 :       wsg[l][0] += shape[k][2] * elem_nodes[k](0);
     378        5712 :       wsg[l][1] += shape[k][2] * elem_nodes[k](1);
     379             :     }
     380             :   }
     381             : 
     382             :   // Compute weights via moment fitting
     383             :   Real * A;
     384         348 :   A = new Real[wsg.size() * wsg.size()];
     385             :   unsigned ind = 0;
     386        1776 :   for (unsigned int i = 0; i < wsg.size(); ++i)
     387             :   {
     388        1428 :     A[ind] = 1.0; // const
     389        1428 :     if (nqp > 1)
     390        1428 :       A[1 + ind] = wsg[i][0]; // x
     391        1428 :     if (nqp > 2)
     392        1428 :       A[2 + ind] = wsg[i][1]; // y
     393        1428 :     if (nqp > 3)
     394        1428 :       A[3 + ind] = wsg[i][0] * wsg[i][1]; // x*y
     395        1428 :     if (nqp > 4)
     396         108 :       A[4 + ind] = wsg[i][0] * wsg[i][0]; // x^2
     397         108 :     if (nqp > 5)
     398         108 :       A[5 + ind] = wsg[i][1] * wsg[i][1]; // y^2
     399         108 :     if (nqp > 6)
     400           0 :       mooseError("Q-points of more than 6 are not allowed now!");
     401        1428 :     ind = ind + nqp;
     402             :   }
     403             : 
     404             :   Real * b;
     405         348 :   b = new Real[wsg.size()];
     406        1776 :   for (unsigned int i = 0; i < wsg.size(); ++i)
     407        1428 :     b[i] = 0.0;
     408        2460 :   for (unsigned int i = 0; i < tsg.size(); ++i)
     409             :   {
     410        2112 :     b[0] += tsg[i][2];
     411        2112 :     if (nqp > 1)
     412        2112 :       b[1] += tsg[i][2] * tsg[i][0];
     413        2112 :     if (nqp > 2)
     414        2112 :       b[2] += tsg[i][2] * tsg[i][1];
     415        2112 :     if (nqp > 3)
     416        2112 :       b[3] += tsg[i][2] * tsg[i][0] * tsg[i][1];
     417        2112 :     if (nqp > 4)
     418          72 :       b[4] += tsg[i][2] * tsg[i][0] * tsg[i][0];
     419          72 :     if (nqp > 5)
     420          72 :       b[5] += tsg[i][2] * tsg[i][1] * tsg[i][1];
     421          72 :     if (nqp > 6)
     422           0 :       mooseError("Q-points of more than 6 are not allowed now!");
     423             :   }
     424             : 
     425         348 :   PetscBLASInt nrhs = 1;
     426             :   PetscBLASInt info;
     427         348 :   PetscBLASInt n = wsg.size();
     428         348 :   std::vector<PetscBLASInt> ipiv(n);
     429             : 
     430         348 :   LAPACKgesv_(&n, &nrhs, A, &n, &ipiv[0], b, &n, &info);
     431             : 
     432        1776 :   for (unsigned int i = 0; i < wsg.size(); ++i)
     433        1428 :     wsg[i][2] = b[i] / old_weights[i]; // get the multiplier
     434             : 
     435             :   // delete arrays
     436         348 :   delete[] A;
     437         348 :   delete[] b;
     438         348 : }
     439             : 
     440             : void
     441      626702 : XFEMCutElem2D::getIntersectionInfo(unsigned int plane_id,
     442             :                                    Point & normal,
     443             :                                    std::vector<Point> & intersectionPoints,
     444             :                                    MeshBase * displaced_mesh) const
     445             : {
     446      626702 :   intersectionPoints.resize(2); // 2D: the intersection line is straight and can be represented by
     447             :                                 // two ending points.(may have issues with double cuts case!)
     448             : 
     449             :   std::vector<std::vector<EFANode *>> cut_line_nodes;
     450     3113830 :   for (unsigned int i = 0; i < _efa_elem2d.getFragment(0)->numEdges(); ++i)
     451             :   {
     452     2487128 :     if (_efa_elem2d.getFragment(0)->isEdgeInterior(i))
     453             :     {
     454      626702 :       std::vector<EFANode *> node_line(2, nullptr);
     455      626702 :       node_line[0] = _efa_elem2d.getFragmentEdge(0, i)->getNode(0);
     456      626702 :       node_line[1] = _efa_elem2d.getFragmentEdge(0, i)->getNode(1);
     457      626702 :       cut_line_nodes.push_back(node_line);
     458      626702 :     }
     459             :   }
     460      626702 :   if (cut_line_nodes.size() == 0)
     461           0 :     mooseError("No cut line found in this element");
     462             : 
     463      626702 :   if (plane_id < cut_line_nodes.size()) // valid plane_id
     464             :   {
     465      626702 :     intersectionPoints[0] = getNodeCoordinates(cut_line_nodes[plane_id][0], displaced_mesh);
     466      626702 :     intersectionPoints[1] = getNodeCoordinates(cut_line_nodes[plane_id][1], displaced_mesh);
     467             :   }
     468             : 
     469      626702 :   normal = getCutPlaneNormal(plane_id, displaced_mesh);
     470      626702 : }

Generated by: LCOV version 1.14