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