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