LCOV - code coverage report
Current view: top level - src/userobjects - LevelSetCutUserObject.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31405 (292dce) with base fef103 Lines: 67 82 81.7 %
Date: 2025-09-04 07:58:55 Functions: 6 9 66.7 %
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 "LevelSetCutUserObject.h"
      11             : #include "SubProblem.h"
      12             : #include "MooseVariable.h"
      13             : #include "libmesh/string_to_enum.h"
      14             : 
      15             : registerMooseObject("XFEMApp", LevelSetCutUserObject);
      16             : 
      17             : InputParameters
      18         270 : LevelSetCutUserObject::validParams()
      19             : {
      20         270 :   InputParameters params = GeometricCutUserObject::validParams();
      21         540 :   params.addRequiredParam<VariableName>(
      22             :       "level_set_var", "The name of level set variable used to represent the interface");
      23         270 :   params.addClassDescription("XFEM mesh cut by level set function");
      24         540 :   params.addParam<CutSubdomainID>(
      25         540 :       "negative_id", 0, "The CutSubdomainID corresponding to a non-positive signed distance");
      26         540 :   params.addParam<CutSubdomainID>(
      27         540 :       "positive_id", 1, "The CutSubdomainID corresponding to a positive signed distance");
      28         270 :   return params;
      29           0 : }
      30             : 
      31         135 : LevelSetCutUserObject::LevelSetCutUserObject(const InputParameters & parameters)
      32             :   : GeometricCutUserObject(parameters),
      33         270 :     _level_set_var_number(_subproblem
      34         135 :                               .getVariable(_tid,
      35         135 :                                            parameters.get<VariableName>("level_set_var"),
      36             :                                            Moose::VarKindType::VAR_ANY,
      37             :                                            Moose::VarFieldType::VAR_FIELD_STANDARD)
      38             :                               .number()),
      39         270 :     _system(_subproblem.getSystem(getParam<VariableName>("level_set_var"))),
      40         135 :     _solution(*_system.current_local_solution.get()),
      41         270 :     _negative_id(getParam<CutSubdomainID>("negative_id")),
      42         405 :     _positive_id(getParam<CutSubdomainID>("positive_id"))
      43             : {
      44             :   mooseAssert(_negative_id != _positive_id,
      45             :               "LevelSetCutUserObject expects different CutSubdomainIDs for the "
      46             :               "negative_id and the positive_id.");
      47         135 : }
      48             : 
      49             : bool
      50       11132 : LevelSetCutUserObject::cutElementByGeometry(const Elem * elem,
      51             :                                             std::vector<Xfem::CutEdge> & cut_edges,
      52             :                                             std::vector<Xfem::CutNode> & /*cut_nodes*/) const
      53             : {
      54             :   bool cut_elem = false;
      55             : 
      56       11132 :   unsigned int n_sides = elem->n_sides();
      57             : 
      58       55660 :   for (unsigned int i = 0; i < n_sides; ++i)
      59             :   {
      60       44528 :     std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
      61             : 
      62       44528 :     if (curr_side->type() != EDGE2)
      63           0 :       mooseError("In LevelSetCutUserObject element side must be EDGE2, but type is: ",
      64           0 :                  libMesh::Utility::enum_to_string(curr_side->type()),
      65             :                  " base element type is: ",
      66           0 :                  libMesh::Utility::enum_to_string(elem->type()));
      67             : 
      68             :     const Node * node1 = curr_side->node_ptr(0);
      69             :     const Node * node2 = curr_side->node_ptr(1);
      70             : 
      71       44528 :     dof_id_type ls_dof_id_1 = node1->dof_number(_system.number(), _level_set_var_number, 0);
      72       44528 :     dof_id_type ls_dof_id_2 = node2->dof_number(_system.number(), _level_set_var_number, 0);
      73             : 
      74       44528 :     Number ls_node_1 = _solution(ls_dof_id_1);
      75       44528 :     Number ls_node_2 = _solution(ls_dof_id_2);
      76             : 
      77       44528 :     if (ls_node_1 * ls_node_2 < 0)
      78             :     {
      79             :       cut_elem = true;
      80             :       Xfem::CutEdge mycut;
      81        2922 :       mycut._id1 = node1->id();
      82        2922 :       mycut._id2 = node2->id();
      83        2922 :       Real seg_int_frac = std::abs(ls_node_1) / std::abs(ls_node_1 - ls_node_2);
      84        2922 :       mycut._distance = seg_int_frac;
      85        2922 :       mycut._host_side_id = i;
      86        2922 :       cut_edges.push_back(mycut);
      87             :     }
      88       44528 :   }
      89             : 
      90       11132 :   return cut_elem;
      91             : }
      92             : 
      93             : bool
      94         750 : LevelSetCutUserObject::cutElementByGeometry(const Elem * elem,
      95             :                                             std::vector<Xfem::CutFace> & cut_faces) const
      96             : {
      97             :   bool cut_elem = false;
      98             : 
      99        5250 :   for (unsigned int i = 0; i < elem->n_sides(); ++i)
     100             :   {
     101        4500 :     std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
     102        4500 :     if (curr_side->dim() != 2)
     103           0 :       mooseError("In LevelSetCutUserObject dimension of side must be 2, but it is ",
     104           0 :                  curr_side->dim());
     105        4500 :     unsigned int n_edges = curr_side->n_sides();
     106             : 
     107             :     std::vector<unsigned int> cut_edges;
     108             :     std::vector<Real> cut_pos;
     109             : 
     110       22500 :     for (unsigned int j = 0; j < n_edges; j++)
     111             :     {
     112             :       // This returns the lowest-order type of side.
     113       18000 :       std::unique_ptr<const Elem> curr_edge = curr_side->side_ptr(j);
     114       18000 :       if (curr_edge->type() != EDGE2)
     115           0 :         mooseError("In LevelSetCutUserObject face edge must be EDGE2, but type is: ",
     116           0 :                    libMesh::Utility::enum_to_string(curr_edge->type()),
     117             :                    " base element type is: ",
     118           0 :                    libMesh::Utility::enum_to_string(elem->type()));
     119             : 
     120             :       const Node * node1 = curr_edge->node_ptr(0);
     121             :       const Node * node2 = curr_edge->node_ptr(1);
     122             : 
     123       18000 :       dof_id_type ls_dof_id_1 = node1->dof_number(_system.number(), _level_set_var_number, 0);
     124       18000 :       dof_id_type ls_dof_id_2 = node2->dof_number(_system.number(), _level_set_var_number, 0);
     125             : 
     126       18000 :       Number ls_node_1 = _solution(ls_dof_id_1);
     127       18000 :       Number ls_node_2 = _solution(ls_dof_id_2);
     128             : 
     129       18000 :       if (ls_node_1 * ls_node_2 < 0)
     130             :       {
     131         378 :         Real seg_int_frac = std::abs(ls_node_1) / std::abs(ls_node_1 - ls_node_2);
     132         378 :         cut_edges.push_back(j);
     133         378 :         cut_pos.push_back(seg_int_frac);
     134             :       }
     135       18000 :     }
     136             : 
     137        4500 :     if (cut_edges.size() == 2)
     138             :     {
     139             :       cut_elem = true;
     140             :       Xfem::CutFace mycut;
     141         189 :       mycut._face_id = i;
     142         189 :       mycut._face_edge.push_back(cut_edges[0]);
     143         189 :       mycut._face_edge.push_back(cut_edges[1]);
     144         189 :       mycut._position.push_back(cut_pos[0]);
     145         189 :       mycut._position.push_back(cut_pos[1]);
     146         189 :       cut_faces.push_back(mycut);
     147             :     }
     148        4500 :   }
     149         750 :   return cut_elem;
     150             : }
     151             : 
     152             : bool
     153         598 : LevelSetCutUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_edges*/,
     154             :                                              std::vector<Xfem::CutEdge> & /*cut_edges*/) const
     155             : {
     156         598 :   return false;
     157             : }
     158             : 
     159             : bool
     160           0 : LevelSetCutUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_faces*/,
     161             :                                              std::vector<Xfem::CutFace> & /*cut_faces*/) const
     162             : {
     163           0 :   mooseError("cutFragmentByGeometry not yet implemented for 3d level set cutting");
     164             :   return false;
     165             : }
     166             : 
     167             : const std::vector<Point>
     168           0 : LevelSetCutUserObject::getCrackFrontPoints(unsigned int /*num_crack_front_points*/) const
     169             : {
     170           0 :   mooseError("getCrackFrontPoints() is not implemented for this object.");
     171             : }
     172             : 
     173             : const std::vector<RealVectorValue>
     174           0 : LevelSetCutUserObject::getCrackPlaneNormals(unsigned int /*num_crack_front_points*/) const
     175             : {
     176           0 :   mooseError("getCrackPlaneNormals() is not implemented for this object.");
     177             : }
     178             : 
     179             : CutSubdomainID
     180        9157 : LevelSetCutUserObject::getCutSubdomainID(const Node * node) const
     181             : {
     182        9157 :   dof_id_type ls_dof_id = node->dof_number(_system.number(), _level_set_var_number, 0);
     183        9157 :   return _solution(ls_dof_id) > 0.0 ? _positive_id : _negative_id;
     184             : }

Generated by: LCOV version 1.14