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