LCOV - code coverage report
Current view: top level - src/utils - MeshBaseDiagnosticsUtils.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 50 53 94.3 %
Date: 2025-07-17 01:28:37 Functions: 2 2 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             : // MOOSE includes
      11             : #include "MeshBaseDiagnosticsUtils.h"
      12             : #include "ConsoleStream.h"
      13             : #include "MooseError.h"
      14             : 
      15             : #include "libmesh/elem.h"
      16             : #include "libmesh/node.h"
      17             : #include "libmesh/mesh_base.h"
      18             : #include "libmesh/point_locator_base.h"
      19             : 
      20             : namespace MeshBaseDiagnosticsUtils
      21             : {
      22             : void
      23         192 : checkNonConformalMesh(const std::unique_ptr<MeshBase> & mesh,
      24             :                       const ConsoleStream & console,
      25             :                       const unsigned int num_outputs,
      26             :                       const Real conformality_tol,
      27             :                       unsigned int & num_nonconformal_nodes)
      28             : {
      29         192 :   num_nonconformal_nodes = 0;
      30         192 :   auto pl = mesh->sub_point_locator();
      31         192 :   pl->set_close_to_point_tol(conformality_tol);
      32             : 
      33         192 :   if (!mesh->is_serial())
      34           0 :     mooseError("Only serialized/replicated meshes are supported");
      35             : 
      36             :   // loop on nodes, assumes a replicated mesh
      37       34560 :   for (auto & node : mesh->node_ptr_range())
      38             :   {
      39             :     // find all the elements around this node
      40       17184 :     std::set<const Elem *> elements;
      41       17184 :     (*pl)(*node, elements);
      42             : 
      43             :     // loop through the set of elements near this node
      44       88136 :     for (auto & elem : elements)
      45             :     {
      46             :       // If the node is not part of this element's nodes, it is a
      47             :       // case of non-conformality
      48       70952 :       bool found_conformal = false;
      49             : 
      50      306344 :       for (auto & elem_node : elem->node_ref_range())
      51             :       {
      52      306272 :         if (*node == elem_node)
      53             :         {
      54       70880 :           found_conformal = true;
      55       70880 :           break;
      56             :         }
      57             :       }
      58       70952 :       if (!found_conformal)
      59             :       {
      60          72 :         num_nonconformal_nodes++;
      61          72 :         if (num_nonconformal_nodes < num_outputs)
      62          72 :           console << "Non-conformality detected at  : " << *node << std::endl;
      63           0 :         else if (num_nonconformal_nodes == num_outputs)
      64           0 :           console << "Maximum output reached, log is silenced" << std::endl;
      65             :       }
      66             :     }
      67       17376 :   }
      68         192 :   pl->unset_close_to_point_tol();
      69         192 : }
      70             : 
      71             : bool
      72      463909 : checkFirstOrderEdgeOverlap(const Elem & edge1,
      73             :                            const Elem & edge2,
      74             :                            Point & intersection_point,
      75             :                            const Real intersection_tol)
      76             : {
      77             :   // check that the two elements are of type EDGE2
      78             :   mooseAssert(edge1.type() == EDGE2, "Elements must be of type EDGE2");
      79             :   mooseAssert(edge2.type() == EDGE2, "Elements must be of type EDGE2");
      80             :   // Get nodes from the two edges
      81      463909 :   const Point & p1 = edge1.point(0);
      82      463909 :   const Point & p2 = edge1.point(1);
      83      463909 :   const Point & p3 = edge2.point(0);
      84      463909 :   const Point & p4 = edge2.point(1);
      85             : 
      86             :   // Check that the two edges are not sharing a node
      87      463909 :   if (p1 == p3 || p1 == p4 || p2 == p3 || p2 == p4)
      88      159872 :     return false;
      89             : 
      90             :   /*
      91             :     There's a chance that they overlap. Find shortest line that connects two edges and if its length
      92             :     is close enough to 0 return true The shortest line between the two edges will be perpendicular
      93             :     to both.
      94             :   */
      95      304037 :   const auto d1343 = (p1 - p3) * (p4 - p3);
      96      304037 :   const auto d4321 = (p4 - p3) * (p2 - p1);
      97      304037 :   const auto d1321 = (p1 - p3) * (p2 - p1);
      98      304037 :   const auto d4343 = (p4 - p3) * (p4 - p3);
      99      304037 :   const auto d2121 = (p2 - p1) * (p2 - p1);
     100             : 
     101      304037 :   const auto denominator = d2121 * d4343 - d4321 * d4321;
     102      304037 :   const auto numerator = d1343 * d4321 - d1321 * d4343;
     103             : 
     104      304037 :   if (std::fabs(denominator) < intersection_tol)
     105             :     // This indicates that the two lines are parallel so they don't intersect
     106       42709 :     return false;
     107             : 
     108      261328 :   const auto mua = numerator / denominator;
     109      261328 :   const auto mub = (d1343 + (mua * d4321)) / d4343;
     110             : 
     111             :   // Use these values to solve for the two points that define the shortest line segment
     112      261328 :   const auto pa = p1 + mua * (p2 - p1);
     113      261328 :   const auto pb = p3 + mub * (p4 - p3);
     114             : 
     115             :   // This method assume the two lines are infinite. This check to make sure na and nb are part of
     116             :   // their respective line segments
     117      261328 :   if (mua < 0 || mua > 1)
     118       94696 :     return false;
     119      166632 :   if (mub < 0 || mub > 1)
     120       57688 :     return false;
     121             : 
     122             :   // Calculate distance between these two nodes
     123      108944 :   const auto distance = (pa - pb).norm();
     124      108944 :   if (distance < intersection_tol)
     125             :   {
     126          16 :     intersection_point = pa;
     127          16 :     return true;
     128             :   }
     129             :   else
     130      108928 :     return false;
     131             : }
     132             : }

Generated by: LCOV version 1.14