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