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 78 : AbaqusUserElement::validParams() 20 : { 21 78 : auto params = GeneralUserObject::validParams(); 22 78 : params += BlockRestrictable::validParams(); 23 78 : params += TaggingInterface::validParams(); 24 78 : params.addClassDescription("Coupling UserObject to use Abaqus UEL plugins in MOOSE"); 25 : 26 : // execute during residual and Jacobian evaluation 27 78 : ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on", true); 28 78 : exec_enum.addAvailableFlags(EXEC_PRE_KERNELS); 29 234 : exec_enum = {EXEC_PRE_KERNELS}; 30 78 : params.suppressParameter<ExecFlagEnum>("execute_on"); 31 : 32 : // Avoid uninitialized residual objects 33 78 : params.suppressParameter<bool>("force_preic"); 34 : 35 : // coupled variables 36 156 : params.addParam<std::vector<NonlinearVariableName>>("variables", "Nonlinear coupled variables"); 37 : // auxiliary variables (including temperature) 38 156 : 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 156 : params.addRequiredParam<FileName>("plugin", "UEL plugin file"); 47 : 48 156 : params.addRequiredParam<std::vector<Real>>( 49 : "constant_properties", "Constant mechanical and thermal material properties (PROPS)"); 50 156 : params.addRequiredParam<unsigned int>("num_state_vars", 51 : "The number of state variables this UMAT is going to use"); 52 : 53 156 : params.addParam<int>("jtype", 0, "Abaqus element type integer"); 54 : 55 78 : return params; 56 78 : } 57 : 58 39 : AbaqusUserElement::AbaqusUserElement(const InputParameters & params) 59 : : GeneralUserObject(params), 60 : BlockRestrictable(this), 61 : TaggingInterface(this), 62 78 : _plugin(getParam<FileName>("plugin")), 63 78 : _library(_plugin + std::string("-") + QUOTE(METHOD) + ".plugin"), 64 39 : _uel(_library.getFunction<uel_t>("uel_")), 65 39 : _moose_mesh(UserObject::_subproblem.mesh()), 66 39 : _mesh(_moose_mesh.getMesh()), 67 39 : _dim(_moose_mesh.dimension()), 68 78 : _variable_names(getParam<std::vector<NonlinearVariableName>>("variables")), 69 117 : _aux_variable_names(getParam<std::vector<AuxVariableName>>("external_fields")), 70 39 : _sub_ids(blockRestricted() ? blockIDs() : _moose_mesh.meshSubdomains()), 71 117 : _props(getParam<std::vector<Real>>("constant_properties")), 72 39 : _nprops(_props.size()), 73 78 : _nstatev(getParam<unsigned int>("num_state_vars")), 74 39 : _statev_index_current(0), 75 39 : _statev_index_old(1), 76 78 : _t_step_old(declareRestartableData<int>("uel_tstep_old", -1)), 77 156 : _jtype(getParam<int>("jtype")) 78 : { 79 : // coupled variables must be nonlinear scalar fields 80 121 : for (const auto & variable_name : _variable_names) 81 : { 82 82 : const auto * var = &UserObject::_subproblem.getVariable( 83 82 : 0, variable_name, Moose::VarKindType::VAR_SOLVER, Moose::VarFieldType::VAR_FIELD_STANDARD); 84 82 : _variables.push_back(var); 85 : 86 : // check block restriction 87 82 : if (!var->hasBlocks(blockIDs())) 88 0 : paramError("variables", "must be defined on all blocks the UEL is operating on."); 89 : } 90 : 91 75 : for (const auto & aux_variable_name : _aux_variable_names) 92 : { 93 : MooseVariableFEBase * aux_var = 94 36 : &UserObject::_subproblem.getVariable(0, 95 : aux_variable_name, 96 : Moose::VarKindType::VAR_AUXILIARY, 97 36 : Moose::VarFieldType::VAR_FIELD_STANDARD); 98 36 : _aux_variables.push_back(aux_var); 99 36 : aux_var->sys().addVariableToZeroOnResidual(aux_variable_name); 100 : 101 : // check block restriction 102 36 : if (!aux_var->hasBlocks(blockIDs())) 103 0 : paramError("aux_variables", "must be defined on all blocks the UEL is operating on."); 104 : } 105 39 : } 106 : 107 : void 108 39 : AbaqusUserElement::initialSetup() 109 : { 110 39 : setupElemRange(); 111 39 : } 112 : 113 : void 114 0 : AbaqusUserElement::meshChanged() 115 : { 116 0 : setupElemRange(); 117 0 : } 118 : 119 : void 120 534 : AbaqusUserElement::timestepSetup() 121 : { 122 : // In case we are on the same timestep, that means this is being redone and we 123 : // don't want to swap the stateful data yet 124 534 : if (_t_step == _t_step_old) 125 : return; 126 : 127 : std::swap(_statev_index_old, _statev_index_current); 128 529 : _t_step_old = _t_step; 129 : } 130 : 131 : void 132 1731 : AbaqusUserElement::initialize() 133 : { 134 1731 : } 135 : 136 : void 137 1731 : AbaqusUserElement::execute() 138 : { 139 : PARALLEL_TRY 140 : { 141 1731 : UELThread ut(_fe_problem, *this); 142 1731 : Threads::parallel_reduce(*_elem_range, ut); 143 1731 : } 144 1731 : PARALLEL_CATCH; 145 1731 : } 146 : 147 : void 148 39 : AbaqusUserElement::setupElemRange() 149 : { 150 : _elem_range = 151 117 : std::make_unique<ConstElemRange>(_mesh.active_local_subdomain_set_elements_begin(_sub_ids), 152 39 : _mesh.active_local_subdomain_set_elements_end(_sub_ids)); 153 : 154 : // prepopulate the statev map outside of a threaded region 155 39 : if (_nstatev > 0) 156 10147 : for (const auto & elem : *_elem_range) 157 : { 158 10108 : _statev[0][elem->id()].resize(_nstatev); 159 10108 : _statev[1][elem->id()].resize(_nstatev); 160 : } 161 39 : }