https://mooseframework.inl.gov
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 
25 using namespace libMesh;
26 
27 template <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 {
62  _continuity = FEInterface::get_continuity(_fe_type);
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 
140 template <typename OutputType>
141 void
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 
171 template <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 
185 template <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 
200 template <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 
215 template <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 
230 template <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 
244 template <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 
259 template <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 
285  case Moose::PreviousNL:
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 
298 template <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 
329 template <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 
360 template <typename OutputType>
363 {
364  _second_phi = &_second_phi_assembly_method(_assembly, _fe_type);
365  return *_second_phi;
366 }
367 
368 template <typename OutputType>
371 {
372  _second_phi_face = &_second_phi_face_assembly_method(_assembly, _fe_type);
373  return *_second_phi_face;
374 }
375 
376 template <typename OutputType>
379 {
380  _curl_phi = &_curl_phi_assembly_method(_assembly, _fe_type);
381  return *_curl_phi;
382 }
383 
384 template <typename OutputType>
387 {
388  _curl_phi_face = &_curl_phi_face_assembly_method(_assembly, _fe_type);
389  return *_curl_phi_face;
390 }
391 
392 template <typename OutputType>
395 {
396  _div_phi = &_div_phi_assembly_method(_assembly, _fe_type);
397  return *_div_phi;
398 }
399 
400 template <typename OutputType>
403 {
404  _div_phi_face = &_div_phi_face_assembly_method(_assembly, _fe_type);
405  return *_div_phi_face;
406 }
407 
408 template <typename OutputType>
409 template <bool constant_monomial,
410  typename DestinationType,
411  typename ShapeType,
412  typename DofValuesType>
413 void
414 MooseVariableData<OutputType>::fill(DestinationType & dest,
415  const ShapeType & phi,
416  const DofValuesType & dof_values,
417  const unsigned int nqp,
418  const std::size_t num_shapes)
419 {
420  if constexpr (constant_monomial)
421  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 
527 template <typename OutputType>
528 template <bool constant_monomial>
529 void
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 
682 template <typename OutputType>
683 void
685 {
686  computeValuesInternal</* constant_monomial = */ false>();
687 }
688 
689 template <typename OutputType>
690 void
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 
703 template <typename OutputType>
704 void
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 
759 template <>
760 void
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 
787 template <typename OutputType>
788 template <bool constant_monomial>
789 void
790 MooseVariableData<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 
868 template <typename OutputType>
869 void
870 MooseVariableData<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 
886 template <typename OutputType>
887 void
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 
906 template <typename OutputType>
907 void
909  const DofValue & v)
910 {
911  residual.set(_nodal_dof_index, v);
912 }
913 
914 template <>
915 void
917  const RealEigenVector & v)
918 {
919  for (const auto j : make_range(_count))
920  residual.set(_nodal_dof_index + j, v(j));
921 }
922 
923 template <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 
954 template <>
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 
994 template <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 
1019 template <>
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 
1062 template <typename OutputType>
1063 void
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 
1073 template <typename OutputType>
1074 void
1076  const DenseVector<Number> & v) const
1077 {
1078  sol.add_vector(v, _dof_indices);
1079 }
1080 
1081 template <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 
1095 template <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 
1110 template <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 
1125 template <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 
1140 template <typename OutputType>
1141 const MooseArray<Number> &
1143 {
1144  _need_dof_du_dot_du = true;
1145  return _dof_du_dot_du;
1146 }
1147 
1148 template <typename OutputType>
1149 const MooseArray<Number> &
1151 {
1152  _need_dof_du_dotdot_du = true;
1153  return _dof_du_dotdot_du;
1154 }
1155 
1156 template <typename OutputType>
1157 void
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 
1173 template <>
1174 void
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 
1207 template <typename OutputType>
1208 void
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 
1220 template <>
1221 void
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 
1246 template <typename OutputType>
1247 const 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 
1268 template <typename OutputType>
1269 const 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 
1291 template <typename OutputType>
1292 const 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 
1313 template <typename OutputType>
1314 const 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 
1336 template <typename OutputType>
1337 void
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 
1355 template <typename OutputType>
1356 void
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 
1363 template <>
1364 void
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 
1374 template <typename OutputType>
1375 void
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 
1392 template <typename OutputType>
1393 void
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 
1408 template <typename OutputType>
1409 void
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 
1429 template <typename OutputType>
1430 void
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 
1467 template <typename OutputType>
1468 void
1469 MooseVariableData<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  dof_id_type dof = nd->dof_number(_sys.number(), _var_num, 0);
1480  _dof_indices.push_back(dof);
1481  }
1482  }
1483  }
1484 
1485  if (!_dof_indices.empty())
1486  _has_dof_indices = true;
1487  else
1488  _has_dof_indices = false;
1489 }
1490 
1491 template class MooseVariableData<Real>;
1492 template class MooseVariableData<RealVectorValue>;
1493 template class MooseVariableData<RealEigenVector>;
const FieldVariableDivergence & divSln(Moose::SolutionState state) const
Local solution divergence getter.
std::string name(const ElemQuality q)
const Assembly & _assembly
const FieldVariableValue & uDotDotOld() const
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
const FieldVariablePhiCurl & curlPhi() const
curl_phi getter
void reinitNodes(const std::vector< dof_id_type > &nodes)
Set _dof_indices to the degrees of freedom existing on the passed-in nodes.
Class for stuff related to variables.
Definition: Adaptivity.h:31
void prepare()
Get the dof indices corresponding to the current element.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:323
void computeConstantMonomialValues()
compute the values for const monomial variables
void computeValues()
compute the variable values
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
const FieldVariableValue & uDotDot() const
void getDofIndices(const Elem *elem, std::vector< dof_id_type > &dof_indices) const
const DofValues & dofValuesDot() const
std::function< const typename OutputTools< OutputShape >::VariablePhiCurl &(const Assembly &, libMesh::FEType)> _curl_phi_assembly_method
const OutputType & nodalValueDotOld() const
std::function< const typename OutputTools< OutputShape >::VariablePhiCurl &(const Assembly &, libMesh::FEType)> _curl_phi_face_assembly_method
void computeIncrementAtNode(const libMesh::NumericVector< libMesh::Number > &increment_vec)
Compute and store incremental change at the current node based on increment_vec.
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:162
const FieldVariableValue & uDot() const
void assignADNodalValue()
Helper method for assigning nodal values from their corresponding solution values (dof values as they...
void computeNodalValues()
compute nodal things
const MooseArray< libMesh::Number > & dofValuesDuDotDotDu() const
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
ElementType
Definition: MooseTypes.h:812
std::function< const ADTemplateVariablePhiGradient< OutputShape > &(const Assembly &, libMesh::FEType)> _ad_grad_phi_assembly_method
Base class for a system (of equations)
Definition: SystemBase.h:84
const unsigned int _var_num
void fill(DestinationType &dest, const ShapeType &phi, const DofValuesType &dof_values, unsigned int nqp, std::size_t num_shapes)
void prepareIC()
prepare the initial condition
const FieldVariableGradient & gradSlnDot() const
Local time derivative of solution gradient getter.
bool doDerivatives(const SubProblem &subproblem, const SystemBase &sys)
Definition: ADUtils.C:83
void setDofValues(const DenseVector< DofValue > &values)
Set local DOF values and evaluate the values on quadrature points.
unsigned int n_dofs(const unsigned int s, const unsigned int var=libMesh::invalid_uint) 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
std::function< const typename OutputTools< OutputShape >::VariablePhiSecond &(const Assembly &, libMesh::FEType)> _second_phi_face_assembly_method
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)
void libmesh_ignore(const Args &...)
const MooseArray< libMesh::Number > & dofValuesDuDotDu() const
const FieldVariablePhiDivergence & divPhi() const
divergence_phi getter
const DofValues & dofValuesDotDotOld() const
dof_id_type id() const
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void computeValuesInternal()
Internal method for computeValues() and computeConstantMonomialValues()
const OutputType & nodalValueDot() const
const FieldVariablePhiSecond & secondPhiFace() const
second_phi_face getter
void computeIncrementAtQps(const libMesh::NumericVector< libMesh::Number > &increment_vec)
Compute and store incremental change in solution at QPs based on increment_vec.
C_ZERO
const FieldVariableGradient & gradSlnDotDot() const
Local second time derivative of solution gradient getter.
ShapeType
Users of this template class must specify the type of shape functions that will be used in the Jacobi...
Moose::DOFType< OutputType >::type DofValue
std::function< const typename OutputTools< OutputShape >::VariablePhiDivergence &(const Assembly &, libMesh::FEType)> _div_phi_face_assembly_method
void reinitNode()
Prepare degrees of freedom for the current node.
const DofValues & dofValuesDotOld() const
void mooseDeprecated(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:374
std::function< const ADTemplateVariablePhiGradient< OutputShape > &(const Assembly &, libMesh::FEType)> _ad_grad_phi_face_assembly_method
const TimeIntegrator * _time_integrator
Pointer to time integrator.
libMesh::FEContinuity _continuity
Continuity type of the variable.
Moose::ElementType _element_type
The element type this object is storing data for. This is either Element, Neighbor, or Lower.
ADReal _ad_zero
A zero AD variable.
std::function< const typename OutputTools< OutputShape >::VariablePhiGradient &(const Assembly &, libMesh::FEType)> _grad_phi_assembly_method
const ADTemplateVariablePhiGradient< OutputShape > * _ad_grad_phi
const OutputType & nodalValueDotDotOld() const
std::function< const typename OutputTools< OutputShape >::VariablePhiGradient &(const Assembly &, libMesh::FEType)> _grad_phi_face_assembly_method
const FieldVariablePhiValue * _phi_face
std::function< const typename OutputTools< OutputShape >::VariablePhiSecond &(const Assembly &, libMesh::FEType)> _second_phi_assembly_method
void fetchADDofValues()
Helper method for assigning the ad_dof* arrays.
GeometryType
Definition: MooseTypes.h:277
DofValue getNodalValue(const Node &node, Moose::SolutionState state) const
const FieldVariableCurl & curlSln(Moose::SolutionState state) const
Local solution curl getter.
C_ONE
const DofValues & dofValuesDotDot() const
const FieldVariableValue & uDotOld() const
SolutionState
Definition: MooseTypes.h:261
const libMesh::FEType & _fe_type
const ADTemplateVariablePhiGradient< OutputShape > * _ad_grad_phi_face
const FieldVariablePhiSecond & secondPhi() const
second_phi getter
const OutputType & nodalValueDotDot() const
SystemBase & _sys
The MOOSE system which ultimately holds the vectors and matrices relevant to this variable data...
IntRange< T > make_range(T beg, T end)
virtual unsigned int size() const override final
void setDofValue(const DofValue &value, unsigned int index)
dof value setters
const TimeIntegrator * queryTimeIntegrator(const unsigned int var_num) const
Retrieve the time integrator that integrates the given variable&#39;s equation.
Definition: SystemBase.C:1673
const FieldVariablePhiGradient * _grad_phi_face
void addSolution(libMesh::NumericVector< libMesh::Number > &sol, const DenseVector< libMesh::Number > &v) const
Add passed in local DOF values to a solution vector.
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N >> &derivs, libMesh::dof_id_type index, Real value)
Definition: ADReal.h:21
const FieldVariablePhiCurl & curlPhiFace() const
curl_phi_face getter
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
Definition: MooseTypes.h:147
virtual void set(const numeric_index_type i, const T value)=0
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
void setGeometry(Moose::GeometryType gm_type)
Set the geometry type before calculating variables values.
void reinitAux()
Prepare dof indices and solution values for elemental auxiliary variables.
std::function< const typename OutputTools< OutputType >::VariablePhiValue &(const Assembly &, libMesh::FEType)> _phi_assembly_method
const FieldVariablePhiDivergence & divPhiFace() const
divergence_phi_face getter
const FieldVariableSecond & secondSln(Moose::SolutionState state) const
Local solution second spatial derivative getter.
bool _is_nodal
if variable is nodal
const FieldVariablePhiGradient * _grad_phi
void insertNodalValue(libMesh::NumericVector< libMesh::Number > &residual, const DofValue &v)
Write a nodal value to the passed-in solution vector.
std::function< const typename OutputTools< OutputShape >::VariablePhiDivergence &(const Assembly &, libMesh::FEType)> _div_phi_assembly_method
const FieldVariablePhiValue * _phi
unsigned int THREAD_ID
Definition: MooseTypes.h:237
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
uint8_t dof_id_type
DofValue getElementalValue(const Elem *elem, Moose::SolutionState state, unsigned int idx=0) const