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 495537 : 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 991074 : _fe_type(var.feType()),
39 495537 : _var_num(var.number()),
40 495537 : _assembly(_subproblem.assembly(_tid, var.kind() == Moose::VAR_SOLVER ? sys.number() : 0)),
41 495537 : _element_type(element_type),
42 495537 : _ad_zero(0),
43 495537 : _need_ad_u_dot(false),
44 495537 : _need_ad_u_dotdot(false),
45 495537 : _need_second(false),
46 495537 : _need_second_old(false),
47 495537 : _need_second_older(false),
48 495537 : _need_second_previous_nl(false),
49 495537 : _need_curl(false),
50 495537 : _need_curl_old(false),
51 495537 : _need_curl_older(false),
52 495537 : _need_div(false),
53 495537 : _need_div_old(false),
54 495537 : _need_div_older(false),
55 495537 : _need_ad(false),
56 495537 : _need_ad_u(false),
57 495537 : _need_ad_grad_u(false),
58 495537 : _need_ad_grad_u_dot(false),
59 495537 : _need_ad_second_u(false),
60 495537 : _need_ad_curl_u(false),
61 495537 : _has_dof_indices(false),
62 495537 : _qrule(qrule_in),
63 495537 : _qrule_face(qrule_face_in),
64 495537 : _use_dual(var.useDual()),
65 495537 : _second_phi_assembly_method(nullptr),
66 495537 : _second_phi_face_assembly_method(nullptr),
67 495537 : _curl_phi_assembly_method(nullptr),
68 495537 : _curl_phi_face_assembly_method(nullptr),
69 495537 : _div_phi_assembly_method(nullptr),
70 495537 : _div_phi_face_assembly_method(nullptr),
71 495537 : _ad_grad_phi_assembly_method(nullptr),
72 495537 : _ad_grad_phi_face_assembly_method(nullptr),
73 495537 : _time_integrator(nullptr),
74 495537 : _node(node),
75 495537 : _elem(elem),
76 495537 : _displaced(dynamic_cast<const DisplacedSystem *>(&_sys) ? true : false),
77 2477685 : _current_side(_assembly.side())
78 : {
79 495537 : _continuity = FEInterface::get_continuity(_fe_type);
80 :
81 495537 : _is_nodal = (_continuity == C_ZERO || _continuity == C_ONE);
82 :
83 495537 : _time_integrator = _sys.queryTimeIntegrator(_var_num);
84 :
85 : // Initialize AD zero with zero derivatives
86 495537 : const auto old_do = ADReal::do_derivatives;
87 495537 : ADReal::do_derivatives = true;
88 495537 : _ad_zero = 0.;
89 495537 : ADReal::do_derivatives = old_do;
90 :
91 495537 : switch (_element_type)
92 : {
93 165179 : case Moose::ElementType::Element:
94 : {
95 165179 : _phi_assembly_method = &Assembly::fePhi<OutputShape>;
96 165179 : _phi_face_assembly_method = &Assembly::fePhiFace<OutputShape>;
97 165179 : _grad_phi_assembly_method = &Assembly::feGradPhi<OutputShape>;
98 165179 : _grad_phi_face_assembly_method = &Assembly::feGradPhiFace<OutputShape>;
99 165179 : _second_phi_assembly_method = &Assembly::feSecondPhi<OutputShape>;
100 165179 : _second_phi_face_assembly_method = &Assembly::feSecondPhiFace<OutputShape>;
101 165179 : _curl_phi_assembly_method = &Assembly::feCurlPhi<OutputShape>;
102 165179 : _curl_phi_face_assembly_method = &Assembly::feCurlPhiFace<OutputShape>;
103 165179 : _div_phi_assembly_method = &Assembly::feDivPhi<OutputShape>;
104 165179 : _div_phi_face_assembly_method = &Assembly::feDivPhiFace<OutputShape>;
105 165179 : _ad_grad_phi_assembly_method = &Assembly::feADGradPhi<OutputShape>;
106 165179 : _ad_grad_phi_face_assembly_method = &Assembly::feADGradPhiFace<OutputShape>;
107 :
108 165179 : _ad_grad_phi = &_ad_grad_phi_assembly_method(_assembly, _fe_type);
109 165179 : _ad_grad_phi_face = &_ad_grad_phi_face_assembly_method(_assembly, _fe_type);
110 165179 : break;
111 : }
112 165179 : case Moose::ElementType::Neighbor:
113 : {
114 165179 : _phi_assembly_method = &Assembly::fePhiNeighbor<OutputShape>;
115 165179 : _phi_face_assembly_method = &Assembly::fePhiFaceNeighbor<OutputShape>;
116 165179 : _grad_phi_assembly_method = &Assembly::feGradPhiNeighbor<OutputShape>;
117 165179 : _grad_phi_face_assembly_method = &Assembly::feGradPhiFaceNeighbor<OutputShape>;
118 165179 : _second_phi_assembly_method = &Assembly::feSecondPhiNeighbor<OutputShape>;
119 165179 : _second_phi_face_assembly_method = &Assembly::feSecondPhiFaceNeighbor<OutputShape>;
120 165179 : _curl_phi_assembly_method = &Assembly::feCurlPhiNeighbor<OutputShape>;
121 165179 : _curl_phi_face_assembly_method = &Assembly::feCurlPhiFaceNeighbor<OutputShape>;
122 165179 : _div_phi_assembly_method = &Assembly::feDivPhiNeighbor<OutputShape>;
123 165179 : _div_phi_face_assembly_method = &Assembly::feDivPhiFaceNeighbor<OutputShape>;
124 :
125 165179 : _ad_grad_phi = nullptr;
126 165179 : _ad_grad_phi_face = nullptr;
127 165179 : break;
128 : }
129 165179 : case Moose::ElementType::Lower:
130 : {
131 165179 : if (_use_dual)
132 : {
133 135 : _phi_assembly_method = &Assembly::feDualPhiLower<OutputType>;
134 135 : _phi_face_assembly_method = &Assembly::feDualPhiLower<OutputType>; // Place holder
135 135 : _grad_phi_assembly_method = &Assembly::feGradDualPhiLower<OutputType>;
136 135 : _grad_phi_face_assembly_method = &Assembly::feGradDualPhiLower<OutputType>; // Place holder
137 : }
138 : else
139 : {
140 165044 : _phi_assembly_method = &Assembly::fePhiLower<OutputType>;
141 165044 : _phi_face_assembly_method = &Assembly::fePhiLower<OutputType>; // Place holder
142 165044 : _grad_phi_assembly_method = &Assembly::feGradPhiLower<OutputType>;
143 165044 : _grad_phi_face_assembly_method = &Assembly::feGradPhiLower<OutputType>; // Place holder
144 : }
145 :
146 165179 : _ad_grad_phi = nullptr;
147 165179 : _ad_grad_phi_face = nullptr;
148 165179 : break;
149 : }
150 : }
151 495537 : _phi = &_phi_assembly_method(_assembly, _fe_type);
152 495537 : _phi_face = &_phi_face_assembly_method(_assembly, _fe_type);
153 495537 : _grad_phi = &_grad_phi_assembly_method(_assembly, _fe_type);
154 495537 : _grad_phi_face = &_grad_phi_face_assembly_method(_assembly, _fe_type);
155 495537 : }
156 :
157 : template <typename OutputType>
158 : void
159 705589435 : MooseVariableData<OutputType>::setGeometry(Moose::GeometryType gm_type)
160 : {
161 705589435 : switch (gm_type)
162 : {
163 662981011 : case Moose::Volume:
164 : {
165 662981011 : _current_qrule = _qrule;
166 662981011 : _current_phi = _phi;
167 662981011 : _current_grad_phi = _grad_phi;
168 662981011 : _current_second_phi = _second_phi;
169 662981011 : _current_curl_phi = _curl_phi;
170 662981011 : _current_div_phi = _div_phi;
171 662981011 : _current_ad_grad_phi = _ad_grad_phi;
172 662981011 : break;
173 : }
174 42608424 : case Moose::Face:
175 : {
176 42608424 : _current_qrule = _qrule_face;
177 42608424 : _current_phi = _phi_face;
178 42608424 : _current_grad_phi = _grad_phi_face;
179 42608424 : _current_second_phi = _second_phi_face;
180 42608424 : _current_curl_phi = _curl_phi_face;
181 42608424 : _current_div_phi = _div_phi_face;
182 42608424 : _current_ad_grad_phi = _ad_grad_phi_face;
183 42608424 : break;
184 : }
185 : }
186 705589435 : }
187 :
188 : template <typename OutputType>
189 : const typename MooseVariableData<OutputType>::FieldVariableValue &
190 15965 : MooseVariableData<OutputType>::uDot() const
191 : {
192 15965 : if (_sys.solutionUDot())
193 : {
194 15965 : _need_u_dot = true;
195 15965 : 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 204 : MooseVariableData<OutputType>::uDotDot() const
205 : {
206 204 : if (_sys.solutionUDotDot())
207 : {
208 204 : _need_u_dotdot = true;
209 204 : 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 37 : MooseVariableData<OutputType>::gradSlnDot() const
250 : {
251 37 : if (_sys.solutionUDot())
252 : {
253 37 : _need_grad_dot = true;
254 37 : 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 187 : MooseVariableData<OutputType>::secondSln(Moose::SolutionState state) const
279 : {
280 187 : secondPhi();
281 187 : secondPhiFace();
282 187 : switch (state)
283 : {
284 187 : case Moose::Current:
285 : {
286 187 : _need_second = true;
287 187 : 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 159 : MooseVariableData<OutputType>::curlSln(Moose::SolutionState state) const
318 : {
319 159 : curlPhi();
320 159 : curlPhiFace();
321 159 : switch (state)
322 : {
323 159 : case Moose::Current:
324 : {
325 159 : _need_curl = true;
326 159 : 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 312 : MooseVariableData<OutputType>::divSln(Moose::SolutionState state) const
349 : {
350 312 : divPhi();
351 312 : divPhiFace();
352 312 : switch (state)
353 : {
354 312 : case Moose::Current:
355 : {
356 312 : _need_div = true;
357 312 : 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 26886 : MooseVariableData<OutputType>::secondPhi() const
380 : {
381 26886 : _second_phi = &_second_phi_assembly_method(_assembly, _fe_type);
382 26886 : return *_second_phi;
383 : }
384 :
385 : template <typename OutputType>
386 : const typename MooseVariableData<OutputType>::FieldVariablePhiSecond &
387 5408 : MooseVariableData<OutputType>::secondPhiFace() const
388 : {
389 5408 : _second_phi_face = &_second_phi_face_assembly_method(_assembly, _fe_type);
390 5408 : return *_second_phi_face;
391 : }
392 :
393 : template <typename OutputType>
394 : const typename MooseVariableData<OutputType>::FieldVariablePhiCurl &
395 57245 : MooseVariableData<OutputType>::curlPhi() const
396 : {
397 57245 : _curl_phi = &_curl_phi_assembly_method(_assembly, _fe_type);
398 57245 : return *_curl_phi;
399 : }
400 :
401 : template <typename OutputType>
402 : const typename MooseVariableData<OutputType>::FieldVariablePhiCurl &
403 209 : MooseVariableData<OutputType>::curlPhiFace() const
404 : {
405 209 : _curl_phi_face = &_curl_phi_face_assembly_method(_assembly, _fe_type);
406 209 : return *_curl_phi_face;
407 : }
408 :
409 : template <typename OutputType>
410 : const typename MooseVariableData<OutputType>::FieldVariablePhiDivergence &
411 469068 : MooseVariableData<OutputType>::divPhi() const
412 : {
413 469068 : _div_phi = &_div_phi_assembly_method(_assembly, _fe_type);
414 469068 : return *_div_phi;
415 : }
416 :
417 : template <typename OutputType>
418 : const typename MooseVariableData<OutputType>::FieldVariablePhiDivergence &
419 312 : MooseVariableData<OutputType>::divPhiFace() const
420 : {
421 312 : _div_phi_face = &_div_phi_face_assembly_method(_assembly, _fe_type);
422 312 : return *_div_phi_face;
423 : }
424 :
425 : template <typename OutputType>
426 : template <bool monomial>
427 : void
428 704878519 : MooseVariableData<OutputType>::computeValuesInternal()
429 : {
430 704878519 : const auto num_dofs = _dof_indices.size();
431 704878519 : if (num_dofs > 0)
432 615556963 : fetchDoFValues();
433 :
434 704878519 : const bool is_transient = _subproblem.isTransient();
435 704878519 : const auto nqp = _current_qrule->n_points();
436 704878519 : 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 4039217 : if (_qrule == _current_qrule)
442 : {
443 3825363 : _mapped_grad_phi.resize(num_dofs);
444 18115121 : for (const auto i : make_range(num_dofs))
445 : {
446 14289758 : _mapped_grad_phi[i].resize(nqp, Eigen::Map<RealDIMValue>(nullptr));
447 95693161 : for (const auto qp : make_range(nqp))
448 : // Note: this does NOT do any allocation. It is "reconstructing" the object in place
449 162806806 : new (&_mapped_grad_phi[i][qp])
450 81403403 : Eigen::Map<RealDIMValue>(const_cast<Real *>(&(*_current_grad_phi)[i][qp](0)));
451 : }
452 : }
453 : else
454 : {
455 213854 : _mapped_grad_phi_face.resize(num_dofs);
456 854266 : for (const auto i : make_range(num_dofs))
457 : {
458 640412 : _mapped_grad_phi_face[i].resize(nqp, Eigen::Map<RealDIMValue>(nullptr));
459 2261916 : for (const auto qp : make_range(nqp))
460 : // Note: this does NOT do any allocation. It is "reconstructing" the object in place
461 3243008 : new (&_mapped_grad_phi_face[i][qp])
462 1621504 : 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 2067126397 : const auto fill = [this, nqp, num_dofs](auto & dest, const auto & phi, const auto & dof_values)
478 : {
479 : if constexpr (monomial)
480 158395425 : libmesh_ignore(num_dofs);
481 :
482 : // Deduce OutputType
483 1362247878 : constexpr bool is_real = std::is_same_v<OutputType, Real>;
484 1362247878 : constexpr bool is_real_vector = std::is_same_v<OutputType, RealVectorValue>;
485 1362247878 : 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 1353979693 : 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 1362247878 : constexpr bool is_value = std::is_same_v<dest_array_type, OutputType>;
495 1362247878 : constexpr bool is_gradient = std::is_same_v<dest_array_type, OutputGradient>;
496 1362247878 : constexpr bool is_second = std::is_same_v<dest_array_type, OutputSecond>;
497 1362247878 : 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 18023583441 : const auto set_zero = [this, &dest](const auto qp)
503 : {
504 : if constexpr (!is_eigen)
505 5514928353 : libmesh_ignore(this);
506 :
507 : if constexpr (is_real || is_real_vector)
508 5514928353 : dest[qp] = 0;
509 : else if constexpr (is_eigen)
510 : {
511 : if constexpr (is_value)
512 27141450 : dest[qp].setZero(this->_count);
513 : else if constexpr (is_gradient)
514 11708718 : 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 >10138*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 15792145361 : dest[qp] += phi[i][qp] * dof_values[i];
531 : else if constexpr (is_gradient || is_second)
532 9197620972 : 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 265652364 : for (const auto d : make_range(Moose::dim))
541 199239273 : 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 1362247878 : 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 158395425 : set_zero(0);
563 158395425 : accumulate(0, 0);
564 708341111 : for (unsigned int qp = 1; qp < nqp; ++qp)
565 549945686 : dest[qp] = dest[0];
566 : }
567 : // Non monomial case
568 : else
569 : {
570 6599235549 : for (const auto qp : make_range(nqp))
571 5395383096 : set_zero(qp);
572 6249472193 : for (const auto i : make_range(num_dofs))
573 29943403739 : for (const auto qp : make_range(nqp))
574 24897783999 : accumulate(i, qp);
575 : }
576 : };
577 :
578 : // Curl
579 704878519 : if (_need_curl)
580 71020 : fill(_curl_u, *_current_curl_phi, _vector_tags_dof_u[_solution_tag]);
581 704878519 : if (_need_curl_old)
582 0 : fill(_curl_u_old, *_current_curl_phi, _vector_tags_dof_u[_old_solution_tag]);
583 :
584 : // Div
585 704878519 : if (_need_div)
586 352128 : fill(_div_u, *_current_div_phi, _vector_tags_dof_u[_solution_tag]);
587 704878519 : 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 704878519 : if (_need_second)
592 83053 : fill(_second_u, *_current_second_phi, _vector_tags_dof_u[_solution_tag]);
593 704878519 : 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 1418722938 : for (auto tag : _required_vector_tags)
599 : {
600 713844419 : if (_need_vector_tag_u[tag] && _sys.hasVector(tag) && _sys.getVector(tag).closed())
601 711383905 : fill(_vector_tag_u[tag], *_current_phi, _vector_tags_dof_u[tag]);
602 713844419 : if (_need_vector_tag_grad[tag] && _sys.hasVector(tag) && _sys.getVector(tag).closed())
603 406690873 : fill(_vector_tag_grad[tag], *_current_grad_phi, _vector_tags_dof_u[tag]);
604 : }
605 :
606 : // Matrix tags
607 704878903 : for (auto tag : active_coupleable_matrix_tags)
608 384 : if (_need_matrix_tag_u[tag])
609 128 : fill(_matrix_tag_u[tag], *_current_phi, _matrix_tags_dof_u[tag]);
610 :
611 : // Derivatives and old values
612 704878519 : if (is_transient)
613 : {
614 526179330 : if (_need_second_old)
615 0 : fill(_second_u_old, *_current_second_phi, _vector_tags_dof_u[_old_solution_tag]);
616 526179330 : if (_need_second_older)
617 0 : fill(_second_u_older, *_current_second_phi, _vector_tags_dof_u[_older_solution_tag]);
618 526179330 : if (_need_u_dot)
619 243535210 : fill(_u_dot, *_current_phi, _dof_values_dot);
620 526179330 : if (_need_u_dotdot)
621 6206 : fill(_u_dotdot, *_current_phi, _dof_values_dotdot);
622 526179330 : if (_need_u_dot_old)
623 0 : fill(_u_dot_old, *_current_phi, _dof_values_dot_old);
624 526179330 : if (_need_u_dotdot_old)
625 0 : fill(_u_dotdot_old, *_current_phi, _dof_values_dotdot_old);
626 :
627 526179330 : if (_need_du_dot_du)
628 : {
629 243657082 : _du_dot_du.resize(nqp);
630 1297579381 : for (const auto qp : make_range(nqp))
631 1053922299 : _du_dot_du[qp] = 0.;
632 1298837156 : for (const auto i : make_range(num_dofs))
633 6048738460 : for (const auto qp : make_range(nqp))
634 4993558386 : _du_dot_du[qp] = _dof_du_dot_du[i];
635 : }
636 526179330 : if (_need_du_dotdot_du)
637 : {
638 5062 : _du_dotdot_du.resize(nqp);
639 24140 : for (const auto qp : make_range(nqp))
640 19078 : _du_dotdot_du[qp] = 0.;
641 42828 : for (const auto i : make_range(num_dofs))
642 187660 : for (const auto qp : make_range(nqp))
643 149894 : _du_dotdot_du[qp] = _dof_du_dotdot_du[i];
644 : }
645 :
646 526179330 : if (_need_grad_dot)
647 125355 : fill(_grad_u_dot, *_current_grad_phi, _dof_values_dot);
648 526179330 : 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 700839302 : if (_need_ad)
655 25227938 : computeAD(num_dofs, nqp);
656 704878519 : }
657 :
658 : template <typename OutputType>
659 : void
660 556415243 : MooseVariableData<OutputType>::computeValues()
661 : {
662 556415243 : computeValuesInternal</* monomial = */ false>();
663 556415243 : }
664 :
665 : template <typename OutputType>
666 : void
667 149247540 : MooseVariableData<OutputType>::computeMonomialValues()
668 : {
669 149247540 : if (_dof_indices.size() == 0)
670 710916 : return;
671 :
672 : // Monomial optimizations are not appropriate after p-refinement
673 148536624 : if (_elem->p_level())
674 73348 : computeValues();
675 : else
676 148463276 : computeValuesInternal</* monomial = */ true>();
677 : }
678 :
679 : template <typename OutputType>
680 : void
681 25227938 : MooseVariableData<OutputType>::computeAD(const unsigned int num_dofs, const unsigned int nqp)
682 : {
683 25227938 : const bool do_derivatives = Moose::doDerivatives(_subproblem, _sys);
684 :
685 25227938 : _ad_dof_values.resize(num_dofs);
686 139090169 : for (const auto i : make_range(num_dofs))
687 113862231 : _ad_dof_values[i] = (*_sys.currentSolution())(_dof_indices[i]);
688 : // NOTE! You have to do this AFTER setting the value!
689 25227938 : if (do_derivatives)
690 29033695 : for (const auto i : make_range(num_dofs))
691 24198936 : Moose::derivInsert(_ad_dof_values[i].derivatives(), _dof_indices[i], 1.);
692 :
693 25227938 : if (_need_ad_u)
694 : {
695 23903797 : _ad_u.resize(nqp);
696 104141594 : for (const auto qp : make_range(nqp))
697 80237797 : _ad_u[qp] = _ad_zero;
698 :
699 133501630 : for (const auto i : make_range(num_dofs))
700 533194000 : for (const auto qp : make_range(nqp))
701 423596167 : _ad_u[qp] += _ad_dof_values[i] * (*_current_phi)[i][qp];
702 : }
703 :
704 25227938 : if (_need_ad_grad_u)
705 : {
706 18614789 : _ad_grad_u.resize(nqp);
707 84159449 : for (const auto qp : make_range(nqp))
708 65544660 : _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 18614789 : if (_displaced && _current_ad_grad_phi)
714 2952192 : for (const auto i : make_range(num_dofs))
715 16241820 : for (const auto qp : make_range(nqp))
716 14361702 : _ad_grad_u[qp] += _ad_dof_values[i] * (*_current_ad_grad_phi)[i][qp];
717 : else
718 93658364 : for (const auto i : make_range(num_dofs))
719 398310926 : for (const auto qp : make_range(nqp))
720 322731314 : _ad_grad_u[qp] += _ad_dof_values[i] * (*_current_grad_phi)[i][qp];
721 : }
722 :
723 25227938 : 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 25227938 : if (_need_ad_curl_u)
737 : {
738 2858120 : _ad_curl_u.resize(nqp);
739 13362760 : for (const auto qp : make_range(nqp))
740 10504640 : _ad_curl_u[qp] = _ad_zero;
741 :
742 14359400 : for (const auto i : make_range(num_dofs))
743 53955040 : 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 42453760 : _ad_curl_u[qp] += _ad_dof_values[i] * (*_current_curl_phi)[i][qp];
750 : }
751 : }
752 :
753 25227938 : bool is_transient = _subproblem.isTransient();
754 25227938 : if (is_transient)
755 : {
756 10331616 : if (_need_ad_u_dot)
757 : {
758 2359413 : _ad_dofs_dot.resize(num_dofs);
759 2359413 : if (_need_ad_u_dotdot)
760 394 : _ad_dofs_dotdot.resize(num_dofs);
761 2359413 : _ad_u_dot.resize(nqp);
762 10198771 : for (const auto qp : make_range(nqp))
763 7839358 : _ad_u_dot[qp] = _ad_zero;
764 :
765 2359413 : if (_time_integrator && _time_integrator->dt())
766 : {
767 12021220 : for (const auto i : make_range(num_dofs))
768 9680378 : _ad_dofs_dot[i] = _ad_dof_values[i];
769 12021220 : for (const auto i : make_range(num_dofs))
770 19359634 : _time_integrator->computeADTimeDerivatives(_ad_dofs_dot[i],
771 9680378 : _dof_indices[i],
772 9680378 : _need_ad_u_dotdot ? _ad_dofs_dotdot[i]
773 : : _ad_real_dummy);
774 :
775 12021220 : for (const auto i : make_range(num_dofs))
776 42326164 : for (const auto qp : make_range(nqp))
777 32645786 : _ad_u_dot[qp] += (*_current_phi)[i][qp] * _ad_dofs_dot[i];
778 : }
779 18571 : 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 10331616 : if (_need_ad_u_dotdot)
789 : {
790 394 : _ad_u_dotdot.resize(nqp);
791 1580 : for (const auto qp : make_range(nqp))
792 1186 : _ad_u_dotdot[qp] = _ad_zero;
793 :
794 394 : if (_time_integrator && _time_integrator->dt())
795 1476 : for (const auto i : make_range(num_dofs))
796 5316 : for (const auto qp : make_range(nqp))
797 4194 : _ad_u_dotdot[qp] += (*_current_phi)[i][qp] * _ad_dofs_dotdot[i];
798 40 : 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 10331616 : 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 25227938 : }
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 7623827 : MooseVariableData<OutputType>::setDofValue(const OutputData & value, unsigned int index)
841 : {
842 7623827 : auto & dof_values = _vector_tags_dof_u[_solution_tag];
843 7623827 : dof_values[index] = value;
844 7623827 : _has_dof_values = true;
845 :
846 7623827 : auto & u = _vector_tag_u[_solution_tag];
847 7623827 : const auto nqps = u.size();
848 7623827 : const auto ndofs = dof_values.size();
849 40712458 : for (const auto qp : make_range(nqps))
850 33088631 : u[qp] *= 0.;
851 40712458 : for (const auto qp : make_range(nqps))
852 282386514 : for (const auto i : make_range(ndofs))
853 249297883 : u[qp] += (*_phi)[i][qp] * dof_values[i];
854 7623827 : }
855 :
856 : template <typename OutputType>
857 : void
858 573480 : MooseVariableData<OutputType>::setDofValues(const DenseVector<OutputData> & values)
859 : {
860 573480 : auto & dof_values = _vector_tags_dof_u[_solution_tag];
861 3399546 : for (unsigned int i = 0; i < values.size(); i++)
862 2826066 : dof_values[i] = values(i);
863 :
864 573480 : _has_dof_values = true;
865 :
866 573480 : auto & u = _vector_tag_u[_solution_tag];
867 573480 : const auto nqps = u.size();
868 573480 : const auto ndofs = dof_values.size();
869 4921392 : for (const auto qp : make_range(nqps))
870 4347912 : u[qp] *= 0.;
871 4921392 : for (const auto qp : make_range(nqps))
872 31890188 : for (const auto i : make_range(ndofs))
873 27542276 : u[qp] += (*_phi)[i][qp] * dof_values[i];
874 573480 : }
875 :
876 : template <typename OutputType>
877 : void
878 54525825 : MooseVariableData<OutputType>::insertNodalValue(NumericVector<Number> & residual,
879 : const OutputData & v)
880 : {
881 54525825 : residual.set(_nodal_dof_index, v);
882 54525825 : }
883 :
884 : template <>
885 : void
886 275872 : MooseVariableData<RealEigenVector>::insertNodalValue(NumericVector<Number> & residual,
887 : const RealEigenVector & v)
888 : {
889 983456 : for (const auto j : make_range(_count))
890 707584 : residual.set(_nodal_dof_index + j, v(j));
891 275872 : }
892 :
893 : template <typename OutputType>
894 : typename MooseVariableData<OutputType>::OutputData
895 104554 : 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 104554 : dof_id_type dof = node.dof_number(_sys.number(), _var_num, 0);
907 :
908 104554 : switch (state)
909 : {
910 1220 : case Moose::Current:
911 1220 : return (*_sys.currentSolution())(dof);
912 :
913 103334 : case Moose::Old:
914 103334 : 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 70888 : MooseVariableData<OutputType>::getElementalValue(const Elem * elem,
967 : Moose::SolutionState state,
968 : unsigned int idx) const
969 : {
970 70888 : std::vector<dof_id_type> dof_indices;
971 70888 : _dof_map.dof_indices(elem, dof_indices, _var_num);
972 :
973 70888 : switch (state)
974 : {
975 69928 : case Moose::Current:
976 69928 : return (*_sys.currentSolution())(dof_indices[idx]);
977 :
978 480 : case Moose::Old:
979 480 : return _sys.solutionOld()(dof_indices[idx]);
980 :
981 480 : case Moose::Older:
982 480 : return _sys.solutionOlder()(dof_indices[idx]);
983 :
984 0 : default:
985 0 : mooseError("PreviousNL not currently supported for getElementalValue");
986 : }
987 70888 : }
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 18860 : MooseVariableData<OutputType>::getDofIndices(const Elem * elem,
1028 : std::vector<dof_id_type> & dof_indices) const
1029 : {
1030 18860 : _dof_map.dof_indices(elem, dof_indices, _var_num);
1031 18860 : }
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 2720 : MooseVariableData<RealEigenVector>::addSolution(NumericVector<Number> & sol,
1044 : const DenseVector<Number> & v) const
1045 : {
1046 2720 : unsigned int p = 0;
1047 2720 : const auto num_dofs = _dof_indices.size();
1048 8160 : for (const auto j : make_range(_count))
1049 : {
1050 5440 : unsigned int inc = (isNodal() ? j : j * num_dofs);
1051 27200 : for (const auto i : make_range(num_dofs))
1052 21760 : sol.add(_dof_indices[i] + inc, v(p++));
1053 : }
1054 2720 : }
1055 :
1056 : template <typename OutputType>
1057 : const typename MooseVariableData<OutputType>::DoFValue &
1058 305 : MooseVariableData<OutputType>::dofValuesDot() const
1059 : {
1060 305 : if (_sys.solutionUDot())
1061 : {
1062 305 : _need_dof_values_dot = true;
1063 305 : 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 122 : MooseVariableData<OutputType>::dofValuesDuDotDu() const
1118 : {
1119 122 : _need_dof_du_dot_du = true;
1120 122 : 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 1774 : MooseVariableData<OutputType>::computeIncrementAtQps(const NumericVector<Number> & increment_vec)
1134 : {
1135 1774 : unsigned int nqp = _qrule->n_points();
1136 :
1137 1774 : _increment.resize(nqp);
1138 : // Compute the increment at each quadrature point
1139 1774 : unsigned int num_dofs = _dof_indices.size();
1140 15108 : for (const auto qp : make_range(nqp))
1141 : {
1142 13334 : _increment[qp] = 0.;
1143 129924 : for (const auto i : make_range(num_dofs))
1144 116590 : _increment[qp] += (*_phi)[i][qp] * increment_vec(_dof_indices[i]);
1145 : }
1146 1774 : }
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 7440 : MooseVariableData<OutputType>::computeIncrementAtNode(const NumericVector<Number> & increment_vec)
1185 : {
1186 7440 : if (!isNodal())
1187 0 : mooseError("computeIncrementAtNode can only be called for nodal variables");
1188 :
1189 7440 : _increment.resize(1);
1190 :
1191 : // Compute the increment for the current DOF
1192 7440 : _increment[0] = increment_vec(_dof_indices[0]);
1193 7440 : }
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 270795437 : MooseVariableData<OutputType>::computeNodalValues()
1314 : {
1315 270795437 : if (_has_dof_indices)
1316 : {
1317 270795227 : fetchDoFValues();
1318 270795227 : assignNodalValue();
1319 :
1320 270795227 : if (_need_ad)
1321 3114893 : fetchADNodalValues();
1322 : }
1323 : else
1324 210 : zeroSizeDofValues();
1325 270795437 : }
1326 :
1327 : template <typename OutputType>
1328 : void
1329 3114893 : MooseVariableData<OutputType>::fetchADNodalValues()
1330 : {
1331 3114893 : auto n = _dof_indices.size();
1332 : libmesh_assert(n);
1333 3114893 : _ad_dof_values.resize(n);
1334 :
1335 3114893 : if (_need_ad_u_dot)
1336 566899 : _ad_dofs_dot.resize(n);
1337 3114893 : if (_need_ad_u_dotdot)
1338 1216 : _ad_dofs_dotdot.resize(n);
1339 :
1340 3114893 : const bool do_derivatives =
1341 3114893 : ADReal::do_derivatives && _sys.number() == _subproblem.currentNlSysNum();
1342 :
1343 6396639 : for (decltype(n) i = 0; i < n; ++i)
1344 : {
1345 3281746 : _ad_dof_values[i] = _vector_tags_dof_u[_solution_tag][i];
1346 3281746 : if (do_derivatives)
1347 1341842 : Moose::derivInsert(_ad_dof_values[i].derivatives(), _dof_indices[i], 1.);
1348 3281746 : assignADNodalValue(_ad_dof_values[i], i);
1349 :
1350 3281746 : if (_need_ad_u_dot)
1351 : {
1352 574359 : if (_time_integrator && _time_integrator->dt())
1353 : {
1354 574359 : _ad_dofs_dot[i] = _ad_dof_values[i];
1355 1147502 : _time_integrator->computeADTimeDerivatives(_ad_dofs_dot[i],
1356 574359 : _dof_indices[i],
1357 574359 : _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 3114893 : }
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 2979111 : MooseVariableData<Real>::assignADNodalValue(const ADReal & value, const unsigned int &)
1380 : {
1381 2979111 : _ad_nodal_value = value;
1382 2979111 : }
1383 :
1384 : template <>
1385 : void
1386 302635 : MooseVariableData<RealVectorValue>::assignADNodalValue(const ADReal & value,
1387 : const unsigned int & component)
1388 : {
1389 302635 : _ad_nodal_value(component) = value;
1390 302635 : }
1391 :
1392 : template <typename OutputType>
1393 : void
1394 1998668 : MooseVariableData<OutputType>::prepareIC()
1395 : {
1396 1998668 : _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1397 1998668 : _vector_tags_dof_u[_solution_tag].resize(_dof_indices.size());
1398 :
1399 1998668 : unsigned int nqp = _qrule->n_points();
1400 1998668 : _vector_tag_u[_solution_tag].resize(nqp);
1401 1998668 : }
1402 :
1403 : template <typename OutputType>
1404 : void
1405 481567578 : MooseVariableData<OutputType>::prepare()
1406 : {
1407 481567578 : _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1408 481567578 : _has_dof_values = false;
1409 :
1410 : // FIXME: remove this when the Richard's module is migrated to use the new NodalCoupleable
1411 : // interface.
1412 481567578 : _has_dof_indices = _dof_indices.size();
1413 481567578 : }
1414 :
1415 : template <typename OutputType>
1416 : void
1417 307731586 : MooseVariableData<OutputType>::reinitNode()
1418 : {
1419 307731586 : if (std::size_t n_dofs = _node->n_dofs(_sys.number(), _var_num))
1420 : {
1421 270789042 : _dof_indices.resize(n_dofs);
1422 542598685 : for (std::size_t i = 0; i < n_dofs; ++i)
1423 271809643 : _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 270789042 : _nodal_dof_index = _dof_indices[0];
1427 270789042 : _has_dof_indices = true;
1428 : }
1429 : else
1430 : {
1431 36942544 : _dof_indices.clear(); // Clear these so Assembly doesn't think there's dofs here
1432 36942544 : _has_dof_indices = false;
1433 : }
1434 307731586 : }
1435 :
1436 : template <typename OutputType>
1437 : void
1438 148512161 : MooseVariableData<OutputType>::reinitAux()
1439 : {
1440 : /* FIXME: this method is only for elemental auxiliary variables, so
1441 : * we may want to rename it */
1442 148512161 : if (_elem)
1443 : {
1444 147542702 : _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1445 147542702 : 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 146687106 : _nodal_dof_index = _elem->dof_number(_sys.number(), _var_num, 0);
1449 :
1450 146687106 : fetchDoFValues();
1451 :
1452 146687106 : const auto num_dofs = _dof_indices.size();
1453 1207449423 : for (auto & dof_u : _vector_tags_dof_u)
1454 1060762317 : dof_u.resize(num_dofs);
1455 :
1456 440072014 : for (auto & dof_u : _matrix_tags_dof_u)
1457 293384908 : dof_u.resize(num_dofs);
1458 :
1459 146687106 : _has_dof_indices = true;
1460 : }
1461 : else
1462 855596 : _has_dof_indices = false;
1463 : }
1464 : else
1465 969459 : _has_dof_indices = false;
1466 148512161 : }
1467 :
1468 : template <typename OutputType>
1469 : void
1470 6990 : MooseVariableData<OutputType>::reinitNodes(const std::vector<dof_id_type> & nodes)
1471 : {
1472 6990 : _dof_indices.clear();
1473 37684 : for (const auto & node_id : nodes)
1474 : {
1475 30694 : auto && nd = _subproblem.mesh().getMesh().query_node_ptr(node_id);
1476 30694 : if (nd && (_subproblem.mesh().isSemiLocal(const_cast<Node *>(nd))))
1477 : {
1478 30628 : if (nd->n_dofs(_sys.number(), _var_num) > 0)
1479 : {
1480 29617 : dof_id_type dof = nd->dof_number(_sys.number(), _var_num, 0);
1481 29617 : _dof_indices.push_back(dof);
1482 : }
1483 : }
1484 : }
1485 :
1486 6990 : if (!_dof_indices.empty())
1487 6780 : _has_dof_indices = true;
1488 : else
1489 210 : _has_dof_indices = false;
1490 6990 : }
1491 :
1492 : template class MooseVariableData<Real>;
1493 : template class MooseVariableData<RealVectorValue>;
1494 : template class MooseVariableData<RealEigenVector>;
|