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" 27 template <
typename OutputType>
32 const QBase *
const & qrule_in,
33 const QBase *
const & qrule_face_in,
34 const Node *
const & node,
35 const Elem *
const & elem)
38 _fe_type(var.feType()),
39 _var_num(var.number()),
40 _assembly(_subproblem.assembly(_tid, var.kind() ==
Moose::
VAR_SOLVER ? sys.number() : 0)),
41 _element_type(element_type),
43 _need_ad_u_dot(false),
44 _need_ad_u_dotdot(false),
46 _need_second_old(false),
47 _need_second_older(false),
48 _need_second_previous_nl(false),
50 _need_curl_old(false),
51 _need_curl_older(false),
54 _need_div_older(false),
57 _need_ad_grad_u(false),
58 _need_ad_grad_u_dot(false),
59 _need_ad_second_u(false),
60 _need_ad_curl_u(false),
61 _has_dof_indices(false),
63 _qrule_face(qrule_face_in),
64 _use_dual(var.useDual()),
65 _second_phi_assembly_method(nullptr),
66 _second_phi_face_assembly_method(nullptr),
67 _curl_phi_assembly_method(nullptr),
68 _curl_phi_face_assembly_method(nullptr),
69 _div_phi_assembly_method(nullptr),
70 _div_phi_face_assembly_method(nullptr),
71 _ad_grad_phi_assembly_method(nullptr),
72 _ad_grad_phi_face_assembly_method(nullptr),
73 _time_integrator(nullptr),
76 _displaced(dynamic_cast<const
DisplacedSystem *>(&_sys) ? true : false),
77 _current_side(_assembly.side())
86 const auto old_do = ADReal::do_derivatives;
87 ADReal::do_derivatives =
true;
89 ADReal::do_derivatives = old_do;
157 template <
typename OutputType>
165 _current_qrule = _qrule;
167 _current_grad_phi = _grad_phi;
168 _current_second_phi = _second_phi;
169 _current_curl_phi = _curl_phi;
170 _current_div_phi = _div_phi;
171 _current_ad_grad_phi = _ad_grad_phi;
176 _current_qrule = _qrule_face;
177 _current_phi = _phi_face;
178 _current_grad_phi = _grad_phi_face;
179 _current_second_phi = _second_phi_face;
180 _current_curl_phi = _curl_phi_face;
181 _current_div_phi = _div_phi_face;
182 _current_ad_grad_phi = _ad_grad_phi_face;
188 template <
typename OutputType>
192 if (_sys.solutionUDot())
198 mooseError(
"MooseVariableFE: Time derivative of solution (`u_dot`) is not stored. Please set " 199 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
202 template <
typename OutputType>
206 if (_sys.solutionUDotDot())
208 _need_u_dotdot =
true;
212 mooseError(
"MooseVariableFE: Second time derivative of solution (`u_dotdot`) is not stored. " 213 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 217 template <
typename OutputType>
221 if (_sys.solutionUDotOld())
223 _need_u_dot_old =
true;
227 mooseError(
"MooseVariableFE: Old time derivative of solution (`u_dot_old`) is not stored. " 228 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 232 template <
typename OutputType>
236 if (_sys.solutionUDotDotOld())
238 _need_u_dotdot_old =
true;
239 return _u_dotdot_old;
242 mooseError(
"MooseVariableFE: Old second time derivative of solution (`u_dotdot_old`) is not " 243 "stored. Please set uDotDotOldRequested() to true in FEProblemBase before " 244 "requesting `u_dotdot_old`");
247 template <
typename OutputType>
251 if (_sys.solutionUDot())
253 _need_grad_dot =
true;
257 mooseError(
"MooseVariableFE: Time derivative of solution (`u_dot`) is not stored. Please set " 258 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
261 template <
typename OutputType>
265 if (_sys.solutionUDotDot())
267 _need_grad_dotdot =
true;
268 return _grad_u_dotdot;
271 mooseError(
"MooseVariableFE: Second time derivative of solution (`u_dotdot`) is not stored. " 272 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 276 template <
typename OutputType>
292 _need_second_old =
true;
293 return _second_u_old;
298 _need_second_older =
true;
299 return _second_u_older;
304 _need_second_previous_nl =
true;
305 return _second_u_previous_nl;
315 template <
typename OutputType>
331 _need_curl_old =
true;
337 _need_curl_older =
true;
338 return _curl_u_older;
342 mooseError(
"We don't currently support curl from the previous non-linear iteration");
346 template <
typename OutputType>
362 _need_div_old =
true;
368 _need_div_older =
true;
373 mooseError(
"We don't currently support divergence from the previous non-linear iteration");
377 template <
typename OutputType>
381 _second_phi = &_second_phi_assembly_method(_assembly, _fe_type);
385 template <
typename OutputType>
389 _second_phi_face = &_second_phi_face_assembly_method(_assembly, _fe_type);
390 return *_second_phi_face;
393 template <
typename OutputType>
397 _curl_phi = &_curl_phi_assembly_method(_assembly, _fe_type);
401 template <
typename OutputType>
405 _curl_phi_face = &_curl_phi_face_assembly_method(_assembly, _fe_type);
406 return *_curl_phi_face;
409 template <
typename OutputType>
413 _div_phi = &_div_phi_assembly_method(_assembly, _fe_type);
417 template <
typename OutputType>
421 _div_phi_face = &_div_phi_face_assembly_method(_assembly, _fe_type);
422 return *_div_phi_face;
425 template <
typename OutputType>
426 template <
bool monomial>
430 const auto num_dofs = _dof_indices.size();
434 const bool is_transient = _subproblem.isTransient();
435 const auto nqp = _current_qrule->n_points();
436 auto && active_coupleable_matrix_tags = _subproblem.getActiveFEVariableCoupleableMatrixTags(_tid);
439 if constexpr (std::is_same_v<OutputType, RealEigenVector>)
441 if (_qrule == _current_qrule)
443 _mapped_grad_phi.resize(num_dofs);
446 _mapped_grad_phi[i].resize(nqp, Eigen::Map<RealDIMValue>(
nullptr));
449 new (&_mapped_grad_phi[i][qp])
450 Eigen::Map<RealDIMValue>(const_cast<Real *>(&(*_current_grad_phi)[i][qp](0)));
455 _mapped_grad_phi_face.resize(num_dofs);
458 _mapped_grad_phi_face[i].resize(nqp, Eigen::Map<RealDIMValue>(
nullptr));
461 new (&_mapped_grad_phi_face[i][qp])
462 Eigen::Map<RealDIMValue>(const_cast<Real *>(&(*_current_grad_phi)[i][qp](0)));
468 !(_need_second || _need_second_old || _need_second_older || _need_second_previous_nl) ||
470 "We're requiring a second calculation but have not set a second shape function!");
471 mooseAssert(!(_need_curl || _need_curl_old) || _current_curl_phi,
472 "We're requiring a curl calculation but have not set a curl shape function!");
473 mooseAssert(!(_need_div || _need_div_old) || _current_div_phi,
474 "We're requiring a divergence calculation but have not set a div shape function!");
477 const auto fill = [
this, nqp, num_dofs](
auto & dest,
const auto & phi,
const auto & dof_values)
479 if constexpr (monomial)
483 constexpr
bool is_real = std::is_same_v<OutputType, Real>;
484 constexpr
bool is_real_vector = std::is_same_v<OutputType, RealVectorValue>;
485 constexpr
bool is_eigen = std::is_same_v<OutputType, RealEigenVector>;
486 static_assert(is_real || is_real_vector || is_eigen,
"Unsupported type");
489 if constexpr (!is_eigen)
493 using dest_array_type =
typename std::remove_reference_t<decltype(dest)>::value_type;
494 constexpr
bool is_value = std::is_same_v<dest_array_type, OutputType>;
495 constexpr
bool is_gradient = std::is_same_v<dest_array_type, OutputGradient>;
496 constexpr
bool is_second = std::is_same_v<dest_array_type, OutputSecond>;
497 constexpr
bool is_divergence = std::is_same_v<dest_array_type, OutputDivergence>;
498 static_assert(is_value || is_gradient || is_second || is_divergence,
499 "Unsupported destination array type");
502 const auto set_zero = [
this, &dest](
const auto qp)
504 if constexpr (!is_eigen)
507 if constexpr (is_real || is_real_vector)
509 else if constexpr (is_eigen)
511 if constexpr (is_value)
512 dest[qp].setZero(this->_count);
513 else if constexpr (is_gradient)
514 dest[qp].setZero(this->_count, LIBMESH_DIM);
515 else if constexpr (is_second)
516 dest[qp].setZero(this->_count, LIBMESH_DIM * LIBMESH_DIM);
518 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
521 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
525 const auto accumulate = [&dest, &phi, &dof_values](
const auto i,
const auto qp)
527 if constexpr (is_real || is_real_vector || (is_eigen && is_value))
529 if constexpr (is_value || is_divergence)
530 dest[qp] += phi[i][qp] * dof_values[i];
531 else if constexpr (is_gradient || is_second)
532 dest[qp].add_scaled(phi[i][qp], dof_values[i]);
534 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
536 else if constexpr (is_eigen)
538 if constexpr (is_gradient)
541 dest[qp].col(d) += phi[i][qp](d) * dof_values[i];
543 else if constexpr (is_second)
545 for (
unsigned int d = 0, d1 = 0; d1 < LIBMESH_DIM; ++d1)
547 dest[qp].col(d++) += phi[i][qp](d1, d2) * dof_values[i];
550 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
553 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
559 if constexpr (monomial)
561 mooseAssert(num_dofs == 1,
"Should have only one dof");
564 for (
unsigned int qp = 1; qp < nqp; ++qp)
580 fill(_curl_u, *_current_curl_phi, _vector_tags_dof_u[_solution_tag]);
581 if (is_transient && _need_curl_old)
582 fill(_curl_u_old, *_current_curl_phi, _vector_tags_dof_u[_old_solution_tag]);
586 fill(_div_u, *_current_div_phi, _vector_tags_dof_u[_solution_tag]);
587 if (is_transient && _need_div_old)
588 fill(_div_u_old, *_current_div_phi, _vector_tags_dof_u[_old_solution_tag]);
592 fill(_second_u, *_current_second_phi, _vector_tags_dof_u[_solution_tag]);
593 if (_need_second_previous_nl)
595 _second_u_previous_nl, *_current_second_phi, _vector_tags_dof_u[_previous_nl_solution_tag]);
598 for (
auto tag : _required_vector_tags)
600 if (_need_vector_tag_u[tag] && _sys.hasVector(tag))
602 mooseAssert(_sys.getVector(tag).closed(),
"Vector should be closed");
603 fill(_vector_tag_u[tag], *_current_phi, _vector_tags_dof_u[tag]);
605 if (_need_vector_tag_grad[tag] && _sys.hasVector(tag))
607 mooseAssert(_sys.getVector(tag).closed(),
"Vector should be closed");
608 fill(_vector_tag_grad[tag], *_current_grad_phi, _vector_tags_dof_u[tag]);
613 for (
auto tag : active_coupleable_matrix_tags)
614 if (_need_matrix_tag_u[tag])
615 fill(_matrix_tag_u[tag], *_current_phi, _matrix_tags_dof_u[tag]);
620 if (_need_second_old)
621 fill(_second_u_old, *_current_second_phi, _vector_tags_dof_u[_old_solution_tag]);
622 if (_need_second_older)
623 fill(_second_u_older, *_current_second_phi, _vector_tags_dof_u[_older_solution_tag]);
625 fill(_u_dot, *_current_phi, _dof_values_dot);
627 fill(_u_dotdot, *_current_phi, _dof_values_dotdot);
629 fill(_u_dot_old, *_current_phi, _dof_values_dot_old);
630 if (_need_u_dotdot_old)
631 fill(_u_dotdot_old, *_current_phi, _dof_values_dotdot_old);
635 _du_dot_du.resize(nqp);
638 _du_dot_du[qp] = _dof_du_dot_du[i];
640 if (_need_du_dotdot_du)
642 _du_dotdot_du.resize(nqp);
645 _du_dotdot_du[qp] = _dof_du_dotdot_du[i];
649 fill(_grad_u_dot, *_current_grad_phi, _dof_values_dot);
650 if (_need_grad_dotdot)
651 fill(_grad_u_dotdot, *_current_grad_phi, _dof_values_dotdot);
655 if constexpr (!std::is_same_v<OutputType, RealEigenVector>)
657 computeAD(num_dofs, nqp);
660 template <
typename OutputType>
664 computeValuesInternal<
false>();
667 template <
typename OutputType>
671 if (_dof_indices.size() == 0)
675 if (_elem->p_level())
678 computeValuesInternal<
true>();
681 template <
typename OutputType>
687 _ad_dof_values.resize(num_dofs);
689 _ad_dof_values[i] = _vector_tags_dof_u[_solution_tag][i];
699 _ad_u[qp] = _ad_zero;
703 _ad_u[qp] += _ad_dof_values[i] * (*_current_phi)[i][qp];
708 _ad_grad_u.resize(nqp);
710 _ad_grad_u[qp] = _ad_zero;
715 if (_displaced && _current_ad_grad_phi)
718 _ad_grad_u[qp] += _ad_dof_values[i] * (*_current_ad_grad_phi)[i][qp];
722 _ad_grad_u[qp] += _ad_dof_values[i] * (*_current_grad_phi)[i][qp];
725 if (_need_ad_second_u)
727 _ad_second_u.resize(nqp);
729 _ad_second_u[qp] = _ad_zero;
735 _ad_second_u[qp] += _ad_dof_values[i] * (*_current_second_phi)[i][qp];
740 _ad_curl_u.resize(nqp);
742 _ad_curl_u[qp] = _ad_zero;
747 mooseAssert(_current_curl_phi,
748 "We're requiring a curl calculation but have not set a curl shape function!");
751 _ad_curl_u[qp] += _ad_dof_values[i] * (*_current_curl_phi)[i][qp];
755 bool is_transient = _subproblem.isTransient();
760 _ad_dofs_dot.resize(num_dofs);
761 if (_need_ad_u_dotdot)
762 _ad_dofs_dotdot.resize(num_dofs);
763 _ad_u_dot.resize(nqp);
765 if (_time_integrator && _time_integrator->dt())
768 _ad_dofs_dot[i] = _ad_dof_values[i];
770 _time_integrator->computeADTimeDerivatives(_ad_dofs_dot[i],
772 _need_ad_u_dotdot ? _ad_dofs_dotdot[i]
776 _ad_u_dot[qp] = _ad_zero;
779 _ad_u_dot[qp] += (*_current_phi)[i][qp] * _ad_dofs_dot[i];
783 else if (!_time_integrator)
786 _ad_dofs_dot[i] = _dof_values_dot[i];
788 _ad_u_dot[qp] = _u_dot[qp];
792 if (_need_ad_u_dotdot)
794 _ad_u_dotdot.resize(nqp);
796 _ad_u_dotdot[qp] = _ad_zero;
798 if (_time_integrator && _time_integrator->dt())
801 _ad_u_dotdot[qp] += (*_current_phi)[i][qp] * _ad_dofs_dotdot[i];
802 else if (!_time_integrator)
804 _ad_u_dotdot[qp] = _u_dotdot[qp];
807 if (_need_ad_grad_u_dot)
809 _ad_grad_u_dot.resize(nqp);
811 if (_time_integrator && _time_integrator->dt())
814 _ad_grad_u_dot[qp] = _ad_zero;
819 if (_displaced && _current_ad_grad_phi)
822 _ad_grad_u_dot[qp] += _ad_dofs_dot[i] * (*_current_ad_grad_phi)[i][qp];
826 _ad_grad_u_dot[qp] += _ad_dofs_dot[i] * (*_current_grad_phi)[i][qp];
828 else if (!_time_integrator)
830 _ad_grad_u_dot[qp] = _grad_u_dot[qp];
840 mooseError(
"AD for array variable has not been implemented");
843 template <
typename OutputType>
847 auto & dof_values = _vector_tags_dof_u[_solution_tag];
848 dof_values[index] =
value;
849 _has_dof_values =
true;
851 auto & u = _vector_tag_u[_solution_tag];
852 const auto nqps = u.size();
853 const auto ndofs = dof_values.size();
858 u[qp] += (*_phi)[i][qp] * dof_values[i];
861 template <
typename OutputType>
865 auto & dof_values = _vector_tags_dof_u[_solution_tag];
866 for (
unsigned int i = 0; i < values.
size(); i++)
867 dof_values[i] = values(i);
869 _has_dof_values =
true;
871 auto & u = _vector_tag_u[_solution_tag];
872 const auto nqps = u.
size();
873 const auto ndofs = dof_values.size();
878 u[qp] += (*_phi)[i][qp] * dof_values[i];
881 template <
typename OutputType>
886 residual.
set(_nodal_dof_index, v);
895 residual.
set(_nodal_dof_index + j, v(j));
898 template <
typename OutputType>
902 mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)),
"Node is not Semilocal");
907 mooseAssert(node.
n_dofs(_sys.number(), _var_num) > 0,
908 "Node " << node.
id() <<
" does not contain any dofs for the " 909 << _sys.system().variable_name(_var_num) <<
" variable");
916 return (*_sys.currentSolution())(dof);
919 return _sys.solutionOld()(dof);
922 return _sys.solutionOlder()(dof);
925 mooseError(
"PreviousNL not currently supported for getNodalValue");
934 mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)),
"Node is not Semilocal");
939 mooseAssert(node.
n_dofs(_sys.number(), _var_num) > 0,
940 "Node " << node.
id() <<
" does not contain any dofs for the " 941 << _sys.system().variable_name(_var_num) <<
" variable");
949 for (
unsigned int i = 0; i < _count; ++i)
950 v(i) = (*_sys.currentSolution())(dof++);
954 for (
unsigned int i = 0; i < _count; ++i)
955 v(i) = _sys.solutionOld()(dof++);
959 for (
unsigned int i = 0; i < _count; ++i)
960 v(i) = _sys.solutionOlder()(dof++);
964 mooseError(
"PreviousNL not currently supported for getNodalValue");
969 template <
typename OutputType>
973 unsigned int idx)
const 975 std::vector<dof_id_type> dof_indices;
976 _dof_map.dof_indices(elem, dof_indices, _var_num);
981 return (*_sys.currentSolution())(dof_indices[
idx]);
984 return _sys.solutionOld()(dof_indices[
idx]);
987 return _sys.solutionOlder()(dof_indices[
idx]);
990 mooseError(
"PreviousNL not currently supported for getElementalValue");
998 unsigned int idx)
const 1000 std::vector<dof_id_type> dof_indices;
1001 _dof_map.dof_indices(elem, dof_indices, _var_num);
1010 for (
unsigned int i = 0; i < _count; ++i)
1011 v(i) = (*_sys.currentSolution())(dof++);
1015 for (
unsigned int i = 0; i < _count; ++i)
1016 v(i) = _sys.solutionOld()(dof++);
1020 for (
unsigned int i = 0; i < _count; ++i)
1021 v(i) = _sys.solutionOlder()(dof++);
1025 mooseError(
"PreviousNL not currently supported for getElementalValue");
1030 template <
typename OutputType>
1033 std::vector<dof_id_type> & dof_indices)
const 1035 _dof_map.dof_indices(elem, dof_indices, _var_num);
1038 template <
typename OutputType>
1052 const auto num_dofs = _dof_indices.size();
1055 unsigned int inc = (isNodal() ? j : j * num_dofs);
1057 sol.
add(_dof_indices[i] + inc, v(p++));
1061 template <
typename OutputType>
1065 if (_sys.solutionUDot())
1067 _need_dof_values_dot =
true;
1068 return _dof_values_dot;
1071 mooseError(
"MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set " 1072 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1075 template <
typename OutputType>
1079 if (_sys.solutionUDotDot())
1081 _need_dof_values_dotdot =
true;
1082 return _dof_values_dotdot;
1085 mooseError(
"MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. " 1086 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 1090 template <
typename OutputType>
1094 if (_sys.solutionUDotOld())
1096 _need_dof_values_dot_old =
true;
1097 return _dof_values_dot_old;
1100 mooseError(
"MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. " 1101 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 1105 template <
typename OutputType>
1109 if (_sys.solutionUDotDotOld())
1111 _need_dof_values_dotdot_old =
true;
1112 return _dof_values_dotdot_old;
1115 mooseError(
"MooseVariableData: Old second time derivative of solution (`u_dotdot_old`) is not " 1116 "stored. Please set uDotDotOldRequested() to true in FEProblemBase before " 1117 "requesting `u_dotdot_old`.");
1120 template <
typename OutputType>
1124 _need_dof_du_dot_du =
true;
1125 return _dof_du_dot_du;
1128 template <
typename OutputType>
1132 _need_dof_du_dotdot_du =
true;
1133 return _dof_du_dotdot_du;
1136 template <
typename OutputType>
1140 unsigned int nqp = _qrule->n_points();
1142 _increment.resize(nqp);
1144 unsigned int num_dofs = _dof_indices.size();
1147 _increment[qp] = 0.;
1149 _increment[qp] += (*_phi)[i][qp] * increment_vec(_dof_indices[i]);
1158 unsigned int nqp = _qrule->n_points();
1160 _increment.resize(nqp);
1162 unsigned int num_dofs = _dof_indices.size();
1169 _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + j);
1180 _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + n);
1187 template <
typename OutputType>
1192 mooseError(
"computeIncrementAtNode can only be called for nodal variables");
1194 _increment.resize(1);
1197 _increment[0] = increment_vec(_dof_indices[0]);
1206 mooseError(
"computeIncrementAtNode can only be called for nodal variables");
1208 _increment.resize(1);
1212 for (
unsigned int j = 0; j < _count; j++)
1213 _increment[0](j) = increment_vec(_dof_indices[0] + j);
1217 const auto n_dof_indices = _dof_indices.size();
1220 _increment[0](j) = increment_vec(_dof_indices[0] + n);
1226 template <
typename OutputType>
1232 if (_sys.solutionUDot())
1234 _need_dof_values_dot =
true;
1235 return _nodal_value_dot;
1239 "MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set " 1240 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1243 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1248 template <
typename OutputType>
1254 if (_sys.solutionUDotDot())
1256 _need_dof_values_dotdot =
true;
1257 return _nodal_value_dotdot;
1261 "MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. " 1262 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 1266 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1271 template <
typename OutputType>
1277 if (_sys.solutionUDotOld())
1279 _need_dof_values_dot_old =
true;
1280 return _nodal_value_dot_old;
1283 mooseError(
"MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. " 1284 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 1288 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1293 template <
typename OutputType>
1299 if (_sys.solutionUDotDotOld())
1301 _need_dof_values_dotdot_old =
true;
1302 return _nodal_value_dotdot_old;
1306 "MooseVariableData: Old second time derivative of solution (`u_dotdot_old`) is not " 1307 "stored. Please set uDotDotOldRequested() to true in FEProblemBase before " 1308 "requesting `u_dotdot_old`.");
1311 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1316 template <
typename OutputType>
1320 if (_has_dof_indices)
1326 fetchADNodalValues();
1329 zeroSizeDofValues();
1332 template <
typename OutputType>
1336 auto n = _dof_indices.size();
1338 _ad_dof_values.resize(n);
1341 _ad_dofs_dot.resize(n);
1342 if (_need_ad_u_dotdot)
1343 _ad_dofs_dotdot.resize(n);
1345 const bool do_derivatives =
1346 ADReal::do_derivatives && _sys.number() == _subproblem.currentNlSysNum();
1348 for (decltype(n) i = 0; i < n; ++i)
1350 _ad_dof_values[i] = _vector_tags_dof_u[_solution_tag][i];
1353 assignADNodalValue(_ad_dof_values[i], i);
1357 if (_time_integrator && _time_integrator->dt())
1359 _ad_dofs_dot[i] = _ad_dof_values[i];
1360 _time_integrator->computeADTimeDerivatives(_ad_dofs_dot[i],
1362 _need_ad_u_dotdot ? _ad_dofs_dotdot[i]
1366 else if (_time_integrator && !_time_integrator->dt())
1367 _ad_dofs_dot[i] = 0.;
1369 mooseError(
"AD nodal time derivatives not implemented for variables without a time " 1370 "integrator (auxiliary variables)");
1379 mooseError(
"I do not know how to support AD with array variables");
1386 _ad_nodal_value =
value;
1392 const unsigned int & component)
1394 _ad_nodal_value(component) =
value;
1397 template <
typename OutputType>
1401 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1402 _vector_tags_dof_u[_solution_tag].resize(_dof_indices.size());
1404 unsigned int nqp = _qrule->n_points();
1405 _vector_tag_u[_solution_tag].resize(nqp);
1408 template <
typename OutputType>
1412 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1413 _has_dof_values =
false;
1417 _has_dof_indices = _dof_indices.size();
1420 template <
typename OutputType>
1424 if (std::size_t n_dofs = _node->n_dofs(_sys.number(), _var_num))
1426 _dof_indices.resize(n_dofs);
1427 for (std::size_t i = 0; i < n_dofs; ++i)
1428 _dof_indices[i] = _node->dof_number(_sys.number(), _var_num, i);
1431 _nodal_dof_index = _dof_indices[0];
1432 _has_dof_indices =
true;
1436 _dof_indices.clear();
1437 _has_dof_indices =
false;
1441 template <
typename OutputType>
1449 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1450 if (_elem->n_dofs(_sys.number(), _var_num) > 0)
1452 _nodal_dof_index = _dof_indices[0];
1456 const auto num_dofs = _dof_indices.size();
1457 for (
auto & dof_u : _vector_tags_dof_u)
1458 dof_u.resize(num_dofs);
1460 for (
auto & dof_u : _matrix_tags_dof_u)
1461 dof_u.resize(num_dofs);
1463 _has_dof_indices =
true;
1466 _has_dof_indices =
false;
1469 _has_dof_indices =
false;
1472 template <
typename OutputType>
1476 _dof_indices.clear();
1477 for (
const auto & node_id : nodes)
1479 auto && nd = _subproblem.mesh().getMesh().query_node_ptr(node_id);
1480 if (nd && (_subproblem.mesh().isSemiLocal(const_cast<Node *>(nd))))
1482 if (nd->n_dofs(_sys.number(), _var_num) > 0)
1484 dof_id_type dof = nd->dof_number(_sys.number(), _var_num, 0);
1485 _dof_indices.push_back(dof);
1490 if (!_dof_indices.empty())
1491 _has_dof_indices =
true;
1493 _has_dof_indices =
false;
const FieldVariableDivergence & divSln(Moose::SolutionState state) const
Local solution divergence getter.
std::string name(const ElemQuality q)
const Assembly & _assembly
OutputData getNodalValue(const Node &node, Moose::SolutionState state) const
const FieldVariableValue & uDotDotOld() const
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
void computeAD(const unsigned int num_dofs, const unsigned int nqp)
compute AD things
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.
void prepare()
Get the dof indices corresponding to the current element.
Class for stuff related to variables.
void setDofValue(const OutputData &value, unsigned int index)
dof value setters
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
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
std::function< const typename OutputTools< OutputShape >::VariablePhiCurl &(const Assembly &, libMesh::FEType)> _curl_phi_assembly_method
Moose::DOFType< OutputType >::type OutputData
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.
const FieldVariableValue & uDot() const
void computeMonomialValues()
compute the values for const monomial variables
MooseVariableData(const MooseVariableField< 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 computeNodalValues()
compute nodal things
const MooseArray< libMesh::Number > & dofValuesDuDotDotDu() const
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
std::function< const ADTemplateVariablePhiGradient< OutputShape > &(const Assembly &, libMesh::FEType)> _ad_grad_phi_assembly_method
Base class for a system (of equations)
DualNumber< Real, DNDerivativeType, true > ADReal
const unsigned int _var_num
void prepareIC()
prepare the initial condition
void assignADNodalValue(const ADReal &value, const unsigned int &component)
Helper methods for assigning nodal values from their corresponding solution values (dof values as the...
const FieldVariableGradient & gradSlnDot() const
Local time derivative of solution gradient getter.
bool doDerivatives(const SubProblem &subproblem, const SystemBase &sys)
void setDofValues(const DenseVector< OutputData > &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
OutputData getElementalValue(const Elem *elem, Moose::SolutionState state, unsigned int idx=0) const
void insertNodalValue(libMesh::NumericVector< libMesh::Number > &residual, const OutputData &v)
Write a nodal value to the passed-in solution vector.
std::function< const typename OutputTools< OutputShape >::VariablePhiSecond &(const Assembly &, libMesh::FEType)> _second_phi_face_assembly_method
void libmesh_ignore(const Args &...)
const DoFValue & dofValuesDotDotOld() const
const MooseArray< libMesh::Number > & dofValuesDuDotDu() const
const DoFValue & dofValuesDot() const
const FieldVariablePhiDivergence & divPhi() const
divergence_phi getter
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void computeValuesInternal()
Internal method for computeValues() and computeMonomialValues()
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.
const FieldVariableGradient & gradSlnDotDot() const
Local second time derivative of solution gradient getter.
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.
std::function< const ADTemplateVariablePhiGradient< OutputShape > &(const Assembly &, libMesh::FEType)> _ad_grad_phi_face_assembly_method
const TimeIntegrator * _time_integrator
Pointer to time integrator.
const DoFValue & dofValuesDotDot() const
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
const FieldVariableCurl & curlSln(Moose::SolutionState state) const
Local solution curl getter.
const FieldVariableValue & uDotOld() const
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
const TimeIntegrator * queryTimeIntegrator(const unsigned int var_num) const
Retrieve the time integrator that integrates the given variable's equation.
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)
const FieldVariablePhiCurl & curlPhiFace() const
curl_phi_face getter
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
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...
const DoFValue & dofValuesDotOld() const
void fetchADNodalValues()
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.
virtual void add(const numeric_index_type i, const T value)=0
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
std::function< const typename OutputTools< OutputShape >::VariablePhiDivergence &(const Assembly &, libMesh::FEType)> _div_phi_assembly_method
const FieldVariablePhiValue * _phi