https://mooseframework.inl.gov
UELThread.C
Go to the documentation of this file.
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 "UELThread.h"
11 #include "NonlinearSystemBase.h"
12 
14  : ThreadedElementLoop<ConstElemRange>(fe_problem),
15  _sys(fe_problem.currentNonlinearSystem()),
16  _aux_sys(&_fe_problem.getAuxiliarySystem()),
17  _variables(uel_uo.getVariables()),
18  _aux_variables(uel_uo.getAuxVariables()),
19  _uel_uo(uel_uo),
20  _uel(uel_uo.getPlugin()),
21  _statev_copy(uel_uo._nstatev)
22 {
23  // general solve step
24  _lflags[3] = 0;
25 
26  // newton based solution (should be 1 when using a predictor or maybe at the start of the
27  // iteration)
28  _lflags[4] = 0;
29 }
30 
31 // Splitting Constructor
34  _sys(x._sys),
35  _aux_sys(x._aux_sys),
36  _variables(x._variables),
37  _aux_variables(x._aux_variables),
38  _uel_uo(x._uel_uo),
39  _uel(x._uel),
40  _lflags(x._lflags),
41  _statev_copy(_uel_uo._nstatev)
42 {
43 }
44 
45 void
47 {
48 }
49 
55 void
56 UELThread::onElement(const Elem * elem)
57 {
58  // get all dof indices for the coupled variables on this element
59  int nnode = elem->n_nodes();
60  const auto nvar = _variables.size();
61  _all_dof_indices.resize(nnode * nvar);
62 
63  // ** System variables **
64  // prepare DOF indices in the correct order
65  for (const auto i : index_range(_variables))
66  {
67  _variables[i]->getDofIndices(elem, _var_dof_indices);
68 
69  // sanity checks
70  if (_variables[i]->scalingFactor() != 1)
71  mooseError("Scaling factors other than unity are not yet supported");
72  if (static_cast<int>(_var_dof_indices.size()) != nnode)
73  mooseError("All coupled variables must be full order lagrangian");
74 
75  for (const auto j : make_range(nnode))
76  _all_dof_indices[j * nvar + i] = _var_dof_indices[j];
77  }
78 
79  int ndofel = _all_dof_indices.size();
80 
81  // Get solution values
82  _all_dof_values.resize(ndofel);
83 
85  _all_dof_increments.resize(ndofel);
87 
88  mooseAssert(_all_dof_values.size() == _all_dof_increments.size(), "Inconsistent solution size.");
89  for (const auto i : index_range(_all_dof_values))
91 
92  _all_udot_dof_values.resize(ndofel);
93  _all_udotdot_dof_values.resize(ndofel);
94 
95  // Get u_dot and u_dotdot solution values (required for future expansion of the interface)
96  if (false)
97  {
98  _all_udot_dof_values.resize(ndofel);
100  _all_udotdot_dof_values.resize(ndofel);
102  }
103 
104  // Prepare external fields
105  const auto nvar_aux = _aux_variables.size();
106  _all_aux_var_dof_indices.resize(nnode * nvar_aux);
107  _all_aux_var_dof_increments.resize(nnode * nvar_aux);
108 
109  for (const auto i : index_range(_aux_variables))
110  {
111  _aux_variables[i]->getDofIndices(elem, _aux_var_dof_indices);
112 
113  if (static_cast<int>(_aux_var_dof_indices.size()) != nnode)
114  mooseError("All auxiliary variables must be full order Lagrangian");
115 
116  for (const auto j : make_range(nnode))
118  }
119 
120  _all_aux_var_dof_values.resize(nnode * nvar_aux);
121  _aux_var_values_to_uel.resize(nnode * nvar_aux * 2); // Value _and_ increment
122 
124  _all_aux_var_dof_increments.resize(nnode * nvar_aux);
126 
127  // First, one external field and increment; then, second external field and increment, etc.
128  for (const auto i : index_range(_all_aux_var_dof_values))
130 
131  for (const auto i : index_range(_all_aux_var_dof_values))
132  {
135  }
136  // End of prepare external fields.
137 
138  const bool do_residual = _sys.hasVector(_sys.residualVectorTag());
139  const bool do_jacobian = _sys.hasMatrix(_sys.systemMatrixTag());
140 
141  // set flags
142  if (do_residual && do_jacobian)
143  _lflags[2] = 0;
144  else if (!do_residual && do_jacobian)
145  _lflags[2] = 4;
146  else if (do_residual && !do_jacobian)
147  _lflags[2] = 5;
148  else
149  _lflags[2] = 0;
150 
151  // copy coords
152  int dim = _uel_uo._dim;
153  _coords.resize(nnode * dim);
154  for (const auto i : make_range(nnode))
155  for (const auto j : make_range(dim))
156  _coords[j + dim * i] = elem->node_ref(i)(j);
157 
158  // prepare residual and jacobian storage
159  _local_re.resize(ndofel);
160  _local_ke.resize(ndofel, ndofel);
161 
162  int nrhs = 1; // : RHS should contain the residual vector
163  int jtype = _uel_uo._jtype; // type of user element
164 
165  Real dt = _fe_problem.dt();
166  Real time = _fe_problem.time();
167  std::vector<Real> times{time - dt, time - dt}; // first entry should be the step time (TODO)
168 
169  std::array<Real, 8> energy;
170  int jelem = elem->id() + 1; // User-assigned element number
171  Real pnewdt;
172 
173  int npredf = nvar_aux; // Number of external fields.
174 
175  // dummy vars
176  Real rdummy = 0;
177  int idummy = 0;
178 
179  // stateful data
180  if (_uel_uo._nstatev)
181  {
182  const auto & statev_old = _uel_uo._statev[_uel_uo._statev_index_old][elem->id()];
183  std::copy(statev_old.begin(), statev_old.end(), _statev_copy.begin());
184  }
185 
186  // call the plugin
187  _uel(_local_re.get_values().data(),
188  _local_ke.get_values().data(),
189  _statev_copy.data(),
190  energy.data(),
191  &ndofel,
192  &nrhs,
193  &_uel_uo._nstatev,
194  _uel_uo._props.data(),
195  &_uel_uo._nprops,
196  _coords.data(),
197  &dim,
198  &nnode,
199  _all_dof_values.data() /* U[] */,
200  _all_dof_increments.data() /* DU[] */,
201  _all_udot_dof_values.data() /* V[] */,
202  _all_udotdot_dof_values.data() /* A[] */,
203  &jtype,
204  times.data(),
205  &dt,
206  &idummy /* KSTEP */,
207  &idummy /* KINC */,
208  &jelem,
209  nullptr /* PARAMS[] */,
210  &idummy /* NDLOAD */,
211  nullptr /* JDLTYP[] */,
212  nullptr /* ADLMAG[] */,
213  _aux_var_values_to_uel.data() /* PREDEF[] */,
214  &npredf /* NPREDF */,
215  nullptr /* LFLAGS[] */,
216  &ndofel /* MLVARX */,
217  nullptr /* DDLMAG[] */,
218  &idummy /* MDLOAD */,
219  &pnewdt,
220  nullptr /* JPROPS[] */,
221  &idummy /* NJPROP */,
222  &rdummy /* PERIOD */
223  );
224 
225  if (_uel_uo._nstatev)
226  {
227  auto & statev_current = _uel_uo._statev[_uel_uo._statev_index_current][elem->id()];
228  std::copy(_statev_copy.begin(), _statev_copy.end(), statev_current.begin());
229  }
230 
231  // write to the residual vector
232  // sign of 'residuals' has been tested with external loading and matches that of moose-umat
233  // setups.
234  if (do_residual)
237 
238  // write to the Jacobian (hope we don't have to transpose...)
239  if (do_jacobian)
241  _local_ke,
244  -1.0);
245 }
UELThread(FEProblemBase &fe_problem, AbaqusUserElement &uel_uo)
Definition: UELThread.C:13
std::array< std::map< dof_id_type, std::vector< Real > >, 2 > _statev
virtual Real & time() const
bool hasVector(const std::string &tag_name) const
TagID systemMatrixTag() const override
virtual void subdomainChanged() override final
Definition: UELThread.C:46
virtual void get(const std::vector< numeric_index_type > &index, Number *values) const
void mooseError(Args &&... args)
unsigned int dim
std::vector< Real > _all_udotdot_dof_values
Definition: UELThread.h:44
std::vector< Real > _statev_copy
state variable copy
Definition: UELThread.h:71
int _nstatev
stateful data
std::vector< dof_id_type > _var_dof_indices
dof indices of all coupled variables
Definition: UELThread.h:39
std::vector< Real > _all_aux_var_dof_increments
Definition: UELThread.h:49
void addResiduals(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
const NumericVector< Number > *const & currentSolution() const override
std::vector< Real > _aux_var_values_to_uel
Definition: UELThread.h:51
virtual bool hasMatrix(TagID tag) const
std::vector< dof_id_type > _aux_var_dof_indices
Definition: UELThread.h:47
StoredRange< MeshBase::const_element_iterator, const Elem *> ConstElemRange
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
std::vector< Real > _coords
Definition: UELThread.h:68
void addJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
std::vector< Real > _all_udot_dof_values
Definition: UELThread.h:43
std::size_t _statev_index_current
std::vector< Real > _all_dof_increments
Definition: UELThread.h:42
DenseMatrix< Real > _local_ke
Definition: UELThread.h:54
DenseVector< Real > _local_re
Definition: UELThread.h:53
virtual const NumericVector< Number > *const & currentSolution() const override final
const std::vector< double > x
std::vector< dof_id_type > _all_dof_indices
Definition: UELThread.h:40
virtual NumericVector< Number > * solutionUDot()
std::vector< Real > _all_aux_var_dof_values
Definition: UELThread.h:50
unsigned int number() const
std::vector< Real > & get_values()
TagID residualVectorTag() const override
std::vector< Real > _props
props
AbaqusUserElement & _uel_uo
reference to the userobject (to access parameters)
Definition: UELThread.h:61
This user-object is a testbed for implementing a custom element.
tbb::split split
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const AbaqusUserElement::uel_t & _uel
have a reference to the UEL plugin here
Definition: UELThread.h:64
NonlinearSystemBase & _sys
Current nonlinear system.
Definition: UELThread.h:33
const int _jtype
Abaqus element type.
const std::vector< const MooseVariableFieldBase * > & _aux_variables
Definition: UELThread.h:58
void resize(const unsigned int new_m, const unsigned int new_n)
IntRange< T > make_range(T beg, T end)
std::vector< Real > _all_dof_values
Definition: UELThread.h:41
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::size_t _statev_index_old
std::vector< dof_id_type > _all_aux_var_dof_indices
Definition: UELThread.h:48
NumericVector< Number > & solutionOld()
virtual Real & dt() const
AuxiliarySystem * _aux_sys
Auxiliary system object.
Definition: UELThread.h:36
auto index_range(const T &sizable)
const std::vector< const MooseVariableFieldBase * > & _variables
Definition: UELThread.h:56
virtual void onElement(const Elem *elem) override final
Fortran array memory layout: (1,1), (2,1) (3,1) (1,2) (2,2) (3,2) (1,3) (2,3) (3,3) C++ array memory ...
Definition: UELThread.C:56
std::array< int, 5 > _lflags
parameters for the UEL plugin
Definition: UELThread.h:67
const unsigned int _dim
The dimension of the mesh, e.g. 3 for hexes and tets, 2 for quads and tris.