LCOV - code coverage report
Current view: top level - src/userobjects - AbaqusUserElement.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: f45d79 Lines: 66 71 93.0 %
Date: 2025-07-25 05:00:39 Functions: 6 7 85.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 "AbaqusUserElement.h"
      11             : #include "SystemBase.h"
      12             : #include "UELThread.h"
      13             : 
      14             : #define QUOTE(macro) stringifyName(macro)
      15             : 
      16             : registerMooseObject("SolidMechanicsApp", AbaqusUserElement);
      17             : 
      18             : InputParameters
      19          68 : AbaqusUserElement::validParams()
      20             : {
      21          68 :   auto params = GeneralUserObject::validParams();
      22          68 :   params += BlockRestrictable::validParams();
      23          68 :   params += TaggingInterface::validParams();
      24          68 :   params.addClassDescription("Coupling UserObject to use Abaqus UEL plugins in MOOSE");
      25             : 
      26             :   // execute during residual and Jacobian evaluation
      27          68 :   ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on", true);
      28          68 :   exec_enum.addAvailableFlags(EXEC_PRE_KERNELS);
      29         272 :   exec_enum = {EXEC_PRE_KERNELS, EXEC_TIMESTEP_END};
      30          68 :   params.suppressParameter<ExecFlagEnum>("execute_on");
      31             : 
      32             :   // Avoid uninitialized residual objects
      33          68 :   params.suppressParameter<bool>("force_preic");
      34             : 
      35             :   // coupled variables
      36         136 :   params.addParam<std::vector<NonlinearVariableName>>("variables", "Nonlinear coupled variables");
      37             :   // auxiliary variables (including temperature)
      38         136 :   params.addParam<std::vector<AuxVariableName>>(
      39             :       "external_fields",
      40             :       {},
      41             :       "Auxiliary field variables (or 'predifined field variables') passed to the UEL plugin. Some "
      42             :       "plugins may assume that the first field is temperature when there are multiple external "
      43             :       "fields.");
      44             : 
      45             :   // UEL plugin file
      46         136 :   params.addRequiredParam<FileName>("plugin", "UEL plugin file");
      47             : 
      48         136 :   params.addRequiredParam<std::vector<Real>>(
      49             :       "constant_properties", "Constant mechanical and thermal material properties (PROPS)");
      50         136 :   params.addRequiredParam<unsigned int>("num_state_vars",
      51             :                                         "The number of state variables this UMAT is going to use");
      52             : 
      53         136 :   params.addParam<int>("jtype", 0, "Abaqus element type integer");
      54             : 
      55          68 :   return params;
      56          68 : }
      57             : 
      58          34 : AbaqusUserElement::AbaqusUserElement(const InputParameters & params)
      59             :   : GeneralUserObject(params),
      60             :     BlockRestrictable(this),
      61             :     TaggingInterface(this),
      62          68 :     _plugin(getParam<FileName>("plugin")),
      63          68 :     _library(_plugin + std::string("-") + QUOTE(METHOD) + ".plugin"),
      64          34 :     _uel(_library.getFunction<uel_t>("uel_")),
      65          34 :     _moose_mesh(UserObject::_subproblem.mesh()),
      66          34 :     _mesh(_moose_mesh.getMesh()),
      67          34 :     _dim(_moose_mesh.dimension()),
      68          68 :     _variable_names(getParam<std::vector<NonlinearVariableName>>("variables")),
      69          68 :     _aux_variable_names(getParam<std::vector<AuxVariableName>>("external_fields")),
      70          34 :     _sub_ids(blockRestricted() ? blockIDs() : _moose_mesh.meshSubdomains()),
      71         102 :     _props(getParam<std::vector<Real>>("constant_properties")),
      72          34 :     _nprops(_props.size()),
      73          68 :     _nstatev(getParam<unsigned int>("num_state_vars")),
      74          34 :     _statev_index_current(0),
      75          34 :     _statev_index_old(1),
      76         170 :     _jtype(getParam<int>("jtype"))
      77             : {
      78             :   // coupled variables must be nonlinear scalar fields
      79         106 :   for (const auto & variable_name : _variable_names)
      80             :   {
      81          72 :     const auto * var = &UserObject::_subproblem.getVariable(
      82          72 :         0, variable_name, Moose::VarKindType::VAR_SOLVER, Moose::VarFieldType::VAR_FIELD_STANDARD);
      83          72 :     _variables.push_back(var);
      84             : 
      85             :     // check block restriction
      86          72 :     if (!var->hasBlocks(blockIDs()))
      87           0 :       paramError("variables", "must be defined on all blocks the UEL is operating on.");
      88             :   }
      89             : 
      90          66 :   for (const auto & aux_variable_name : _aux_variable_names)
      91             :   {
      92             :     MooseVariableFEBase * aux_var =
      93          32 :         &UserObject::_subproblem.getVariable(0,
      94             :                                              aux_variable_name,
      95             :                                              Moose::VarKindType::VAR_AUXILIARY,
      96          32 :                                              Moose::VarFieldType::VAR_FIELD_STANDARD);
      97          32 :     _aux_variables.push_back(aux_var);
      98          32 :     aux_var->sys().addVariableToZeroOnResidual(aux_variable_name);
      99             : 
     100             :     // check block restriction
     101          32 :     if (!aux_var->hasBlocks(blockIDs()))
     102           0 :       paramError("aux_variables", "must be defined on all blocks the UEL is operating on.");
     103             :   }
     104          34 : }
     105             : 
     106             : void
     107          34 : AbaqusUserElement::initialSetup()
     108             : {
     109          34 :   setupElemRange();
     110          34 : }
     111             : 
     112             : void
     113           0 : AbaqusUserElement::meshChanged()
     114             : {
     115           0 :   setupElemRange();
     116           0 : }
     117             : 
     118             : void
     119        1874 : AbaqusUserElement::initialize()
     120             : {
     121        1874 : }
     122             : 
     123             : void
     124        1874 : AbaqusUserElement::execute()
     125             : {
     126             :   // swap the current and old state data at the end of a converged timestep
     127        1874 :   if (_fe_problem.getCurrentExecuteOnFlag() == EXEC_TIMESTEP_END)
     128             :   {
     129             :     std::swap(_statev_index_old, _statev_index_current);
     130         450 :     return;
     131             :   }
     132             : 
     133             :   PARALLEL_TRY
     134             :   {
     135        1424 :     UELThread ut(_fe_problem, *this);
     136        1424 :     Threads::parallel_reduce(*_elem_range, ut);
     137        1424 :   }
     138        1424 :   PARALLEL_CATCH;
     139             : }
     140             : 
     141             : void
     142          34 : AbaqusUserElement::setupElemRange()
     143             : {
     144             :   _elem_range =
     145         102 :       std::make_unique<ConstElemRange>(_mesh.active_local_subdomain_set_elements_begin(_sub_ids),
     146          34 :                                        _mesh.active_local_subdomain_set_elements_end(_sub_ids));
     147             : 
     148             :   // prepopulate the statev map outside of a threaded region
     149          34 :   if (_nstatev > 0)
     150        8142 :     for (const auto & elem : *_elem_range)
     151             :     {
     152        8108 :       _statev[0][elem->id()].resize(_nstatev);
     153        8108 :       _statev[1][elem->id()].resize(_nstatev);
     154             :     }
     155          34 : }

Generated by: LCOV version 1.14