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 "MooseVariableData.h"
11 : #include "MooseVariableField.h"
12 : #include "Assembly.h"
13 : #include "MooseError.h"
14 : #include "DisplacedSystem.h"
15 : #include "TimeIntegrator.h"
16 : #include "MooseVariableFE.h"
17 : #include "MooseTypes.h"
18 :
19 : #include "libmesh/quadrature.h"
20 : #include "libmesh/fe_base.h"
21 : #include "libmesh/system.h"
22 : #include "libmesh/type_n_tensor.h"
23 : #include "libmesh/fe_interface.h"
24 :
25 : using namespace libMesh;
26 :
27 : template <typename OutputType>
28 522213 : MooseVariableData<OutputType>::MooseVariableData(const MooseVariableFE<OutputType> & var,
29 : SystemBase & sys,
30 : THREAD_ID tid,
31 : Moose::ElementType element_type,
32 : const QBase * const & qrule_in,
33 : const QBase * const & qrule_face_in,
34 : const Node * const & node,
35 : const Elem * const & elem)
36 :
37 : : MooseVariableDataBase<OutputType>(var, sys, tid),
38 522213 : _var(var),
39 1044426 : _fe_type(var.feType()),
40 522213 : _var_num(var.number()),
41 522213 : _assembly(_subproblem.assembly(_tid, var.kind() == Moose::VAR_SOLVER ? sys.number() : 0)),
42 522213 : _element_type(element_type),
43 522213 : _ad_zero(0),
44 522213 : _has_dof_indices(false),
45 522213 : _qrule(qrule_in),
46 522213 : _qrule_face(qrule_face_in),
47 522213 : _use_dual(var.useDual()),
48 522213 : _second_phi_assembly_method(nullptr),
49 522213 : _second_phi_face_assembly_method(nullptr),
50 522213 : _curl_phi_assembly_method(nullptr),
51 522213 : _curl_phi_face_assembly_method(nullptr),
52 522213 : _div_phi_assembly_method(nullptr),
53 522213 : _div_phi_face_assembly_method(nullptr),
54 522213 : _ad_grad_phi_assembly_method(nullptr),
55 522213 : _ad_grad_phi_face_assembly_method(nullptr),
56 522213 : _time_integrator(nullptr),
57 522213 : _node(node),
58 522213 : _elem(elem),
59 522213 : _displaced(dynamic_cast<const DisplacedSystem *>(&_sys) ? true : false),
60 2611065 : _current_side(_assembly.side())
61 : {
62 522213 : _continuity = FEInterface::get_continuity(_fe_type);
63 :
64 522213 : _is_nodal = (_continuity == C_ZERO || _continuity == C_ONE);
65 :
66 522213 : _time_integrator = _sys.queryTimeIntegrator(_var_num);
67 :
68 : // Initialize AD zero with zero derivatives
69 522213 : const auto old_do = ADReal::do_derivatives;
70 522213 : ADReal::do_derivatives = true;
71 522213 : _ad_zero = 0.;
72 522213 : ADReal::do_derivatives = old_do;
73 :
74 522213 : switch (_element_type)
75 : {
76 174071 : case Moose::ElementType::Element:
77 : {
78 174071 : _phi_assembly_method = &Assembly::fePhi<OutputShape>;
79 174071 : _phi_face_assembly_method = &Assembly::fePhiFace<OutputShape>;
80 174071 : _grad_phi_assembly_method = &Assembly::feGradPhi<OutputShape>;
81 174071 : _grad_phi_face_assembly_method = &Assembly::feGradPhiFace<OutputShape>;
82 174071 : _second_phi_assembly_method = &Assembly::feSecondPhi<OutputShape>;
83 174071 : _second_phi_face_assembly_method = &Assembly::feSecondPhiFace<OutputShape>;
84 174071 : _curl_phi_assembly_method = &Assembly::feCurlPhi<OutputShape>;
85 174071 : _curl_phi_face_assembly_method = &Assembly::feCurlPhiFace<OutputShape>;
86 174071 : _div_phi_assembly_method = &Assembly::feDivPhi<OutputShape>;
87 174071 : _div_phi_face_assembly_method = &Assembly::feDivPhiFace<OutputShape>;
88 174071 : _ad_grad_phi_assembly_method = &Assembly::feADGradPhi<OutputShape>;
89 174071 : _ad_grad_phi_face_assembly_method = &Assembly::feADGradPhiFace<OutputShape>;
90 :
91 174071 : _ad_grad_phi = &_ad_grad_phi_assembly_method(_assembly, _fe_type);
92 174071 : _ad_grad_phi_face = &_ad_grad_phi_face_assembly_method(_assembly, _fe_type);
93 174071 : break;
94 : }
95 174071 : case Moose::ElementType::Neighbor:
96 : {
97 174071 : _phi_assembly_method = &Assembly::fePhiNeighbor<OutputShape>;
98 174071 : _phi_face_assembly_method = &Assembly::fePhiFaceNeighbor<OutputShape>;
99 174071 : _grad_phi_assembly_method = &Assembly::feGradPhiNeighbor<OutputShape>;
100 174071 : _grad_phi_face_assembly_method = &Assembly::feGradPhiFaceNeighbor<OutputShape>;
101 174071 : _second_phi_assembly_method = &Assembly::feSecondPhiNeighbor<OutputShape>;
102 174071 : _second_phi_face_assembly_method = &Assembly::feSecondPhiFaceNeighbor<OutputShape>;
103 174071 : _curl_phi_assembly_method = &Assembly::feCurlPhiNeighbor<OutputShape>;
104 174071 : _curl_phi_face_assembly_method = &Assembly::feCurlPhiFaceNeighbor<OutputShape>;
105 174071 : _div_phi_assembly_method = &Assembly::feDivPhiNeighbor<OutputShape>;
106 174071 : _div_phi_face_assembly_method = &Assembly::feDivPhiFaceNeighbor<OutputShape>;
107 :
108 174071 : _ad_grad_phi = nullptr;
109 174071 : _ad_grad_phi_face = nullptr;
110 174071 : break;
111 : }
112 174071 : case Moose::ElementType::Lower:
113 : {
114 174071 : if (_use_dual)
115 : {
116 135 : _phi_assembly_method = &Assembly::feDualPhiLower<OutputType>;
117 135 : _phi_face_assembly_method = &Assembly::feDualPhiLower<OutputType>; // Place holder
118 135 : _grad_phi_assembly_method = &Assembly::feGradDualPhiLower<OutputType>;
119 135 : _grad_phi_face_assembly_method = &Assembly::feGradDualPhiLower<OutputType>; // Place holder
120 : }
121 : else
122 : {
123 173936 : _phi_assembly_method = &Assembly::fePhiLower<OutputType>;
124 173936 : _phi_face_assembly_method = &Assembly::fePhiLower<OutputType>; // Place holder
125 173936 : _grad_phi_assembly_method = &Assembly::feGradPhiLower<OutputType>;
126 173936 : _grad_phi_face_assembly_method = &Assembly::feGradPhiLower<OutputType>; // Place holder
127 : }
128 :
129 174071 : _ad_grad_phi = nullptr;
130 174071 : _ad_grad_phi_face = nullptr;
131 174071 : break;
132 : }
133 : }
134 522213 : _phi = &_phi_assembly_method(_assembly, _fe_type);
135 522213 : _phi_face = &_phi_face_assembly_method(_assembly, _fe_type);
136 522213 : _grad_phi = &_grad_phi_assembly_method(_assembly, _fe_type);
137 522213 : _grad_phi_face = &_grad_phi_face_assembly_method(_assembly, _fe_type);
138 522213 : }
139 :
140 : template <typename OutputType>
141 : void
142 696979845 : MooseVariableData<OutputType>::setGeometry(Moose::GeometryType gm_type)
143 : {
144 696979845 : switch (gm_type)
145 : {
146 662714234 : case Moose::Volume:
147 : {
148 662714234 : _current_qrule = _qrule;
149 662714234 : _current_phi = _phi;
150 662714234 : _current_grad_phi = _grad_phi;
151 662714234 : _current_second_phi = _second_phi;
152 662714234 : _current_curl_phi = _curl_phi;
153 662714234 : _current_div_phi = _div_phi;
154 662714234 : _current_ad_grad_phi = _ad_grad_phi;
155 662714234 : break;
156 : }
157 34265611 : case Moose::Face:
158 : {
159 34265611 : _current_qrule = _qrule_face;
160 34265611 : _current_phi = _phi_face;
161 34265611 : _current_grad_phi = _grad_phi_face;
162 34265611 : _current_second_phi = _second_phi_face;
163 34265611 : _current_curl_phi = _curl_phi_face;
164 34265611 : _current_div_phi = _div_phi_face;
165 34265611 : _current_ad_grad_phi = _ad_grad_phi_face;
166 34265611 : break;
167 : }
168 : }
169 696979845 : }
170 :
171 : template <typename OutputType>
172 : const typename MooseVariableData<OutputType>::FieldVariableValue &
173 15810 : MooseVariableData<OutputType>::uDot() const
174 : {
175 15810 : if (_sys.solutionUDot())
176 : {
177 15810 : _need_u_dot = true;
178 15810 : return _u_dot;
179 : }
180 : else
181 0 : mooseError("MooseVariableFE: Time derivative of solution (`u_dot`) is not stored. Please set "
182 : "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
183 : }
184 :
185 : template <typename OutputType>
186 : const typename MooseVariableData<OutputType>::FieldVariableValue &
187 202 : MooseVariableData<OutputType>::uDotDot() const
188 : {
189 202 : if (_sys.solutionUDotDot())
190 : {
191 202 : _need_u_dotdot = true;
192 202 : return _u_dotdot;
193 : }
194 : else
195 0 : mooseError("MooseVariableFE: Second time derivative of solution (`u_dotdot`) is not stored. "
196 : "Please set uDotDotRequested() to true in FEProblemBase before requesting "
197 : "`u_dotdot`.");
198 : }
199 :
200 : template <typename OutputType>
201 : const typename MooseVariableData<OutputType>::FieldVariableValue &
202 0 : MooseVariableData<OutputType>::uDotOld() const
203 : {
204 0 : if (_sys.solutionUDotOld())
205 : {
206 0 : _need_u_dot_old = true;
207 0 : return _u_dot_old;
208 : }
209 : else
210 0 : mooseError("MooseVariableFE: Old time derivative of solution (`u_dot_old`) is not stored. "
211 : "Please set uDotOldRequested() to true in FEProblemBase before requesting "
212 : "`u_dot_old`.");
213 : }
214 :
215 : template <typename OutputType>
216 : const typename MooseVariableData<OutputType>::FieldVariableValue &
217 0 : MooseVariableData<OutputType>::uDotDotOld() const
218 : {
219 0 : if (_sys.solutionUDotDotOld())
220 : {
221 0 : _need_u_dotdot_old = true;
222 0 : return _u_dotdot_old;
223 : }
224 : else
225 0 : mooseError("MooseVariableFE: Old second time derivative of solution (`u_dotdot_old`) is not "
226 : "stored. Please set uDotDotOldRequested() to true in FEProblemBase before "
227 : "requesting `u_dotdot_old`");
228 : }
229 :
230 : template <typename OutputType>
231 : const typename MooseVariableData<OutputType>::FieldVariableGradient &
232 36 : MooseVariableData<OutputType>::gradSlnDot() const
233 : {
234 36 : if (_sys.solutionUDot())
235 : {
236 36 : _need_grad_dot = true;
237 36 : return _grad_u_dot;
238 : }
239 : else
240 0 : mooseError("MooseVariableFE: Time derivative of solution (`u_dot`) is not stored. Please set "
241 : "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
242 : }
243 :
244 : template <typename OutputType>
245 : const typename MooseVariableData<OutputType>::FieldVariableGradient &
246 0 : MooseVariableData<OutputType>::gradSlnDotDot() const
247 : {
248 0 : if (_sys.solutionUDotDot())
249 : {
250 0 : _need_grad_dotdot = true;
251 0 : return _grad_u_dotdot;
252 : }
253 : else
254 0 : mooseError("MooseVariableFE: Second time derivative of solution (`u_dotdot`) is not stored. "
255 : "Please set uDotDotRequested() to true in FEProblemBase before requesting "
256 : "`u_dotdot`.");
257 : }
258 :
259 : template <typename OutputType>
260 : const typename MooseVariableData<OutputType>::FieldVariableSecond &
261 187 : MooseVariableData<OutputType>::secondSln(Moose::SolutionState state) const
262 : {
263 187 : secondPhi();
264 187 : secondPhiFace();
265 187 : switch (state)
266 : {
267 187 : case Moose::Current:
268 : {
269 187 : _need_second = true;
270 187 : return _second_u;
271 : }
272 :
273 0 : case Moose::Old:
274 : {
275 0 : _need_second_old = true;
276 0 : return _second_u_old;
277 : }
278 :
279 0 : case Moose::Older:
280 : {
281 0 : _need_second_older = true;
282 0 : return _second_u_older;
283 : }
284 :
285 0 : case Moose::PreviousNL:
286 : {
287 0 : _need_second_previous_nl = true;
288 0 : return _second_u_previous_nl;
289 : }
290 :
291 0 : default:
292 : // We should never get here but gcc requires that we have a default. See
293 : // htpps://stackoverflow.com/questions/18680378/after-defining-case-for-all-enum-values-compiler-still-says-control-reaches-e
294 0 : mooseError("Unknown SolutionState!");
295 : }
296 : }
297 :
298 : template <typename OutputType>
299 : const typename MooseVariableData<OutputType>::FieldVariableCurl &
300 158 : MooseVariableData<OutputType>::curlSln(Moose::SolutionState state) const
301 : {
302 158 : curlPhi();
303 158 : curlPhiFace();
304 158 : switch (state)
305 : {
306 158 : case Moose::Current:
307 : {
308 158 : _need_curl = true;
309 158 : return _curl_u;
310 : }
311 :
312 0 : case Moose::Old:
313 : {
314 0 : _need_curl_old = true;
315 0 : return _curl_u_old;
316 : }
317 :
318 0 : case Moose::Older:
319 : {
320 0 : _need_curl_older = true;
321 0 : return _curl_u_older;
322 : }
323 :
324 0 : default:
325 0 : mooseError("We don't currently support curl from the previous non-linear iteration");
326 : }
327 : }
328 :
329 : template <typename OutputType>
330 : const typename MooseVariableData<OutputType>::FieldVariableDivergence &
331 546 : MooseVariableData<OutputType>::divSln(Moose::SolutionState state) const
332 : {
333 546 : divPhi();
334 546 : divPhiFace();
335 546 : switch (state)
336 : {
337 546 : case Moose::Current:
338 : {
339 546 : _need_div = true;
340 546 : return _div_u;
341 : }
342 :
343 0 : case Moose::Old:
344 : {
345 0 : _need_div_old = true;
346 0 : return _div_u_old;
347 : }
348 :
349 0 : case Moose::Older:
350 : {
351 0 : _need_div_older = true;
352 0 : return _div_u_older;
353 : }
354 :
355 0 : default:
356 0 : mooseError("We don't currently support divergence from the previous non-linear iteration");
357 : }
358 : }
359 :
360 : template <typename OutputType>
361 : const typename MooseVariableData<OutputType>::FieldVariablePhiSecond &
362 24522 : MooseVariableData<OutputType>::secondPhi() const
363 : {
364 24522 : _second_phi = &_second_phi_assembly_method(_assembly, _fe_type);
365 24522 : return *_second_phi;
366 : }
367 :
368 : template <typename OutputType>
369 : const typename MooseVariableData<OutputType>::FieldVariablePhiSecond &
370 4448 : MooseVariableData<OutputType>::secondPhiFace() const
371 : {
372 4448 : _second_phi_face = &_second_phi_face_assembly_method(_assembly, _fe_type);
373 4448 : return *_second_phi_face;
374 : }
375 :
376 : template <typename OutputType>
377 : const typename MooseVariableData<OutputType>::FieldVariablePhiCurl &
378 57237 : MooseVariableData<OutputType>::curlPhi() const
379 : {
380 57237 : _curl_phi = &_curl_phi_assembly_method(_assembly, _fe_type);
381 57237 : return *_curl_phi;
382 : }
383 :
384 : template <typename OutputType>
385 : const typename MooseVariableData<OutputType>::FieldVariablePhiCurl &
386 207 : MooseVariableData<OutputType>::curlPhiFace() const
387 : {
388 207 : _curl_phi_face = &_curl_phi_face_assembly_method(_assembly, _fe_type);
389 207 : return *_curl_phi_face;
390 : }
391 :
392 : template <typename OutputType>
393 : const typename MooseVariableData<OutputType>::FieldVariablePhiDivergence &
394 521416 : MooseVariableData<OutputType>::divPhi() const
395 : {
396 521416 : _div_phi = &_div_phi_assembly_method(_assembly, _fe_type);
397 521416 : return *_div_phi;
398 : }
399 :
400 : template <typename OutputType>
401 : const typename MooseVariableData<OutputType>::FieldVariablePhiDivergence &
402 546 : MooseVariableData<OutputType>::divPhiFace() const
403 : {
404 546 : _div_phi_face = &_div_phi_face_assembly_method(_assembly, _fe_type);
405 546 : return *_div_phi_face;
406 : }
407 :
408 : template <typename OutputType>
409 : template <bool constant_monomial,
410 : typename DestinationType,
411 : typename ShapeType,
412 : typename DofValuesType>
413 : void
414 1378930204 : MooseVariableData<OutputType>::fill(DestinationType & dest,
415 : const ShapeType & phi,
416 : const DofValuesType & dof_values,
417 : const unsigned int nqp,
418 : const std::size_t num_shapes)
419 : {
420 : if constexpr (constant_monomial)
421 160958727 : libmesh_ignore(num_shapes);
422 :
423 : // Deduce OutputType
424 1378930204 : constexpr bool is_real = std::is_same_v<OutputType, Real>;
425 1378930204 : constexpr bool is_real_vector = std::is_same_v<OutputType, RealVectorValue>;
426 1378930204 : constexpr bool is_eigen = std::is_same_v<OutputType, RealEigenVector>;
427 : static_assert(is_real || is_real_vector || is_eigen, "Unsupported type");
428 :
429 : // this is only used in the RealEigenVector case to get this->_count
430 : if constexpr (!is_eigen)
431 1370145650 : libmesh_ignore(this);
432 :
433 : // Deduce type of value within dest MooseArray
434 : using dest_array_type = typename std::remove_reference_t<decltype(dest)>::value_type;
435 1378930204 : constexpr bool is_value =
436 : std::is_same_v<dest_array_type, OutputType> ||
437 : std::is_same_v<dest_array_type, typename Moose::ADType<OutputType>::type>;
438 1378930204 : constexpr bool is_gradient =
439 : std::is_same_v<dest_array_type, OutputGradient> ||
440 : std::is_same_v<dest_array_type, typename Moose::ADType<OutputGradient>::type>;
441 1378930204 : constexpr bool is_second =
442 : std::is_same_v<dest_array_type, OutputSecond> ||
443 : std::is_same_v<dest_array_type, typename Moose::ADType<OutputSecond>::type>;
444 1378930204 : constexpr bool is_divergence =
445 : std::is_same_v<dest_array_type, OutputDivergence> ||
446 : std::is_same_v<dest_array_type, typename Moose::ADType<OutputDivergence>::type>;
447 : static_assert(is_value || is_gradient || is_second || is_divergence,
448 : "Unsupported destination array type");
449 :
450 : // Sets a value to zero at a quadrature point
451 12666852444 : const auto set_zero = [this, &dest](const auto qp)
452 : {
453 : if constexpr (!is_eigen)
454 5603533126 : libmesh_ignore(this);
455 :
456 : if constexpr (is_real || is_real_vector)
457 5603533126 : dest[qp] = 0;
458 : else if constexpr (is_eigen)
459 : {
460 : if constexpr (is_value)
461 28244734 : dest[qp].setZero(this->_count);
462 : else if constexpr (is_gradient)
463 12183260 : dest[qp].setZero(this->_count, LIBMESH_DIM);
464 : else if constexpr (is_second)
465 0 : dest[qp].setZero(this->_count, LIBMESH_DIM * LIBMESH_DIM);
466 : else
467 : static_assert(Moose::always_false<OutputType, dest_array_type>, "Unsupported type");
468 : }
469 : else
470 : static_assert(Moose::always_false<OutputType, dest_array_type>, "Unsupported type");
471 : };
472 :
473 : // Accumulates a value
474 52461597413 : const auto accumulate = [&dest, &phi, &dof_values](const auto i, const auto qp)
475 : {
476 : if constexpr (is_real || is_real_vector || (is_eigen && is_value))
477 : {
478 : if constexpr (is_value || is_divergence)
479 16021101980 : dest[qp] += phi[i][qp] * dof_values[i];
480 : else if constexpr (is_gradient || is_second)
481 9486784721 : dest[qp].add_scaled(phi[i][qp], dof_values[i]);
482 : else
483 : static_assert(Moose::always_false<OutputType, dest_array_type>, "Unsupported type");
484 : }
485 : else if constexpr (is_eigen)
486 : {
487 : if constexpr (is_gradient)
488 : {
489 267575228 : for (const auto d : make_range(Moose::dim))
490 200681421 : dest[qp].col(d) += phi[i][qp](d) * dof_values[i];
491 : }
492 : else if constexpr (is_second)
493 : {
494 0 : for (unsigned int d = 0, d1 = 0; d1 < LIBMESH_DIM; ++d1)
495 0 : for (const auto d2 : make_range(Moose::dim))
496 0 : dest[qp].col(d++) += phi[i][qp](d1, d2) * dof_values[i];
497 : }
498 : else
499 : static_assert(Moose::always_false<OutputType, dest_array_type>, "Unsupported type");
500 : }
501 : else
502 : static_assert(Moose::always_false<OutputType, dest_array_type>, "Unsupported type");
503 : };
504 :
505 1378930204 : dest.resize(nqp);
506 :
507 : // Monomial case, accumulate dest[0] and set dest[>0] to dest[0]
508 : if constexpr (constant_monomial)
509 : {
510 : mooseAssert(num_shapes == 1, "Should have only one shape function for a constant monomial");
511 160958727 : set_zero(0);
512 160958727 : accumulate(0, 0);
513 728898509 : for (unsigned int qp = 1; qp < nqp; ++qp)
514 567939782 : dest[qp] = dest[0];
515 : }
516 : // Non constant monomial case
517 : else
518 : {
519 6700973870 : for (const auto qp : make_range(nqp))
520 5483002393 : set_zero(qp);
521 6303654117 : for (const auto i : make_range(num_shapes))
522 30499504421 : for (const auto qp : make_range(nqp))
523 25413821781 : accumulate(i, qp);
524 : }
525 1378930204 : }
526 :
527 : template <typename OutputType>
528 : template <bool constant_monomial>
529 : void
530 696338852 : MooseVariableData<OutputType>::computeValuesInternal()
531 : {
532 696338852 : const auto num_dofs = _dof_indices.size();
533 696338852 : const auto num_shapes = num_dofs / _count;
534 :
535 696338852 : if (num_dofs > 0)
536 603420182 : fetchDofValues();
537 :
538 696338852 : const bool is_transient = _subproblem.isTransient();
539 696338852 : const auto nqp = _current_qrule->n_points();
540 : const auto & active_coupleable_matrix_tags =
541 696338852 : _subproblem.getActiveFEVariableCoupleableMatrixTags(_tid);
542 :
543 : // Map grad_phi using Eigen so that we can perform array operations easier
544 : if constexpr (std::is_same_v<OutputType, RealEigenVector>)
545 : {
546 4226956 : if (_qrule == _current_qrule)
547 : {
548 4019062 : _mapped_grad_phi.resize(num_shapes);
549 18881751 : for (const auto i : make_range(num_shapes))
550 : {
551 14862689 : _mapped_grad_phi[i].resize(nqp, Eigen::Map<RealDIMValue>(nullptr));
552 97256488 : for (const auto qp : make_range(nqp))
553 : // Note: this does NOT do any allocation. It is "reconstructing" the object in place
554 164787598 : new (&_mapped_grad_phi[i][qp])
555 82393799 : Eigen::Map<RealDIMValue>(const_cast<Real *>(&(*_current_grad_phi)[i][qp](0)));
556 : }
557 : }
558 : else
559 : {
560 207894 : _mapped_grad_phi_face.resize(num_shapes);
561 820342 : for (const auto i : make_range(num_shapes))
562 : {
563 612448 : _mapped_grad_phi_face[i].resize(nqp, Eigen::Map<RealDIMValue>(nullptr));
564 2121984 : for (const auto qp : make_range(nqp))
565 : // Note: this does NOT do any allocation. It is "reconstructing" the object in place
566 3019072 : new (&_mapped_grad_phi_face[i][qp])
567 1509536 : Eigen::Map<RealDIMValue>(const_cast<Real *>(&(*_current_grad_phi)[i][qp](0)));
568 : }
569 : }
570 : }
571 :
572 : mooseAssert(
573 : !(_need_second || _need_second_old || _need_second_older || _need_second_previous_nl) ||
574 : _current_second_phi,
575 : "We're requiring a second calculation but have not set a second shape function!");
576 : mooseAssert(!(_need_curl || _need_curl_old) || _current_curl_phi,
577 : "We're requiring a curl calculation but have not set a curl shape function!");
578 : mooseAssert(!(_need_div || _need_div_old) || _current_div_phi,
579 : "We're requiring a divergence calculation but have not set a div shape function!");
580 :
581 : // Curl
582 696338852 : if (_need_curl)
583 71006 : fill<constant_monomial>(
584 71006 : _curl_u, *_current_curl_phi, _vector_tags_dof_u[_solution_tag], nqp, num_shapes);
585 696338852 : if (is_transient && _need_curl_old)
586 0 : fill<constant_monomial>(
587 0 : _curl_u_old, *_current_curl_phi, _vector_tags_dof_u[_old_solution_tag], nqp, num_shapes);
588 :
589 : // Div
590 696338852 : if (_need_div)
591 426624 : fill<constant_monomial>(
592 426624 : _div_u, *_current_div_phi, _vector_tags_dof_u[_solution_tag], nqp, num_shapes);
593 696338852 : if (is_transient && _need_div_old)
594 0 : fill<constant_monomial>(
595 0 : _div_u_old, *_current_div_phi, _vector_tags_dof_u[_old_solution_tag], nqp, num_shapes);
596 :
597 : // Second
598 696338852 : if (_need_second)
599 80167 : fill<constant_monomial>(
600 80167 : _second_u, *_current_second_phi, _vector_tags_dof_u[_solution_tag], nqp, num_shapes);
601 696338852 : if (_need_second_previous_nl)
602 0 : fill<constant_monomial>(_second_u_previous_nl,
603 0 : *_current_second_phi,
604 0 : _vector_tags_dof_u[_previous_nl_solution_tag],
605 : nqp,
606 : num_shapes);
607 :
608 : // Vector tags
609 1399232438 : for (auto tag : _required_vector_tags)
610 : {
611 702893586 : if (_need_vector_tag_u[tag] && _sys.hasVector(tag))
612 : {
613 : mooseAssert(_sys.getVector(tag).closed(), "Vector should be closed");
614 700361386 : fill<constant_monomial>(
615 700361386 : _vector_tag_u[tag], *_current_phi, _vector_tags_dof_u[tag], nqp, num_shapes);
616 : }
617 702893586 : if (_need_vector_tag_grad[tag] && _sys.hasVector(tag))
618 : {
619 : mooseAssert(_sys.getVector(tag).closed(), "Vector should be closed");
620 398456747 : fill<constant_monomial>(
621 398456747 : _vector_tag_grad[tag], *_current_grad_phi, _vector_tags_dof_u[tag], nqp, num_shapes);
622 : }
623 : }
624 :
625 : // Matrix tags
626 696339236 : for (auto tag : active_coupleable_matrix_tags)
627 384 : if (_need_matrix_tag_u[tag])
628 128 : fill<constant_monomial>(
629 128 : _matrix_tag_u[tag], *_current_phi, _matrix_tags_dof_u[tag], nqp, num_shapes);
630 :
631 : // Derivatives and old values
632 696338852 : if (is_transient)
633 : {
634 529073097 : if (_need_second_old)
635 0 : fill<constant_monomial>(_second_u_old,
636 0 : *_current_second_phi,
637 0 : _vector_tags_dof_u[_old_solution_tag],
638 : nqp,
639 : num_shapes);
640 529073097 : if (_need_second_older)
641 0 : fill<constant_monomial>(_second_u_older,
642 0 : *_current_second_phi,
643 0 : _vector_tags_dof_u[_older_solution_tag],
644 : nqp,
645 : num_shapes);
646 529073097 : if (_need_u_dot)
647 238972611 : fill<constant_monomial>(_u_dot, *_current_phi, _dof_values_dot, nqp, num_shapes);
648 529073097 : if (_need_u_dotdot)
649 6378 : fill<constant_monomial>(_u_dotdot, *_current_phi, _dof_values_dotdot, nqp, num_shapes);
650 529073097 : if (_need_u_dot_old)
651 0 : fill<constant_monomial>(_u_dot_old, *_current_phi, _dof_values_dot_old, nqp, num_shapes);
652 529073097 : if (_need_u_dotdot_old)
653 0 : fill<constant_monomial>(
654 0 : _u_dotdot_old, *_current_phi, _dof_values_dotdot_old, nqp, num_shapes);
655 :
656 529073097 : if (_need_du_dot_du)
657 : {
658 239094856 : _du_dot_du.resize(nqp);
659 1280824765 : for (const auto i : make_range(num_shapes))
660 6028656765 : for (const auto qp : make_range(nqp))
661 4986926856 : _du_dot_du[qp] = _dof_du_dot_du[i];
662 : }
663 529073097 : if (_need_du_dotdot_du)
664 : {
665 5198 : _du_dotdot_du.resize(nqp);
666 43996 : for (const auto i : make_range(num_shapes))
667 192796 : for (const auto qp : make_range(nqp))
668 153998 : _du_dotdot_du[qp] = _dof_du_dotdot_du[i];
669 : }
670 :
671 529073097 : if (_need_grad_dot)
672 125502 : fill<constant_monomial>(_grad_u_dot, *_current_grad_phi, _dof_values_dot, nqp, num_shapes);
673 529073097 : if (_need_grad_dotdot)
674 0 : fill<constant_monomial>(
675 0 : _grad_u_dotdot, *_current_grad_phi, _dof_values_dotdot, nqp, num_shapes);
676 : }
677 :
678 696338852 : if (_need_ad)
679 20471932 : computeAD<constant_monomial>(num_dofs, nqp);
680 696338852 : }
681 :
682 : template <typename OutputType>
683 : void
684 545089169 : MooseVariableData<OutputType>::computeValues()
685 : {
686 545089169 : computeValuesInternal</* constant_monomial = */ false>();
687 545089169 : }
688 :
689 : template <typename OutputType>
690 : void
691 152027104 : MooseVariableData<OutputType>::computeConstantMonomialValues()
692 : {
693 152027104 : if (_dof_indices.size() == 0)
694 640993 : return;
695 :
696 : // Monomial optimizations are not appropriate after p-refinement
697 151386111 : if (_elem->p_level())
698 136428 : computeValues();
699 : else
700 151249683 : computeValuesInternal</* constant_monomial = */ true>();
701 : }
702 :
703 : template <typename OutputType>
704 : void
705 23466328 : MooseVariableData<OutputType>::fetchADDofValues()
706 : {
707 23466328 : const auto num_dofs = _dof_indices.size();
708 :
709 23466328 : const bool do_derivatives = Moose::doDerivatives(_subproblem, _sys);
710 :
711 23466328 : _ad_dof_values.resize(num_dofs);
712 110168890 : for (const auto i : make_range(num_dofs))
713 86702562 : _ad_dof_values[i] = _vector_tags_dof_u[_solution_tag][i];
714 : // NOTE! You have to do this AFTER setting the value!
715 23466328 : if (do_derivatives)
716 18130212 : for (const auto i : make_range(num_dofs))
717 13988217 : Moose::derivInsert(_ad_dof_values[i].derivatives(), _dof_indices[i], 1.);
718 :
719 23466328 : const bool is_transient = _subproblem.isTransient();
720 23466328 : if (is_transient && _need_ad_u_dot)
721 : {
722 2740880 : _ad_dofs_dot.resize(num_dofs);
723 2740880 : if (_need_ad_u_dotdot)
724 1252 : _ad_dofs_dotdot.resize(num_dofs);
725 :
726 2740880 : if (_time_integrator)
727 : {
728 2740880 : if (_time_integrator->dt())
729 : {
730 12365778 : for (const auto i : make_range(num_dofs))
731 9644250 : _ad_dofs_dot[i] = _ad_dof_values[i];
732 12365778 : for (const auto i : make_range(num_dofs))
733 19286502 : _time_integrator->computeADTimeDerivatives(_ad_dofs_dot[i],
734 9644250 : _dof_indices[i],
735 9644250 : _need_ad_u_dotdot ? _ad_dofs_dotdot[i]
736 : : _ad_real_dummy);
737 : }
738 : else
739 : // Executing something with a time derivative at initial should not put a NaN
740 95724 : for (const auto i : make_range(num_dofs))
741 : {
742 76372 : _ad_dofs_dot[i] = 0.;
743 76372 : if (_need_ad_u_dotdot)
744 64 : _ad_dofs_dotdot[i] = 0;
745 : }
746 : }
747 : // We are too early in the setup to have a time integrator, so we are not really using the
748 : // AD-derivatives. We set the AD value of the derivatives to the nonAD value
749 : else
750 0 : for (const auto i : make_range(num_dofs))
751 : {
752 0 : _ad_dofs_dot[i] = _dof_values_dot[i];
753 0 : if (_need_ad_u_dotdot)
754 0 : _ad_dofs_dotdot[i] = _dof_values_dotdot[i];
755 : }
756 : }
757 23466328 : }
758 :
759 : template <>
760 : void
761 38798 : MooseVariableData<RealEigenVector>::fetchADDofValues()
762 : {
763 38798 : const auto num_dofs = _dof_indices.size();
764 :
765 38798 : const bool do_derivatives = Moose::doDerivatives(_subproblem, _sys);
766 38798 : const auto n_test = num_dofs / _count;
767 : mooseAssert(num_dofs == _count * n_test,
768 : "Our assertions around number of dofs, test functions, and count are incorrect");
769 :
770 38798 : _ad_dof_values.resize(n_test);
771 : // Test is outer, count is inner
772 147032 : for (const auto i : make_range(n_test))
773 : {
774 108234 : _ad_dof_values[i].resize(_count);
775 324702 : for (const auto j : make_range(_count))
776 : {
777 216468 : auto & dual_number = _ad_dof_values[i](j);
778 216468 : const auto global_dof_index = _dof_indices[j * n_test + i];
779 216468 : dual_number = (*_sys.currentSolution())(global_dof_index);
780 : // NOTE! You have to do this AFTER setting the value!
781 216468 : if (do_derivatives)
782 16172 : Moose::derivInsert(dual_number.derivatives(), global_dof_index, 1.);
783 : }
784 : }
785 38798 : }
786 :
787 : template <typename OutputType>
788 : template <bool constant_monomial>
789 : void
790 20471932 : MooseVariableData<OutputType>::computeAD(const unsigned int num_dofs, const unsigned int nqp)
791 : {
792 20471932 : fetchADDofValues();
793 20471932 : const auto n_test = num_dofs / _count;
794 :
795 : // Values
796 20471932 : if (_need_ad_u)
797 19150413 : fill<constant_monomial>(_ad_u, *_current_phi, _ad_dof_values, nqp, n_test);
798 : // Grad
799 20471932 : if (_need_ad_grad_u)
800 : {
801 : // The latter check here is for handling the fact that we have not yet implemented
802 : // calculation of ad_grad_phi for neighbor and neighbor-face, so if we are in that
803 : // situation we need to default to using the non-ad grad_phi
804 16596918 : if (_displaced && _current_ad_grad_phi)
805 472706 : fill<constant_monomial>(_ad_grad_u, *_current_ad_grad_phi, _ad_dof_values, nqp, n_test);
806 : else
807 16124212 : fill<constant_monomial>(_ad_grad_u, *_current_grad_phi, _ad_dof_values, nqp, n_test);
808 : }
809 : // Second
810 : if constexpr (std::is_same_v<OutputType, Real>)
811 17279736 : if (_need_ad_second_u)
812 0 : fill<constant_monomial>(_ad_second_u, *_current_second_phi, _ad_dof_values, nqp, n_test);
813 : // Curl
814 20471932 : if (_need_ad_curl_u)
815 2452600 : fill<constant_monomial>(_ad_curl_u, *_current_curl_phi, _ad_dof_values, nqp, n_test);
816 :
817 20471932 : const bool is_transient = _subproblem.isTransient();
818 20471932 : if (is_transient)
819 : {
820 10824251 : if (_need_ad_u_dot)
821 : {
822 2229324 : if (_time_integrator)
823 2229324 : fill<constant_monomial>(_ad_u_dot, *_current_phi, _ad_dofs_dot, nqp, n_test);
824 : // We are too early in the setup to have a time integrator, so we are not really using the
825 : // AD-derivatives. We set the AD value of the derivatives to the nonAD value
826 : else
827 : {
828 0 : _ad_u_dot.resize(nqp);
829 0 : for (const auto qp : make_range(nqp))
830 0 : _ad_u_dot[qp] = _u_dot[qp];
831 : }
832 : }
833 :
834 10824251 : if (_need_ad_u_dotdot)
835 : {
836 400 : if (_time_integrator)
837 400 : fill<constant_monomial>(_ad_u_dotdot, *_current_phi, _ad_dofs_dotdot, nqp, n_test);
838 : else
839 : {
840 0 : _ad_u_dotdot.resize(nqp);
841 0 : for (const auto qp : make_range(nqp))
842 0 : _ad_u_dotdot[qp] = _u_dotdot[qp];
843 : }
844 : }
845 :
846 10824251 : if (_need_ad_grad_u_dot)
847 : {
848 0 : if (_time_integrator)
849 : {
850 : // The latter check here is for handling the fact that we have not yet implemented
851 : // calculation of ad_grad_phi for neighbor and neighbor-face, so if we are in that
852 : // situation we need to default to using the non-ad grad_phi
853 0 : if (_displaced && _current_ad_grad_phi)
854 0 : fill<constant_monomial>(_ad_grad_u_dot, *_current_ad_grad_phi, _ad_dofs_dot, nqp, n_test);
855 : else
856 0 : fill<constant_monomial>(_ad_grad_u_dot, *_current_grad_phi, _ad_dofs_dot, nqp, n_test);
857 : }
858 : else
859 : {
860 0 : _ad_grad_u_dot.resize(nqp);
861 0 : for (const auto qp : make_range(nqp))
862 0 : _ad_grad_u_dot[qp] = _grad_u_dot[qp];
863 : }
864 : }
865 : }
866 20471932 : }
867 :
868 : template <typename OutputType>
869 : void
870 8421231 : MooseVariableData<OutputType>::setDofValue(const DofValue & value, unsigned int index)
871 : {
872 8421231 : auto & dof_values = _vector_tags_dof_u[_solution_tag];
873 8421231 : dof_values[index] = value;
874 8421231 : _has_dof_values = true;
875 :
876 8421231 : auto & u = _vector_tag_u[_solution_tag];
877 8421231 : const auto nqps = u.size();
878 8421231 : const auto ndofs = dof_values.size();
879 42752917 : for (const auto qp : make_range(nqps))
880 34331686 : u[qp] *= 0.;
881 42752917 : for (const auto qp : make_range(nqps))
882 292452170 : for (const auto i : make_range(ndofs))
883 258120484 : u[qp] += (*_phi)[i][qp] * dof_values[i];
884 8421231 : }
885 :
886 : template <typename OutputType>
887 : void
888 582887 : MooseVariableData<OutputType>::setDofValues(const DenseVector<DofValue> & values)
889 : {
890 582887 : auto & dof_values = _vector_tags_dof_u[_solution_tag];
891 3453696 : for (unsigned int i = 0; i < values.size(); i++)
892 2870809 : dof_values[i] = values(i);
893 :
894 582887 : _has_dof_values = true;
895 :
896 582887 : auto & u = _vector_tag_u[_solution_tag];
897 582887 : const auto nqps = u.size();
898 582887 : const auto ndofs = dof_values.size();
899 5007718 : for (const auto qp : make_range(nqps))
900 4424831 : u[qp] *= 0.;
901 5007718 : for (const auto qp : make_range(nqps))
902 32308741 : for (const auto i : make_range(ndofs))
903 27883910 : u[qp] += (*_phi)[i][qp] * dof_values[i];
904 582887 : }
905 :
906 : template <typename OutputType>
907 : void
908 55397720 : MooseVariableData<OutputType>::insertNodalValue(NumericVector<Number> & residual,
909 : const DofValue & v)
910 : {
911 55397720 : residual.set(_nodal_dof_index, v);
912 55397720 : }
913 :
914 : template <>
915 : void
916 293942 : MooseVariableData<RealEigenVector>::insertNodalValue(NumericVector<Number> & residual,
917 : const RealEigenVector & v)
918 : {
919 1039426 : for (const auto j : make_range(_count))
920 745484 : residual.set(_nodal_dof_index + j, v(j));
921 293942 : }
922 :
923 : template <typename OutputType>
924 : typename MooseVariableData<OutputType>::DofValue
925 110099 : MooseVariableData<OutputType>::getNodalValue(const Node & node, Moose::SolutionState state) const
926 : {
927 : mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)), "Node is not Semilocal");
928 :
929 : // Make sure that the node has DOFs
930 : /* Note, this is a reproduction of an assert within libMesh::Node::dof_number, this is done to
931 : * produce a better error (see misc/check_error.node_value_off_block) */
932 : mooseAssert(node.n_dofs(_sys.number(), _var_num) > 0,
933 : "Node " << node.id() << " does not contain any dofs for the "
934 : << _sys.system().variable_name(_var_num) << " variable");
935 :
936 110099 : dof_id_type dof = node.dof_number(_sys.number(), _var_num, 0);
937 :
938 110099 : switch (state)
939 : {
940 1199 : case Moose::Current:
941 1199 : return (*_sys.currentSolution())(dof);
942 :
943 108900 : case Moose::Old:
944 108900 : return _sys.solutionOld()(dof);
945 :
946 0 : case Moose::Older:
947 0 : return _sys.solutionOlder()(dof);
948 :
949 0 : default:
950 0 : mooseError("PreviousNL not currently supported for getNodalValue");
951 : }
952 : }
953 :
954 : template <>
955 : RealEigenVector
956 0 : MooseVariableData<RealEigenVector>::getNodalValue(const Node & node,
957 : Moose::SolutionState state) const
958 : {
959 : mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)), "Node is not Semilocal");
960 :
961 : // Make sure that the node has DOFs
962 : /* Note, this is a reproduction of an assert within libMesh::Node::dof_number, this is done to
963 : * produce a better error (see misc/check_error.node_value_off_block) */
964 : mooseAssert(node.n_dofs(_sys.number(), _var_num) > 0,
965 : "Node " << node.id() << " does not contain any dofs for the "
966 : << _sys.system().variable_name(_var_num) << " variable");
967 :
968 0 : dof_id_type dof = node.dof_number(_sys.number(), _var_num, 0);
969 :
970 0 : RealEigenVector v(_count);
971 0 : switch (state)
972 : {
973 0 : case Moose::Current:
974 0 : for (unsigned int i = 0; i < _count; ++i)
975 0 : v(i) = (*_sys.currentSolution())(dof++);
976 0 : break;
977 :
978 0 : case Moose::Old:
979 0 : for (unsigned int i = 0; i < _count; ++i)
980 0 : v(i) = _sys.solutionOld()(dof++);
981 0 : break;
982 :
983 0 : case Moose::Older:
984 0 : for (unsigned int i = 0; i < _count; ++i)
985 0 : v(i) = _sys.solutionOlder()(dof++);
986 0 : break;
987 :
988 0 : default:
989 0 : mooseError("PreviousNL not currently supported for getNodalValue");
990 : }
991 0 : return v;
992 0 : }
993 :
994 : template <typename OutputType>
995 : typename MooseVariableData<OutputType>::DofValue
996 70787 : MooseVariableData<OutputType>::getElementalValue(const Elem * elem,
997 : const Moose::SolutionState state,
998 : const unsigned int idx) const
999 : {
1000 70787 : static thread_local std::vector<dof_id_type> dof_indices;
1001 70787 : _dof_map.dof_indices(elem, dof_indices, _var_num);
1002 :
1003 70787 : switch (state)
1004 : {
1005 69803 : case Moose::Current:
1006 69803 : return (*_sys.currentSolution())(dof_indices[idx]);
1007 :
1008 492 : case Moose::Old:
1009 492 : return _sys.solutionOld()(dof_indices[idx]);
1010 :
1011 492 : case Moose::Older:
1012 492 : return _sys.solutionOlder()(dof_indices[idx]);
1013 :
1014 0 : default:
1015 0 : mooseError("PreviousNL not currently supported for getElementalValue");
1016 : }
1017 : }
1018 :
1019 : template <>
1020 : RealEigenVector
1021 0 : MooseVariableData<RealEigenVector>::getElementalValue(const Elem * elem,
1022 : const Moose::SolutionState state,
1023 : const unsigned int idx) const
1024 : {
1025 0 : mooseDeprecated(
1026 : "getElementalValue has a really bad API name. It is retrieving a value from the solution "
1027 : "vector for a particular dof index. Generally speaking it has absolutely no equivalence to "
1028 : "an 'elemental' value, which most people would consider to be something like an element "
1029 : "average value");
1030 :
1031 0 : static thread_local std::vector<dof_id_type> dof_indices;
1032 0 : _dof_map.array_dof_indices(elem, dof_indices, _var_num);
1033 : mooseAssert(dof_indices.size() % _count == 0,
1034 : "The number of array dof indices should divide cleanly by the variable count");
1035 0 : const auto num_shapes = dof_indices.size() / _count;
1036 :
1037 0 : RealEigenVector v(_count);
1038 :
1039 0 : switch (state)
1040 : {
1041 0 : case Moose::Current:
1042 0 : for (unsigned int i = 0; i < _count; ++i)
1043 0 : v(i) = (*_sys.currentSolution())(dof_indices[i * num_shapes + idx]);
1044 0 : break;
1045 :
1046 0 : case Moose::Old:
1047 0 : for (unsigned int i = 0; i < _count; ++i)
1048 0 : v(i) = _sys.solutionOld()(dof_indices[i * num_shapes + idx]);
1049 0 : break;
1050 :
1051 0 : case Moose::Older:
1052 0 : for (unsigned int i = 0; i < _count; ++i)
1053 0 : v(i) = _sys.solutionOlder()(dof_indices[i * num_shapes + idx]);
1054 0 : break;
1055 :
1056 0 : default:
1057 0 : mooseError("PreviousNL not currently supported for getElementalValue");
1058 : }
1059 0 : return v;
1060 0 : }
1061 :
1062 : template <typename OutputType>
1063 : void
1064 18960 : MooseVariableData<OutputType>::getDofIndices(const Elem * elem,
1065 : std::vector<dof_id_type> & dof_indices) const
1066 : {
1067 : if constexpr (std::is_same<OutputType, RealEigenVector>::value)
1068 1928 : _dof_map.array_dof_indices(elem, dof_indices, _var_num);
1069 : else
1070 17032 : _dof_map.dof_indices(elem, dof_indices, _var_num);
1071 18960 : }
1072 :
1073 : template <typename OutputType>
1074 : void
1075 2720 : MooseVariableData<OutputType>::addSolution(NumericVector<Number> & sol,
1076 : const DenseVector<Number> & v) const
1077 : {
1078 2720 : sol.add_vector(v, _dof_indices);
1079 2720 : }
1080 :
1081 : template <typename OutputType>
1082 : const typename MooseVariableData<OutputType>::DofValues &
1083 348 : MooseVariableData<OutputType>::dofValuesDot() const
1084 : {
1085 348 : if (_sys.solutionUDot())
1086 : {
1087 348 : _need_dof_values_dot = true;
1088 348 : return _dof_values_dot;
1089 : }
1090 : else
1091 0 : mooseError("MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set "
1092 : "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1093 : }
1094 :
1095 : template <typename OutputType>
1096 : const typename MooseVariableData<OutputType>::DofValues &
1097 3 : MooseVariableData<OutputType>::dofValuesDotDot() const
1098 : {
1099 3 : if (_sys.solutionUDotDot())
1100 : {
1101 3 : _need_dof_values_dotdot = true;
1102 3 : return _dof_values_dotdot;
1103 : }
1104 : else
1105 0 : mooseError("MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. "
1106 : "Please set uDotDotRequested() to true in FEProblemBase before requesting "
1107 : "`u_dotdot`.");
1108 : }
1109 :
1110 : template <typename OutputType>
1111 : const typename MooseVariableData<OutputType>::DofValues &
1112 0 : MooseVariableData<OutputType>::dofValuesDotOld() const
1113 : {
1114 0 : if (_sys.solutionUDotOld())
1115 : {
1116 0 : _need_dof_values_dot_old = true;
1117 0 : return _dof_values_dot_old;
1118 : }
1119 : else
1120 0 : mooseError("MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. "
1121 : "Please set uDotOldRequested() to true in FEProblemBase before requesting "
1122 : "`u_dot_old`.");
1123 : }
1124 :
1125 : template <typename OutputType>
1126 : const typename MooseVariableData<OutputType>::DofValues &
1127 0 : MooseVariableData<OutputType>::dofValuesDotDotOld() const
1128 : {
1129 0 : if (_sys.solutionUDotDotOld())
1130 : {
1131 0 : _need_dof_values_dotdot_old = true;
1132 0 : return _dof_values_dotdot_old;
1133 : }
1134 : else
1135 0 : mooseError("MooseVariableData: Old second time derivative of solution (`u_dotdot_old`) is not "
1136 : "stored. Please set uDotDotOldRequested() to true in FEProblemBase before "
1137 : "requesting `u_dotdot_old`.");
1138 : }
1139 :
1140 : template <typename OutputType>
1141 : const MooseArray<Number> &
1142 165 : MooseVariableData<OutputType>::dofValuesDuDotDu() const
1143 : {
1144 165 : _need_dof_du_dot_du = true;
1145 165 : return _dof_du_dot_du;
1146 : }
1147 :
1148 : template <typename OutputType>
1149 : const MooseArray<Number> &
1150 0 : MooseVariableData<OutputType>::dofValuesDuDotDotDu() const
1151 : {
1152 0 : _need_dof_du_dotdot_du = true;
1153 0 : return _dof_du_dotdot_du;
1154 : }
1155 :
1156 : template <typename OutputType>
1157 : void
1158 1563 : MooseVariableData<OutputType>::computeIncrementAtQps(const NumericVector<Number> & increment_vec)
1159 : {
1160 1563 : unsigned int nqp = _qrule->n_points();
1161 :
1162 1563 : _increment.resize(nqp);
1163 : // Compute the increment at each quadrature point
1164 1563 : unsigned int num_dofs = _dof_indices.size();
1165 13082 : for (const auto qp : make_range(nqp))
1166 : {
1167 11519 : _increment[qp] = 0.;
1168 112278 : for (const auto i : make_range(num_dofs))
1169 100759 : _increment[qp] += (*_phi)[i][qp] * increment_vec(_dof_indices[i]);
1170 : }
1171 1563 : }
1172 :
1173 : template <>
1174 : void
1175 0 : MooseVariableData<RealEigenVector>::computeIncrementAtQps(
1176 : const NumericVector<Number> & increment_vec)
1177 : {
1178 0 : unsigned int nqp = _qrule->n_points();
1179 :
1180 0 : _increment.resize(nqp);
1181 : // Compute the increment at each quadrature point
1182 0 : unsigned int num_dofs = _dof_indices.size();
1183 0 : if (isNodal())
1184 : {
1185 0 : for (const auto qp : make_range(nqp))
1186 : {
1187 0 : for (const auto i : make_range(num_dofs))
1188 0 : for (const auto j : make_range(_count))
1189 0 : _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + j);
1190 : }
1191 : }
1192 : else
1193 : {
1194 0 : for (const auto qp : make_range(nqp))
1195 : {
1196 0 : unsigned int n = 0;
1197 0 : for (const auto j : make_range(_count))
1198 0 : for (const auto i : make_range(num_dofs))
1199 : {
1200 0 : _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + n);
1201 0 : n += num_dofs;
1202 : }
1203 : }
1204 : }
1205 0 : }
1206 :
1207 : template <typename OutputType>
1208 : void
1209 7525 : MooseVariableData<OutputType>::computeIncrementAtNode(const NumericVector<Number> & increment_vec)
1210 : {
1211 7525 : if (!isNodal())
1212 0 : mooseError("computeIncrementAtNode can only be called for nodal variables");
1213 :
1214 7525 : _increment.resize(1);
1215 :
1216 : // Compute the increment for the current DOF
1217 7525 : _increment[0] = increment_vec(_dof_indices[0]);
1218 7525 : }
1219 :
1220 : template <>
1221 : void
1222 0 : MooseVariableData<RealEigenVector>::computeIncrementAtNode(
1223 : const NumericVector<Number> & increment_vec)
1224 : {
1225 0 : if (!isNodal())
1226 0 : mooseError("computeIncrementAtNode can only be called for nodal variables");
1227 :
1228 0 : _increment.resize(1);
1229 :
1230 : // Compute the increment for the current DOF
1231 0 : if (isNodal())
1232 0 : for (unsigned int j = 0; j < _count; j++)
1233 0 : _increment[0](j) = increment_vec(_dof_indices[0] + j);
1234 : else
1235 : {
1236 0 : unsigned int n = 0;
1237 0 : const auto n_dof_indices = _dof_indices.size();
1238 0 : for (const auto j : make_range(_count))
1239 : {
1240 0 : _increment[0](j) = increment_vec(_dof_indices[0] + n);
1241 0 : n += n_dof_indices;
1242 : }
1243 : }
1244 0 : }
1245 :
1246 : template <typename OutputType>
1247 : const OutputType &
1248 0 : MooseVariableData<OutputType>::nodalValueDot() const
1249 : {
1250 0 : if (isNodal())
1251 : {
1252 0 : if (_sys.solutionUDot())
1253 : {
1254 0 : _need_dof_values_dot = true;
1255 0 : return _nodal_value_dot;
1256 : }
1257 : else
1258 0 : mooseError(
1259 : "MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set "
1260 : "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1261 : }
1262 : else
1263 0 : mooseError("Nodal values can be requested only on nodal variables, variable '",
1264 0 : var().name(),
1265 : "' is not nodal.");
1266 : }
1267 :
1268 : template <typename OutputType>
1269 : const OutputType &
1270 0 : MooseVariableData<OutputType>::nodalValueDotDot() const
1271 : {
1272 0 : if (isNodal())
1273 : {
1274 0 : if (_sys.solutionUDotDot())
1275 : {
1276 0 : _need_dof_values_dotdot = true;
1277 0 : return _nodal_value_dotdot;
1278 : }
1279 : else
1280 0 : mooseError(
1281 : "MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. "
1282 : "Please set uDotDotRequested() to true in FEProblemBase before requesting "
1283 : "`u_dotdot`.");
1284 : }
1285 : else
1286 0 : mooseError("Nodal values can be requested only on nodal variables, variable '",
1287 0 : var().name(),
1288 : "' is not nodal.");
1289 : }
1290 :
1291 : template <typename OutputType>
1292 : const OutputType &
1293 0 : MooseVariableData<OutputType>::nodalValueDotOld() const
1294 : {
1295 0 : if (isNodal())
1296 : {
1297 0 : if (_sys.solutionUDotOld())
1298 : {
1299 0 : _need_dof_values_dot_old = true;
1300 0 : return _nodal_value_dot_old;
1301 : }
1302 : else
1303 0 : mooseError("MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. "
1304 : "Please set uDotOldRequested() to true in FEProblemBase before requesting "
1305 : "`u_dot_old`.");
1306 : }
1307 : else
1308 0 : mooseError("Nodal values can be requested only on nodal variables, variable '",
1309 0 : var().name(),
1310 : "' is not nodal.");
1311 : }
1312 :
1313 : template <typename OutputType>
1314 : const OutputType &
1315 0 : MooseVariableData<OutputType>::nodalValueDotDotOld() const
1316 : {
1317 0 : if (isNodal())
1318 : {
1319 0 : if (_sys.solutionUDotDotOld())
1320 : {
1321 0 : _need_dof_values_dotdot_old = true;
1322 0 : return _nodal_value_dotdot_old;
1323 : }
1324 : else
1325 0 : mooseError(
1326 : "MooseVariableData: Old second time derivative of solution (`u_dotdot_old`) is not "
1327 : "stored. Please set uDotDotOldRequested() to true in FEProblemBase before "
1328 : "requesting `u_dotdot_old`.");
1329 : }
1330 : else
1331 0 : mooseError("Nodal values can be requested only on nodal variables, variable '",
1332 0 : var().name(),
1333 : "' is not nodal.");
1334 : }
1335 :
1336 : template <typename OutputType>
1337 : void
1338 246348834 : MooseVariableData<OutputType>::computeNodalValues()
1339 : {
1340 246348834 : if (_has_dof_indices)
1341 : {
1342 246348630 : fetchDofValues();
1343 246348630 : assignNodalValue();
1344 :
1345 246348630 : if (_need_ad)
1346 : {
1347 3033194 : fetchADDofValues();
1348 3033194 : assignADNodalValue();
1349 : }
1350 : }
1351 : else
1352 204 : zeroSizeDofValues();
1353 246348834 : }
1354 :
1355 : template <typename OutputType>
1356 : void
1357 2903180 : MooseVariableData<OutputType>::assignADNodalValue()
1358 : {
1359 : mooseAssert(_ad_dof_values.size(), "The AD dof values container must have size greater than 0");
1360 2903180 : _ad_nodal_value = _ad_dof_values[0];
1361 2903180 : }
1362 :
1363 : template <>
1364 : void
1365 130014 : MooseVariableData<RealVectorValue>::assignADNodalValue()
1366 : {
1367 130014 : const auto num_dofs = _dof_indices.size();
1368 : mooseAssert(_ad_dof_values.size() == num_dofs,
1369 : "Our dof values container size should match the dof indices container size");
1370 387858 : for (const auto i : make_range(num_dofs))
1371 257844 : _ad_nodal_value(i) = _ad_dof_values[i];
1372 130014 : }
1373 :
1374 : template <typename OutputType>
1375 : void
1376 2207079 : MooseVariableData<OutputType>::prepareIC()
1377 : {
1378 : if constexpr (std::is_same<RealEigenVector, OutputType>::value)
1379 55374 : _dof_map.array_dof_indices(_elem, _dof_indices, _var_num);
1380 : else
1381 2151705 : _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1382 :
1383 : mooseAssert(_dof_indices.size() % _count == 0,
1384 : "The number of dof indices should divide cleanly by the variable count");
1385 2207079 : const auto num_shapes = _dof_indices.size() / _count;
1386 2207079 : _vector_tags_dof_u[_solution_tag].resize(num_shapes);
1387 :
1388 2207079 : unsigned int nqp = _qrule->n_points();
1389 2207079 : _vector_tag_u[_solution_tag].resize(nqp);
1390 2207079 : }
1391 :
1392 : template <typename OutputType>
1393 : void
1394 473876275 : MooseVariableData<OutputType>::prepare()
1395 : {
1396 : if constexpr (std::is_same<OutputType, RealEigenVector>::value)
1397 3506105 : _dof_map.array_dof_indices(_elem, _dof_indices, _var_num);
1398 : else
1399 470370170 : _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1400 :
1401 473876275 : _has_dof_values = false;
1402 :
1403 : // FIXME: remove this when the Richard's module is migrated to use the new NodalCoupleable
1404 : // interface.
1405 473876275 : _has_dof_indices = _dof_indices.size();
1406 473876275 : }
1407 :
1408 : template <typename OutputType>
1409 : void
1410 282198903 : MooseVariableData<OutputType>::reinitNode()
1411 : {
1412 : if constexpr (std::is_same<OutputType, RealEigenVector>::value)
1413 2304330 : _dof_map.array_dof_indices(_node, _dof_indices, _var_num);
1414 : else
1415 279894573 : _dof_map.dof_indices(_node, _dof_indices, _var_num);
1416 :
1417 282198903 : const auto n_dofs = _dof_indices.size();
1418 282198903 : if (n_dofs)
1419 : {
1420 : // For standard variables. _nodal_dof_index is retrieved by nodalDofIndex() which is used in
1421 : // NodalBC for example
1422 246342821 : _nodal_dof_index = _dof_indices[0];
1423 246342821 : _has_dof_indices = true;
1424 : }
1425 : else
1426 35856082 : _has_dof_indices = false;
1427 282198903 : }
1428 :
1429 : template <typename OutputType>
1430 : void
1431 152208408 : MooseVariableData<OutputType>::reinitAux()
1432 : {
1433 : /* FIXME: this method is only for elemental auxiliary variables, so
1434 : * we may want to rename it */
1435 152208408 : if (_elem)
1436 : {
1437 : if constexpr (std::is_same<RealEigenVector, OutputType>::value)
1438 79714 : _dof_map.array_dof_indices(_elem, _dof_indices, _var_num);
1439 : else
1440 151182461 : _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1441 151262175 : if (_elem->n_dofs(_sys.number(), _var_num) > 0)
1442 : {
1443 : // FIXME: Setting _nodal_dof_index inside of a method that apparently is only for "elemental"
1444 : // aux variables seems absolutely absurd
1445 150389846 : _nodal_dof_index = _dof_indices[0];
1446 :
1447 150389846 : fetchDofValues();
1448 :
1449 : mooseAssert(_dof_indices.size() % _count == 0,
1450 : "The number of dof indices should be cleanly divisible by the variable count");
1451 150389846 : const auto num_shapes = _dof_indices.size() / _count;
1452 1088686722 : for (auto & dof_u : _vector_tags_dof_u)
1453 938296876 : dof_u.resize(num_shapes);
1454 :
1455 347817072 : for (auto & dof_u : _matrix_tags_dof_u)
1456 197427226 : dof_u.resize(num_shapes);
1457 :
1458 150389846 : _has_dof_indices = true;
1459 : }
1460 : else
1461 872329 : _has_dof_indices = false;
1462 : }
1463 : else
1464 946233 : _has_dof_indices = false;
1465 152208408 : }
1466 :
1467 : template <typename OutputType>
1468 : void
1469 6612 : MooseVariableData<OutputType>::reinitNodes(const std::vector<dof_id_type> & nodes)
1470 : {
1471 6612 : _dof_indices.clear();
1472 32917 : for (const auto & node_id : nodes)
1473 : {
1474 26305 : auto && nd = _subproblem.mesh().getMesh().query_node_ptr(node_id);
1475 26305 : if (nd && (_subproblem.mesh().isSemiLocal(const_cast<Node *>(nd))))
1476 : {
1477 26239 : if (nd->n_dofs(_sys.number(), _var_num) > 0)
1478 : {
1479 : if constexpr (std::is_same<RealEigenVector, OutputType>::value)
1480 : {
1481 96 : static thread_local std::vector<dof_id_type> dof_indices;
1482 96 : _dof_map.array_dof_indices(nd, dof_indices, _var_num);
1483 288 : for (const auto dof : dof_indices)
1484 192 : _dof_indices.push_back(dof);
1485 : }
1486 : else
1487 : {
1488 25105 : dof_id_type dof = nd->dof_number(_sys.number(), _var_num, 0);
1489 25105 : _dof_indices.push_back(dof);
1490 : }
1491 : }
1492 : }
1493 : }
1494 :
1495 6612 : if (!_dof_indices.empty())
1496 6408 : _has_dof_indices = true;
1497 : else
1498 204 : _has_dof_indices = false;
1499 6612 : }
1500 :
1501 : template class MooseVariableData<Real>;
1502 : template class MooseVariableData<RealVectorValue>;
1503 : template class MooseVariableData<RealEigenVector>;
|