LCOV - code coverage report
Current view: top level - src/actions - XFEMAction.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31653 (1b25b3) with base 4e5abd Lines: 151 160 94.4 %
Date: 2025-11-02 01:26:22 Functions: 3 3 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 "XFEMAction.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "FEProblem.h"
      14             : #include "NonlinearSystem.h"
      15             : #include "Executioner.h"
      16             : #include "MooseEnum.h"
      17             : #include "Parser.h"
      18             : #include "Factory.h"
      19             : #include "AddVariableAction.h"
      20             : #include "MooseApp.h"
      21             : #include "InputParameterWarehouse.h"
      22             : 
      23             : #include "GeometricCutUserObject.h"
      24             : #include "CrackFrontDefinition.h"
      25             : 
      26             : #include "libmesh/transient_system.h"
      27             : #include "libmesh/string_to_enum.h"
      28             : 
      29             : // XFEM includes
      30             : #include "XFEM.h"
      31             : 
      32             : registerMooseAction("XFEMApp", XFEMAction, "setup_xfem");
      33             : 
      34             : registerMooseAction("XFEMApp", XFEMAction, "add_aux_variable");
      35             : 
      36             : registerMooseAction("XFEMApp", XFEMAction, "add_aux_kernel");
      37             : 
      38             : registerMooseAction("XFEMApp", XFEMAction, "add_variable");
      39             : 
      40             : registerMooseAction("XFEMApp", XFEMAction, "add_kernel");
      41             : 
      42             : registerMooseAction("XFEMApp", XFEMAction, "add_bc");
      43             : 
      44             : InputParameters
      45         433 : XFEMAction::validParams()
      46             : {
      47         433 :   InputParameters params = Action::validParams();
      48             : 
      49         866 :   params.addParam<std::vector<UserObjectName>>(
      50             :       "geometric_cut_userobjects",
      51             :       {},
      52             :       "List of names of GeometricCutUserObjects with cut info and methods");
      53         866 :   params.addParam<std::string>("qrule", "volfrac", "XFEM quadrature rule to use");
      54        1299 :   params.addRangeCheckedParam<unsigned int>(
      55             :       "debug_output_level",
      56         866 :       1,
      57             :       "debug_output_level <= 3",
      58             :       "Controls the amount of debug output from XFEM.  0: None, 1: Summary, 2: Details on "
      59             :       "modifications to mesh, 3: Full dump of element fragment algorithm mesh");
      60        1299 :   params.addRangeCheckedParam<Real>("min_weight_multiplier",
      61         866 :                                     1.e-3,
      62             :                                     "min_weight_multiplier >= 0 & min_weight_multiplier<=1",
      63             :                                     "Minimum average multiplier applied by XFEM to integration "
      64             :                                     "point weights for partial elements");
      65         866 :   params.addParam<bool>("output_cut_plane", false, "Output the XFEM cut plane and volume fraction");
      66         866 :   params.addParam<bool>("use_crack_growth_increment", false, "Use fixed crack growth increment");
      67         866 :   params.addParam<Real>("crack_growth_increment", 0.1, "Crack growth increment");
      68         866 :   params.addParam<bool>("use_crack_tip_enrichment", false, "Use crack tip enrichment functions");
      69         866 :   params.addParam<UserObjectName>("crack_front_definition",
      70             :                                   "The CrackFrontDefinition user object name (only "
      71             :                                   "needed if 'use_crack_tip_enrichment=true')");
      72         866 :   params.addParam<std::vector<VariableName>>("displacements",
      73             :                                              "Names of displacement variables (only "
      74             :                                              "needed if 'use_crack_tip_enrichment=true')");
      75         866 :   params.addParam<std::vector<VariableName>>("enrichment_displacements",
      76             :                                              "Names of enrichment displacement variables (only "
      77             :                                              "needed if 'use_crack_tip_enrichment=true')");
      78         866 :   params.addParam<std::vector<BoundaryName>>("cut_off_boundary",
      79             :                                              "Boundary that contains all nodes for which "
      80             :                                              "enrichment DOFs should be fixed away from crack tip "
      81             :                                              "(only needed if 'use_crack_tip_enrichment=true')");
      82         866 :   params.addParam<Real>("cut_off_radius",
      83             :                         "The cut off radius of crack tip enrichment functions (only needed if "
      84             :                         "'use_crack_tip_enrichment=true')");
      85         433 :   params.addClassDescription("Action to input general parameters and simulation options for use "
      86             :                              "in XFEM.");
      87         433 :   return params;
      88           0 : }
      89             : 
      90         433 : XFEMAction::XFEMAction(const InputParameters & params)
      91             :   : Action(params),
      92         433 :     _geom_cut_userobjects(getParam<std::vector<UserObjectName>>("geometric_cut_userobjects")),
      93        1299 :     _xfem_qrule(getParam<std::string>("qrule")),
      94         433 :     _xfem_cut_plane(false),
      95         866 :     _xfem_use_crack_growth_increment(getParam<bool>("use_crack_growth_increment")),
      96         866 :     _xfem_crack_growth_increment(getParam<Real>("crack_growth_increment")),
      97        1299 :     _use_crack_tip_enrichment(getParam<bool>("use_crack_tip_enrichment"))
      98             : {
      99         433 :   _order = "CONSTANT";
     100         433 :   _family = "MONOMIAL";
     101         866 :   if (isParamValid("output_cut_plane"))
     102         866 :     _xfem_cut_plane = getParam<bool>("output_cut_plane");
     103             : 
     104         433 :   if (_use_crack_tip_enrichment)
     105             :   {
     106           8 :     if (isParamValid("crack_front_definition"))
     107           4 :       _crack_front_definition = getParam<UserObjectName>("crack_front_definition");
     108             :     else
     109           0 :       mooseError("To add crack tip enrichment, crack_front_definition must be provided.");
     110             : 
     111           8 :     if (isParamValid("displacements"))
     112           8 :       _displacements = getParam<std::vector<VariableName>>("displacements");
     113             :     else
     114           0 :       mooseError("To add crack tip enrichment, displacements must be provided.");
     115             : 
     116           8 :     if (isParamValid("enrichment_displacements"))
     117             :     {
     118          12 :       _enrich_displacements = getParam<std::vector<VariableName>>("enrichment_displacements");
     119           4 :       if (_enrich_displacements.size() != 8 && _displacements.size() == 2)
     120           0 :         mooseError("The number of enrichment displacements should be total 8 for 2D.");
     121           4 :       else if (_enrich_displacements.size() != 12 && _displacements.size() == 3)
     122           0 :         mooseError("The number of enrichment displacements should be total 12 for 3D.");
     123             :     }
     124             :     else
     125           0 :       mooseError("To add crack tip enrichment, enrichment_displacements must be provided.");
     126             : 
     127           8 :     if (isParamValid("cut_off_boundary"))
     128           8 :       _cut_off_bc = getParam<std::vector<BoundaryName>>("cut_off_boundary");
     129             :     else
     130           0 :       mooseError("To add crack tip enrichment, cut_off_boundary must be provided.");
     131             : 
     132           8 :     if (isParamValid("cut_off_radius"))
     133           8 :       _cut_off_radius = getParam<Real>("cut_off_radius");
     134             :     else
     135           0 :       mooseError("To add crack tip enrichment, cut_off_radius must be provided.");
     136             :   }
     137         433 : }
     138             : 
     139             : void
     140        2594 : XFEMAction::act()
     141             : {
     142             : 
     143        2594 :   std::shared_ptr<XFEMInterface> xfem_interface = _problem->getXFEM();
     144        2594 :   if (xfem_interface == nullptr)
     145             :   {
     146         433 :     const auto & params = _app.getInputParameterWarehouse().getInputParameters();
     147         433 :     InputParameters & pars(*(params.find(uniqueActionName())->second.get()));
     148         433 :     pars.set<FEProblemBase *>("_fe_problem_base") = &*_problem;
     149         433 :     std::shared_ptr<XFEM> new_xfem(new XFEM(_pars));
     150         866 :     _problem->initXFEM(new_xfem);
     151         866 :     xfem_interface = _problem->getXFEM();
     152             :   }
     153             : 
     154        2594 :   std::shared_ptr<XFEM> xfem = MooseSharedNamespace::dynamic_pointer_cast<XFEM>(xfem_interface);
     155        2594 :   if (xfem == nullptr)
     156           0 :     mooseError("dynamic cast of xfem object failed");
     157             : 
     158        2594 :   if (_current_task == "setup_xfem")
     159             :   {
     160         432 :     xfem->setXFEMQRule(_xfem_qrule);
     161             : 
     162         432 :     xfem->setCrackGrowthMethod(_xfem_use_crack_growth_increment, _xfem_crack_growth_increment);
     163         864 :     xfem->setDebugOutputLevel(getParam<unsigned int>("debug_output_level"));
     164        1296 :     xfem->setMinWeightMultiplier(getParam<Real>("min_weight_multiplier"));
     165             :   }
     166        2162 :   else if (_current_task == "add_variable" && _use_crack_tip_enrichment)
     167             :   {
     168           4 :     auto var_params = _factory.getValidParams("MooseVariable");
     169           8 :     var_params.set<MooseEnum>("family") = "LAGRANGE";
     170           8 :     var_params.set<MooseEnum>("order") = "FIRST";
     171             : 
     172          36 :     for (const auto & enrich_disp : _enrich_displacements)
     173          64 :       _problem->addVariable("MooseVariable", enrich_disp, var_params);
     174           4 :   }
     175        2158 :   else if (_current_task == "add_kernel" && _use_crack_tip_enrichment)
     176             :   {
     177          36 :     for (unsigned int i = 0; i < _enrich_displacements.size(); ++i)
     178             :     {
     179          64 :       InputParameters params = _factory.getValidParams("CrackTipEnrichmentStressDivergenceTensors");
     180          64 :       params.set<NonlinearVariableName>("variable") = _enrich_displacements[i];
     181          32 :       params.set<unsigned int>("component") = i / 4;
     182          32 :       params.set<unsigned int>("enrichment_component") = i % 4;
     183          32 :       params.set<UserObjectName>("crack_front_definition") = _crack_front_definition;
     184          32 :       params.set<std::vector<VariableName>>("enrichment_displacements") = _enrich_displacements;
     185          32 :       params.set<std::vector<VariableName>>("displacements") = _displacements;
     186          32 :       _problem->addKernel(
     187             :           "CrackTipEnrichmentStressDivergenceTensors", _enrich_displacements[i], params);
     188          32 :     }
     189             :   }
     190        2154 :   else if (_current_task == "add_bc" && _use_crack_tip_enrichment)
     191             :   {
     192          36 :     for (unsigned int i = 0; i < _enrich_displacements.size(); ++i)
     193             :     {
     194          64 :       InputParameters params = _factory.getValidParams("CrackTipEnrichmentCutOffBC");
     195          64 :       params.set<NonlinearVariableName>("variable") = _enrich_displacements[i];
     196          32 :       params.set<Real>("value") = 0;
     197          32 :       params.set<std::vector<BoundaryName>>("boundary") = _cut_off_bc;
     198          32 :       params.set<Real>("cut_off_radius") = _cut_off_radius;
     199          32 :       params.set<UserObjectName>("crack_front_definition") = _crack_front_definition;
     200          32 :       _problem->addBoundaryCondition(
     201             :           "CrackTipEnrichmentCutOffBC", _enrich_displacements[i], params);
     202          32 :     }
     203             :   }
     204        2150 :   else if (_current_task == "add_aux_variable" && _xfem_cut_plane)
     205             :   {
     206         433 :     auto var_params = _factory.getValidParams("MooseVariableConstMonomial");
     207             : 
     208         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut_origin_x", var_params);
     209         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut_origin_y", var_params);
     210         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut_origin_z", var_params);
     211         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut_normal_x", var_params);
     212         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut_normal_y", var_params);
     213         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut_normal_z", var_params);
     214         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut2_origin_x", var_params);
     215         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut2_origin_y", var_params);
     216         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut2_origin_z", var_params);
     217         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut2_normal_x", var_params);
     218         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut2_normal_y", var_params);
     219         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_cut2_normal_z", var_params);
     220         866 :     _problem->addAuxVariable("MooseVariableConstMonomial", "xfem_volfrac", var_params);
     221         433 :   }
     222        1717 :   else if (_current_task == "add_aux_kernel" && _xfem_cut_plane)
     223             :   {
     224         432 :     InputParameters params = _factory.getValidParams("XFEMVolFracAux");
     225         864 :     params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_BEGIN;
     226         864 :     params.set<AuxVariableName>("variable") = "xfem_volfrac";
     227         864 :     _problem->addAuxKernel("XFEMVolFracAux", "xfem_volfrac", params);
     228             : 
     229         432 :     params = _factory.getValidParams("XFEMCutPlaneAux");
     230         432 :     params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
     231             : 
     232             :     // first cut plane
     233         432 :     params.set<unsigned int>("plane_id") = 0;
     234             : 
     235         864 :     params.set<AuxVariableName>("variable") = "xfem_cut_origin_x";
     236         864 :     params.set<MooseEnum>("quantity") = "origin_x";
     237         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut_origin_x", params);
     238             : 
     239         864 :     params.set<AuxVariableName>("variable") = "xfem_cut_origin_y";
     240         864 :     params.set<MooseEnum>("quantity") = "origin_y";
     241         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut_origin_y", params);
     242             : 
     243         864 :     params.set<AuxVariableName>("variable") = "xfem_cut_origin_z";
     244         864 :     params.set<MooseEnum>("quantity") = "origin_z";
     245         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut_origin_z", params);
     246             : 
     247         864 :     params.set<AuxVariableName>("variable") = "xfem_cut_normal_x";
     248         864 :     params.set<MooseEnum>("quantity") = "normal_x";
     249         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut_normal_x", params);
     250             : 
     251         864 :     params.set<AuxVariableName>("variable") = "xfem_cut_normal_y";
     252         864 :     params.set<MooseEnum>("quantity") = "normal_y";
     253         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut_normal_y", params);
     254             : 
     255         864 :     params.set<AuxVariableName>("variable") = "xfem_cut_normal_z";
     256         864 :     params.set<MooseEnum>("quantity") = "normal_z";
     257         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut_normal_z", params);
     258             : 
     259             :     // second cut plane
     260         432 :     params.set<unsigned int>("plane_id") = 1;
     261             : 
     262         864 :     params.set<AuxVariableName>("variable") = "xfem_cut2_origin_x";
     263         864 :     params.set<MooseEnum>("quantity") = "origin_x";
     264         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut2_origin_x", params);
     265             : 
     266         864 :     params.set<AuxVariableName>("variable") = "xfem_cut2_origin_y";
     267         864 :     params.set<MooseEnum>("quantity") = "origin_y";
     268         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut2_origin_y", params);
     269             : 
     270         864 :     params.set<AuxVariableName>("variable") = "xfem_cut2_origin_z";
     271         864 :     params.set<MooseEnum>("quantity") = "origin_z";
     272         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut2_origin_z", params);
     273             : 
     274         864 :     params.set<AuxVariableName>("variable") = "xfem_cut2_normal_x";
     275         864 :     params.set<MooseEnum>("quantity") = "normal_x";
     276         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut2_normal_x", params);
     277             : 
     278         864 :     params.set<AuxVariableName>("variable") = "xfem_cut2_normal_y";
     279         864 :     params.set<MooseEnum>("quantity") = "normal_y";
     280         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut2_normal_y", params);
     281             : 
     282         864 :     params.set<AuxVariableName>("variable") = "xfem_cut2_normal_z";
     283         864 :     params.set<MooseEnum>("quantity") = "normal_z";
     284         864 :     _problem->addAuxKernel("XFEMCutPlaneAux", "xfem_cut2_normal_z", params);
     285         432 :   }
     286        2594 : }

Generated by: LCOV version 1.14