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 : }