LCOV - code coverage report
Current view: top level - src/actions - CohesiveZoneAction.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #32971 (54bef8) with base c6cf66 Lines: 175 214 81.8 %
Date: 2026-05-29 20:40:07 Functions: 12 13 92.3 %
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 "CohesiveZoneAction.h"
      11             : #include "AddAuxVariableAction.h"
      12             : #include "Factory.h"
      13             : #include "FEProblem.h"
      14             : #include "Conversion.h"
      15             : 
      16             : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_interface_kernel");
      17             : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_material");
      18             : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_master_action_material");
      19             : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_aux_variable");
      20             : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_aux_kernel");
      21             : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_kernel");
      22             : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "validate_coordinate_systems");
      23             : 
      24             : InputParameters
      25         138 : CohesiveZoneAction::validParams()
      26             : {
      27         138 :   InputParameters params = CohesiveZoneActionBase::validParams();
      28         138 :   params.addClassDescription("Action to create an instance of the cohesive zone model kernel for "
      29             :                              "each displacement component");
      30         276 :   params.addRequiredParam<std::vector<BoundaryName>>(
      31             :       "boundary", "The list of boundary IDs from the mesh where the cohesive zone will be applied");
      32         138 :   return params;
      33           0 : }
      34             : 
      35         138 : CohesiveZoneAction::CohesiveZoneAction(const InputParameters & params)
      36             :   : CohesiveZoneActionBase(params),
      37         276 :     _displacements(getParam<std::vector<VariableName>>("displacements")),
      38         138 :     _ndisp(_displacements.size()),
      39         276 :     _use_AD(getParam<bool>("use_automatic_differentiation")),
      40         428 :     _base_name(isParamValid("base_name") && !getParam<std::string>("base_name").empty()
      41         138 :                    ? getParam<std::string>("base_name")
      42             :                    : ""),
      43         276 :     _boundary(getParam<std::vector<BoundaryName>>("boundary")),
      44         276 :     _strain(getParam<MooseEnum>("strain").getEnum<Strain>()),
      45         276 :     _save_in_primary(getParam<std::vector<AuxVariableName>>("save_in_primary")),
      46         276 :     _diag_save_in_primary(getParam<std::vector<AuxVariableName>>("diag_save_in_primary")),
      47         276 :     _save_in_secondary(getParam<std::vector<AuxVariableName>>("save_in_secondary")),
      48         414 :     _diag_save_in_secondary(getParam<std::vector<AuxVariableName>>("diag_save_in_secondary")),
      49         276 :     _material_output_order(getParam<MultiMooseEnum>("material_output_order")),
      50         414 :     _material_output_family(getParam<MultiMooseEnum>("material_output_family")),
      51         414 :     _verbose(getParam<bool>("verbose"))
      52             : {
      53             :   // We can't enforce consistency between the number of displacement variables and the mesh
      54             :   // dimension. Hence we only check we have a reasonable number of displacement variables
      55         138 :   if (_ndisp > 3 || _ndisp < 1)
      56           0 :     mooseError("the CZM Action requires 1, 2 or 3 displacement variables.");
      57             : 
      58         138 :   switch (_strain)
      59             :   {
      60          93 :     case Strain::Small:
      61             :     {
      62             :       _czm_kernel_name =
      63         182 :           _use_AD ? "ADCZMInterfaceKernelSmallStrain" : "CZMInterfaceKernelSmallStrain";
      64          93 :       _disp_jump_provider_name = _use_AD ? "ADCZMComputeDisplacementJumpSmallStrain"
      65         182 :                                          : "CZMComputeDisplacementJumpSmallStrain";
      66             :       _equilibrium_traction_calculator_name =
      67         182 :           _use_AD ? "ADCZMComputeGlobalTractionSmallStrain" : "CZMComputeGlobalTractionSmallStrain";
      68             :       break;
      69             :     }
      70          45 :     case Strain::Finite:
      71             :     {
      72             :       _czm_kernel_name =
      73          86 :           _use_AD ? "ADCZMInterfaceKernelTotalLagrangian" : "CZMInterfaceKernelTotalLagrangian";
      74          45 :       _disp_jump_provider_name = _use_AD ? "ADCZMComputeDisplacementJumpTotalLagrangian"
      75          86 :                                          : "CZMComputeDisplacementJumpTotalLagrangian";
      76          45 :       _equilibrium_traction_calculator_name = _use_AD ? "ADCZMComputeGlobalTractionTotalLagrangian"
      77          86 :                                                       : "CZMComputeGlobalTractionTotalLagrangian";
      78             :       break;
      79             :     }
      80           0 :     default:
      81           0 :       mooseError("CohesiveZoneAction Error: Invalid kinematic parameter. Allowed values are: "
      82             :                  "SmallStrain or TotalLagrangian");
      83             :   }
      84             : 
      85         138 :   if (_save_in_primary.size() != 0 && _save_in_primary.size() != _ndisp)
      86           0 :     mooseError(
      87             :         "Number of save_in_primary variables should equal to the number of displacement variables ",
      88           0 :         _ndisp);
      89         138 :   if (_diag_save_in_primary.size() != 0 && _diag_save_in_primary.size() != _ndisp)
      90           0 :     mooseError(
      91             :         "Number of diag_save_in_primary variables should equal to the number of displacement "
      92             :         "variables ",
      93           0 :         _ndisp);
      94         138 :   if (_save_in_secondary.size() != 0 && _save_in_secondary.size() != _ndisp)
      95           0 :     mooseError("Number of save_in_secondary variables should equal to the number of displacement "
      96             :                "variables ",
      97           0 :                _ndisp);
      98             : 
      99         138 :   if (_diag_save_in_secondary.size() != 0 && _diag_save_in_secondary.size() != _ndisp)
     100           0 :     mooseError(
     101             :         "Number of diag_save_in_secondary variables should equal to the number of displacement "
     102             :         "variables ",
     103           0 :         _ndisp);
     104             : 
     105             :   // convert output variable names to lower case
     106        1052 :   for (const auto & out : getParam<MultiMooseEnum>("generate_output"))
     107             :   {
     108             :     std::string lower(out);
     109             :     std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
     110         776 :     _generate_output.push_back(lower);
     111             :   }
     112             : 
     113         138 :   if (!_generate_output.empty())
     114          80 :     verifyOrderAndFamilyOutputs();
     115         138 : }
     116             : 
     117             : void
     118         134 : CohesiveZoneAction::addRequiredCZMInterfaceKernels()
     119             : {
     120         492 :   for (unsigned int i = 0; i < _ndisp; ++i)
     121             :   {
     122             :     // Create unique kernel name for each displacement component
     123        1074 :     std::string unique_kernel_name = _czm_kernel_name + "_" + _name + "_" + Moose::stringify(i);
     124             : 
     125         358 :     InputParameters paramsk = _factory.getValidParams(_czm_kernel_name);
     126             : 
     127         358 :     paramsk.set<unsigned int>("component") = i;
     128         716 :     paramsk.set<NonlinearVariableName>("variable") = _displacements[i];
     129        1074 :     paramsk.set<std::vector<VariableName>>("neighbor_var") = {_displacements[i]};
     130         358 :     paramsk.set<std::vector<VariableName>>("displacements") = _displacements;
     131         358 :     paramsk.set<std::vector<BoundaryName>>("boundary") = _boundary;
     132         716 :     paramsk.set<std::string>("base_name") = _base_name;
     133             : 
     134             :     std::string save_in_side;
     135             :     std::vector<AuxVariableName> save_in_var_names;
     136         358 :     if (_save_in_primary.size() == _ndisp || _save_in_secondary.size() == _ndisp)
     137             :     {
     138           0 :       prepareSaveInInputs(save_in_var_names, save_in_side, _save_in_primary, _save_in_secondary, i);
     139           0 :       paramsk.set<std::vector<AuxVariableName>>("save_in") = save_in_var_names;
     140           0 :       paramsk.set<MultiMooseEnum>("save_in_var_side") = save_in_side;
     141             :     }
     142         358 :     if (_diag_save_in_primary.size() == _ndisp || _diag_save_in_secondary.size() == _ndisp)
     143             :     {
     144           0 :       prepareSaveInInputs(
     145           0 :           save_in_var_names, save_in_side, _diag_save_in_primary, _diag_save_in_secondary, i);
     146           0 :       paramsk.set<std::vector<AuxVariableName>>("diag_save_in") = save_in_var_names;
     147           0 :       paramsk.set<MultiMooseEnum>("diag_save_in_var_side") = save_in_side;
     148             :     }
     149         358 :     _problem->addInterfaceKernel(_czm_kernel_name, unique_kernel_name, paramsk);
     150         716 :   }
     151         134 : }
     152             : 
     153             : void
     154         134 : CohesiveZoneAction::addRequiredCZMInterfaceMaterials()
     155             : {
     156             :   // Create unique material name for the "CZMComputeDisplacementJump" object
     157         134 :   std::string unique_material_name = _disp_jump_provider_name + "_" + _name;
     158         134 :   InputParameters paramsm = _factory.getValidParams(_disp_jump_provider_name);
     159         134 :   paramsm.set<std::vector<BoundaryName>>("boundary") = _boundary;
     160             :   ;
     161         134 :   paramsm.set<std::vector<VariableName>>("displacements") = _displacements;
     162         134 :   paramsm.set<std::string>("base_name") = _base_name;
     163         134 :   _problem->addInterfaceMaterial(_disp_jump_provider_name, unique_material_name, paramsm);
     164             : 
     165             :   // Create unique material name for the "CZMComputeGlobalTraction" object
     166         134 :   unique_material_name = _equilibrium_traction_calculator_name + "_" + _name;
     167         134 :   paramsm = _factory.getValidParams(_equilibrium_traction_calculator_name);
     168         134 :   paramsm.set<std::vector<BoundaryName>>("boundary") = _boundary;
     169             :   ;
     170         134 :   paramsm.set<std::string>("base_name") = _base_name;
     171         134 :   _problem->addInterfaceMaterial(
     172             :       _equilibrium_traction_calculator_name, unique_material_name, paramsm);
     173         268 : }
     174             : 
     175             : void
     176         940 : CohesiveZoneAction::act()
     177             : {
     178             :   // Enforce consistency
     179         940 :   if (_ndisp != _mesh->dimension())
     180           0 :     paramError("displacements", "Number of displacements must match problem dimension.");
     181             : 
     182         940 :   chekMultipleActionParameters();
     183             : 
     184         938 :   if (_current_task == "add_interface_kernel")
     185         134 :     addRequiredCZMInterfaceKernels();
     186         804 :   else if (_current_task == "add_master_action_material")
     187         134 :     addRequiredCZMInterfaceMaterials();
     188             : 
     189             :   // optional, add required outputs
     190         938 :   actOutputGeneration();
     191         938 : }
     192             : 
     193             : void
     194         406 : CohesiveZoneAction::addRelationshipManagers(Moose::RelationshipManagerType input_rm_type)
     195             : {
     196         406 :   InputParameters ips = _factory.getValidParams(_czm_kernel_name);
     197         406 :   addRelationshipManagers(input_rm_type, ips);
     198         406 : }
     199             : 
     200             : void
     201           0 : CohesiveZoneAction::prepareSaveInInputs(std::vector<AuxVariableName> & save_in_names,
     202             :                                         std::string & save_in_side,
     203             :                                         const std::vector<AuxVariableName> & var_name_primary,
     204             :                                         const std::vector<AuxVariableName> & var_name_secondary,
     205             :                                         const int & i) const
     206             : {
     207           0 :   save_in_names.clear();
     208             :   save_in_side.clear();
     209           0 :   if (var_name_primary.size() == _ndisp)
     210             :   {
     211           0 :     save_in_names.push_back(var_name_primary[i]);
     212             :     save_in_side += "m";
     213           0 :     if (var_name_secondary.size() == _ndisp)
     214             :       save_in_side += " ";
     215             :   }
     216           0 :   if (var_name_secondary.size() == _ndisp)
     217             :   {
     218           0 :     save_in_names.push_back(var_name_secondary[i]);
     219             :     save_in_side += "s";
     220             :   }
     221           0 : }
     222             : 
     223             : void
     224          80 : CohesiveZoneAction::verifyOrderAndFamilyOutputs()
     225             : {
     226             :   // Ensure material output order and family vectors are same size as generate output
     227             : 
     228             :   // check number of supplied orders and families
     229          80 :   if (_material_output_order.size() > 1 && _material_output_order.size() < _generate_output.size())
     230           0 :     paramError("material_output_order",
     231             :                "The number of orders assigned to material outputs must be: 0 to be assigned "
     232             :                "CONSTANT; 1 to assign all outputs the same value, or the same size as the number "
     233             :                "of generate outputs listed.");
     234             : 
     235          80 :   if (_material_output_family.size() > 1 &&
     236           0 :       _material_output_family.size() < _generate_output.size())
     237           0 :     paramError("material_output_family",
     238             :                "The number of families assigned to material outputs must be: 0 to be assigned "
     239             :                "MONOMIAL; 1 to assign all outputs the same value, or the same size as the number "
     240             :                "of generate outputs listed.");
     241             : 
     242             :   // if no value was provided, chose the default CONSTANT
     243          80 :   if (_material_output_order.size() == 0)
     244         144 :     _material_output_order.setAdditionalValue("CONSTANT");
     245             : 
     246             :   // For only one order, make all orders the same magnitude
     247          80 :   if (_material_output_order.size() == 1)
     248             :     _material_output_order =
     249          80 :         std::vector<std::string>(_generate_output.size(), _material_output_order[0]);
     250             : 
     251          80 :   if (_verbose)
     252           0 :     Moose::out << COLOR_CYAN << "*** Automatic applied material output orders ***"
     253             :                << "\n"
     254           0 :                << _name << ": " << Moose::stringify(_material_output_order) << "\n"
     255           0 :                << COLOR_DEFAULT;
     256             : 
     257             :   // if no value was provided, chose the default MONOMIAL
     258          80 :   if (_material_output_family.size() == 0)
     259         160 :     _material_output_family.setAdditionalValue("MONOMIAL");
     260             : 
     261             :   // For only one family, make all families that value
     262          80 :   if (_material_output_family.size() == 1)
     263             :     _material_output_family =
     264          80 :         std::vector<std::string>(_generate_output.size(), _material_output_family[0]);
     265             : 
     266          80 :   if (_verbose)
     267           0 :     Moose::out << COLOR_CYAN << "*** Automatic applied material output families ***"
     268             :                << "\n"
     269           0 :                << _name << ": " << Moose::stringify(_material_output_family) << "\n"
     270           0 :                << COLOR_DEFAULT;
     271          80 : }
     272             : 
     273             : void
     274         938 : CohesiveZoneAction::actOutputGeneration()
     275             : {
     276         938 :   if (_current_task == "add_material")
     277         134 :     actOutputMatProp();
     278             : 
     279             :   // Add variables (optional)
     280         938 :   if (_current_task == "add_aux_variable")
     281             :   {
     282             :     unsigned int index = 0;
     283         910 :     for (auto out : _generate_output)
     284             :     {
     285         776 :       const auto & order = _material_output_order[index];
     286         776 :       const auto & family = _material_output_family[index];
     287             : 
     288         696 :       std::string type = (order == "CONSTANT" && family == "MONOMIAL")
     289             :                              ? "MooseVariableConstMonomial"
     290        1552 :                              : "MooseVariable";
     291             : 
     292             :       // Create output helper aux variables
     293         776 :       auto params = _factory.getValidParams(type);
     294         776 :       params.set<MooseEnum>("order") = order;
     295         776 :       params.set<MooseEnum>("family") = family;
     296         776 :       if (family == "MONOMIAL")
     297        1552 :         _problem->addAuxVariable(type, addBaseName(out), params);
     298             :       else
     299           0 :         _problem->addVariable(type, addBaseName(out), params);
     300             : 
     301         776 :       index++;
     302         776 :     }
     303             :   }
     304             : 
     305             :   // Add output AuxKernels
     306         804 :   else if (_current_task == "add_aux_kernel")
     307             :   {
     308         260 :     const std::string material_output_aux_name = _use_AD ? "ADMaterialRealAux" : "MaterialRealAux";
     309             :     // Loop through output aux variables
     310             :     unsigned int index = 0;
     311         910 :     for (auto out : _generate_output)
     312             :     {
     313         776 :       if (_material_output_family[index] == "MONOMIAL")
     314             :       {
     315         776 :         InputParameters params = _factory.getValidParams(material_output_aux_name);
     316        2328 :         params.set<MaterialPropertyName>("property") = addBaseName(out);
     317        2328 :         params.set<AuxVariableName>("variable") = addBaseName(out);
     318         776 :         params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
     319         776 :         params.set<std::vector<BoundaryName>>("boundary") = _boundary;
     320         776 :         params.set<bool>("check_boundary_restricted") = false;
     321         776 :         _problem->addAuxKernel(material_output_aux_name, addBaseName(out) + '_' + name(), params);
     322         776 :       }
     323         776 :       index++;
     324             :     }
     325             :   }
     326         938 : }
     327             : 
     328             : void
     329         134 : CohesiveZoneAction::actOutputMatProp()
     330             : {
     331         134 :   if (_current_task == "add_material")
     332             :   {
     333             :     // Add output Materials
     334         910 :     for (auto out : _generate_output)
     335             :     {
     336         776 :       InputParameters params = emptyInputParameters();
     337             : 
     338             :       // RealVectorCartesianComponent
     339        1248 :       if (
     340        1552 :           [&]()
     341             :           {
     342        2160 :             for (const auto & vq : _real_vector_cartesian_component_table)
     343        6464 :               for (unsigned int a = 0; a < 3; ++a)
     344       10160 :                 if (vq.first + '_' + _component_table[a] == out)
     345             :                 {
     346         472 :                   auto type = _use_AD ? "ADCZMRealVectorCartesianComponent"
     347             :                                       : "CZMRealVectorCartesianComponent";
     348         472 :                   params = _factory.getValidParams(type);
     349         472 :                   params.set<std::string>("real_vector_value") = vq.second;
     350         472 :                   params.set<unsigned int>("index") = a;
     351         472 :                   params.set<std::vector<BoundaryName>>("boundary") = _boundary;
     352        1416 :                   params.set<MaterialPropertyName>("property_name") = addBaseName(out);
     353         472 :                   params.set<std::string>("base_name") = _base_name;
     354        1416 :                   _problem->addInterfaceMaterial(type, addBaseName(out) + '_' + name(), params);
     355             :                   return true;
     356             :                 }
     357             :             return false;
     358         776 :           }())
     359         472 :         continue;
     360             : 
     361             :       // CZMRealVectorScalar
     362         608 :       if (setupOutput(out,
     363             :                       _vector_direction_table,
     364         304 :                       [&](std::string prop_name, std::string direction)
     365             :                       {
     366         304 :                         auto type = _use_AD ? "ADCZMRealVectorScalar" : "CZMRealVectorScalar";
     367         304 :                         params = _factory.getValidParams(type);
     368         304 :                         params.set<std::string>("real_vector_value") = prop_name;
     369         304 :                         params.set<MooseEnum>("direction") = direction;
     370         912 :                         params.set<MaterialPropertyName>("property_name") = addBaseName(out);
     371         304 :                         params.set<std::vector<BoundaryName>>("boundary") = _boundary;
     372         304 :                         params.set<std::string>("base_name") = _base_name;
     373         912 :                         _problem->addInterfaceMaterial(
     374         304 :                             type, addBaseName(out) + '_' + name(), params);
     375         304 :                       }))
     376         304 :         continue;
     377             : 
     378           0 :       mooseError("CZM Master: unable to add output Material");
     379         776 :     }
     380             :   }
     381         134 : }
     382             : 
     383             : void
     384         940 : CohesiveZoneAction::chekMultipleActionParameters()
     385             : {
     386             : 
     387             :   // Gather info about all other master actions when we add variables
     388         940 :   if (_current_task == "validate_coordinate_systems")
     389             :   {
     390         136 :     auto actions = _awh.getActions<CohesiveZoneAction>();
     391         307 :     for (const auto & action : actions)
     392             :     {
     393             :       const auto size_before = _boundary_name_union.size();
     394         172 :       const auto added_size = action->_boundary.size();
     395         172 :       _boundary_name_union.insert(action->_boundary.begin(), action->_boundary.end());
     396             :       const auto size_after = _boundary_name_union.size();
     397         172 :       if (size_after != size_before + added_size)
     398           1 :         mooseError("The boundary restrictions in the CohesiveZoneAction actions must be "
     399             :                    "non-overlapping.");
     400             :     }
     401             : 
     402         304 :     for (const auto & action : actions)
     403             :     {
     404             :       // check for different strain definitions
     405         170 :       _strain_formulation_union.insert(action->_strain);
     406             :       const auto size_after = _strain_formulation_union.size();
     407             : 
     408         170 :       if (size_after != 1)
     409           1 :         mooseError("All blocks of the CohesiveZoneAction should have the same strain formulation");
     410             :     }
     411         134 :   }
     412         938 : }

Generated by: LCOV version 1.14