LCOV - code coverage report
Current view: top level - src/userobjects - NodeValueAtXFEMInterface.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31405 (292dce) with base fef103 Lines: 72 77 93.5 %
Date: 2025-09-04 07:58:55 Functions: 6 6 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 "NodeValueAtXFEMInterface.h"
      11             : #include "MooseVariableFE.h"
      12             : #include "XFEM.h"
      13             : #include "InterfaceMeshCutUserObjectBase.h"
      14             : #include "libmesh/parallel_algebra.h"
      15             : #include "libmesh/parallel.h"
      16             : 
      17             : registerMooseObject("XFEMApp", NodeValueAtXFEMInterface);
      18             : 
      19             : InputParameters
      20          24 : NodeValueAtXFEMInterface::validParams()
      21             : {
      22          24 :   InputParameters params = GeneralUserObject::validParams();
      23          48 :   params.addRequiredParam<VariableName>(
      24             :       "variable", "The name of the variable that this UserObject operates on");
      25          48 :   params.addParam<UserObjectName>(
      26             :       "interface_mesh_cut_userobject",
      27             :       "Name of InterfaceMeshCutUserObject that provides cut locations to this UserObject.");
      28          48 :   params.addRequiredParam<VariableName>(
      29             :       "level_set_var", "The name of level set variable used to represent the interface");
      30          24 :   params.addClassDescription("Obtain field values and gradients on the interface.");
      31          24 :   return params;
      32           0 : }
      33             : 
      34          12 : NodeValueAtXFEMInterface::NodeValueAtXFEMInterface(const InputParameters & parameters)
      35             :   : GeneralUserObject(parameters),
      36          12 :     _mesh(_subproblem.mesh()),
      37          12 :     _var(&_subproblem.getVariable(_tid, parameters.get<VariableName>("variable"))),
      38          12 :     _level_set_var_number(
      39          12 :         _subproblem.getVariable(_tid, parameters.get<VariableName>("level_set_var")).number()),
      40          24 :     _system(_subproblem.getSystem(getParam<VariableName>("level_set_var"))),
      41          24 :     _solution(*_system.current_local_solution.get())
      42             : {
      43          12 : }
      44             : 
      45             : void
      46          60 : NodeValueAtXFEMInterface::initialize()
      47             : {
      48         120 :   _pl = _mesh.getPointLocator();
      49         180 :   _xfem = MooseSharedNamespace::dynamic_pointer_cast<XFEM>(_fe_problem.getXFEM());
      50          60 :   if (_xfem == nullptr)
      51           0 :     mooseError("Problem casting to XFEM in NodeValueAtXFEMInterface");
      52             : 
      53             :   const UserObject * uo =
      54         120 :       &(_fe_problem.getUserObjectBase(getParam<UserObjectName>("interface_mesh_cut_userobject")));
      55             : 
      56          60 :   if (dynamic_cast<const InterfaceMeshCutUserObjectBase *>(uo) == nullptr)
      57           0 :     mooseError("UserObject casting to InterfaceMeshCutUserObjectBase in NodeValueAtXFEMInterface");
      58             : 
      59          60 :   _mesh_cut = dynamic_cast<const InterfaceMeshCutUserObjectBase *>(uo);
      60          60 :   _elem_pairs = _xfem->getXFEMCutElemPairs(_xfem->getGeometricCutID(_mesh_cut));
      61          60 : }
      62             : 
      63             : void
      64          60 : NodeValueAtXFEMInterface::execute()
      65             : {
      66             :   _values_positive_level_set_side.clear();
      67             :   _values_negative_level_set_side.clear();
      68             :   _grad_values_positive_level_set_side.clear();
      69             :   _grad_values_negative_level_set_side.clear();
      70          60 :   _nodes.clear();
      71             : 
      72          60 :   std::shared_ptr<MeshBase> cutter_mesh = _mesh_cut->getCutterMesh();
      73             : 
      74        7560 :   for (const auto & node : cutter_mesh->node_ptr_range())
      75        3780 :     _nodes.push_back(*node);
      76             : 
      77          60 :   _pl->enable_out_of_mesh_mode();
      78             : 
      79        7560 :   for (const auto & node : cutter_mesh->node_ptr_range())
      80             :   {
      81        3720 :     unsigned int i = node->id();
      82             : 
      83        3720 :     if ((*_pl)(*node) != nullptr)
      84             :     {
      85        2760 :       const Elem * elem = getElemContainingPoint(*node, /*positive_level_set = */ true);
      86             : 
      87        2760 :       if (elem != nullptr)
      88             :       {
      89        2070 :         _subproblem.setCurrentSubdomainID(elem, /*_tid */ 0);
      90        2070 :         _subproblem.reinitElemPhys(elem, {*node}, 0);
      91             : 
      92        2070 :         _values_positive_level_set_side[i] = (dynamic_cast<MooseVariable *>(_var))->sln()[0];
      93        2070 :         _grad_values_positive_level_set_side[i] =
      94        2070 :             ((dynamic_cast<MooseVariable *>(_var))->gradSln())[0];
      95             :       }
      96             : 
      97        2760 :       const Elem * elem2 = getElemContainingPoint(*node, false);
      98        2760 :       if (elem2 != nullptr)
      99             :       {
     100        2070 :         _subproblem.setCurrentSubdomainID(elem2, /*_tid */ 0);
     101        2070 :         _subproblem.reinitElemPhys(elem2, {*node}, 0);
     102             : 
     103        2070 :         _values_negative_level_set_side[i] = (dynamic_cast<MooseVariable *>(_var))->sln()[0];
     104        2070 :         _grad_values_negative_level_set_side[i] =
     105        2070 :             ((dynamic_cast<MooseVariable *>(_var))->gradSln())[0];
     106             :       }
     107             :     }
     108             :     else // When node is outside of computation domain
     109             :     {
     110         960 :       _values_positive_level_set_side[i] = 0;
     111         960 :       _values_negative_level_set_side[i] = 0;
     112         960 :       _grad_values_positive_level_set_side[i] = RealVectorValue(0);
     113         960 :       _grad_values_negative_level_set_side[i] = RealVectorValue(0);
     114             :     }
     115          60 :   }
     116          60 : }
     117             : 
     118             : void
     119          60 : NodeValueAtXFEMInterface::finalize()
     120             : {
     121          60 :   _communicator.set_union(_values_positive_level_set_side);
     122          60 :   _communicator.set_union(_grad_values_positive_level_set_side);
     123          60 :   _communicator.set_union(_values_negative_level_set_side);
     124          60 :   _communicator.set_union(_grad_values_negative_level_set_side);
     125          60 : }
     126             : 
     127             : const Elem *
     128        5520 : NodeValueAtXFEMInterface::getElemContainingPoint(const Node & p, bool positive_level_set)
     129             : {
     130        5520 :   const Elem * elem1 = (*_pl)(p);
     131             : 
     132        5520 :   if (elem1->processor_id() != processor_id())
     133             :     return nullptr;
     134             : 
     135             :   const Node * node = elem1->node_ptr(0);
     136             : 
     137        4140 :   dof_id_type ls_dof_id = node->dof_number(_system.number(), _level_set_var_number, 0);
     138             : 
     139        4140 :   Number ls_node_value = _solution(ls_dof_id);
     140             : 
     141             :   bool positive = false;
     142             : 
     143        4140 :   if (_xfem->isPointInsidePhysicalDomain(elem1, *node))
     144             :   {
     145        4140 :     if (ls_node_value > 0.0)
     146             :       positive = true;
     147             :   }
     148             :   else
     149             :   {
     150             :     if (ls_node_value < 0.0)
     151             :       positive = false;
     152             :   }
     153             : 
     154             :   const Elem * elem2 = nullptr;
     155             :   bool found = false;
     156        8280 :   for (auto & pair : *_elem_pairs)
     157             :   {
     158        4140 :     if (pair.first == elem1)
     159             :     {
     160        4140 :       elem2 = pair.second;
     161             :       found = true;
     162             :     }
     163           0 :     else if (pair.second == elem1)
     164             :     {
     165             :       elem2 = pair.first;
     166             :       found = true;
     167             :     }
     168             :   }
     169             : 
     170        4140 :   if (!found)
     171           0 :     mooseError("NodeValueAtXFEMInterface: The interface node ",
     172             :                p,
     173             :                " are not found by element pair locator.");
     174             : 
     175        4140 :   if ((positive && positive_level_set) || (!positive && !positive_level_set))
     176             :     return elem1;
     177             :   else if ((!positive && positive_level_set) || (positive && !positive_level_set))
     178        2070 :     return elem2;
     179             :   else
     180             :     return nullptr;
     181             : }

Generated by: LCOV version 1.14