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