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]);
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) && _sys.getVector(tag).closed())
601 fill(_vector_tag_u[tag], *_current_phi, _vector_tags_dof_u[tag]);
602 if (_need_vector_tag_grad[tag] && _sys.hasVector(tag) && _sys.getVector(tag).closed())
603 fill(_vector_tag_grad[tag], *_current_grad_phi, _vector_tags_dof_u[tag]);
607 for (
auto tag : active_coupleable_matrix_tags)
608 if (_need_matrix_tag_u[tag])
609 fill(_matrix_tag_u[tag], *_current_phi, _matrix_tags_dof_u[tag]);
614 if (_need_second_old)
615 fill(_second_u_old, *_current_second_phi, _vector_tags_dof_u[_old_solution_tag]);
616 if (_need_second_older)
617 fill(_second_u_older, *_current_second_phi, _vector_tags_dof_u[_older_solution_tag]);
619 fill(_u_dot, *_current_phi, _dof_values_dot);
621 fill(_u_dotdot, *_current_phi, _dof_values_dotdot);
623 fill(_u_dot_old, *_current_phi, _dof_values_dot_old);
624 if (_need_u_dotdot_old)
625 fill(_u_dotdot_old, *_current_phi, _dof_values_dotdot_old);
629 _du_dot_du.resize(nqp);
634 _du_dot_du[qp] = _dof_du_dot_du[i];
636 if (_need_du_dotdot_du)
638 _du_dotdot_du.resize(nqp);
640 _du_dotdot_du[qp] = 0.;
643 _du_dotdot_du[qp] = _dof_du_dotdot_du[i];
647 fill(_grad_u_dot, *_current_grad_phi, _dof_values_dot);
648 if (_need_grad_dotdot)
649 fill(_grad_u_dotdot, *_current_grad_phi, _dof_values_dotdot);
653 if constexpr (!std::is_same_v<OutputType, RealEigenVector>)
655 computeAD(num_dofs, nqp);
658 template <
typename OutputType>
662 computeValuesInternal<
false>();
665 template <
typename OutputType>
669 if (_dof_indices.size() == 0)
673 if (_elem->p_level())
676 computeValuesInternal<
true>();
679 template <
typename OutputType>
685 _ad_dof_values.resize(num_dofs);
687 _ad_dof_values[i] = (*_sys.currentSolution())(_dof_indices[i]);
697 _ad_u[qp] = _ad_zero;
701 _ad_u[qp] += _ad_dof_values[i] * (*_current_phi)[i][qp];
706 _ad_grad_u.resize(nqp);
708 _ad_grad_u[qp] = _ad_zero;
713 if (_displaced && _current_ad_grad_phi)
716 _ad_grad_u[qp] += _ad_dof_values[i] * (*_current_ad_grad_phi)[i][qp];
720 _ad_grad_u[qp] += _ad_dof_values[i] * (*_current_grad_phi)[i][qp];
723 if (_need_ad_second_u)
725 _ad_second_u.resize(nqp);
727 _ad_second_u[qp] = _ad_zero;
733 _ad_second_u[qp] += _ad_dof_values[i] * (*_current_second_phi)[i][qp];
738 _ad_curl_u.resize(nqp);
740 _ad_curl_u[qp] = _ad_zero;
745 mooseAssert(_current_curl_phi,
746 "We're requiring a curl calculation but have not set a curl shape function!");
749 _ad_curl_u[qp] += _ad_dof_values[i] * (*_current_curl_phi)[i][qp];
753 bool is_transient = _subproblem.isTransient();
758 _ad_dofs_dot.resize(num_dofs);
759 if (_need_ad_u_dotdot)
760 _ad_dofs_dotdot.resize(num_dofs);
761 _ad_u_dot.resize(nqp);
763 _ad_u_dot[qp] = _ad_zero;
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]
777 _ad_u_dot[qp] += (*_current_phi)[i][qp] * _ad_dofs_dot[i];
779 else if (!_time_integrator)
782 _ad_dofs_dot[i] = _dof_values_dot[i];
784 _ad_u_dot[qp] = _u_dot[qp];
788 if (_need_ad_u_dotdot)
790 _ad_u_dotdot.resize(nqp);
792 _ad_u_dotdot[qp] = _ad_zero;
794 if (_time_integrator && _time_integrator->dt())
797 _ad_u_dotdot[qp] += (*_current_phi)[i][qp] * _ad_dofs_dotdot[i];
798 else if (!_time_integrator)
800 _ad_u_dotdot[qp] = _u_dotdot[qp];
803 if (_need_ad_grad_u_dot)
805 _ad_grad_u_dot.resize(nqp);
807 _ad_grad_u_dot[qp] = _ad_zero;
809 if (_time_integrator && _time_integrator->dt())
814 if (_displaced && _current_ad_grad_phi)
817 _ad_grad_u_dot[qp] += _ad_dofs_dot[i] * (*_current_ad_grad_phi)[i][qp];
821 _ad_grad_u_dot[qp] += _ad_dofs_dot[i] * (*_current_grad_phi)[i][qp];
823 else if (!_time_integrator)
825 _ad_grad_u_dot[qp] = _grad_u_dot[qp];
835 mooseError(
"AD for array variable has not been implemented");
838 template <
typename OutputType>
842 auto & dof_values = _vector_tags_dof_u[_solution_tag];
843 dof_values[index] =
value;
844 _has_dof_values =
true;
846 auto & u = _vector_tag_u[_solution_tag];
847 const auto nqps = u.size();
848 const auto ndofs = dof_values.size();
853 u[qp] += (*_phi)[i][qp] * dof_values[i];
856 template <
typename OutputType>
860 auto & dof_values = _vector_tags_dof_u[_solution_tag];
861 for (
unsigned int i = 0; i < values.
size(); i++)
862 dof_values[i] = values(i);
864 _has_dof_values =
true;
866 auto & u = _vector_tag_u[_solution_tag];
867 const auto nqps = u.
size();
868 const auto ndofs = dof_values.size();
873 u[qp] += (*_phi)[i][qp] * dof_values[i];
876 template <
typename OutputType>
881 residual.
set(_nodal_dof_index, v);
890 residual.
set(_nodal_dof_index + j, v(j));
893 template <
typename OutputType>
897 mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)),
"Node is not Semilocal");
902 mooseAssert(node.
n_dofs(_sys.number(), _var_num) > 0,
903 "Node " << node.
id() <<
" does not contain any dofs for the " 904 << _sys.system().variable_name(_var_num) <<
" variable");
911 return (*_sys.currentSolution())(dof);
914 return _sys.solutionOld()(dof);
917 return _sys.solutionOlder()(dof);
920 mooseError(
"PreviousNL not currently supported for getNodalValue");
929 mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)),
"Node is not Semilocal");
934 mooseAssert(node.
n_dofs(_sys.number(), _var_num) > 0,
935 "Node " << node.
id() <<
" does not contain any dofs for the " 936 << _sys.system().variable_name(_var_num) <<
" variable");
944 for (
unsigned int i = 0; i < _count; ++i)
945 v(i) = (*_sys.currentSolution())(dof++);
949 for (
unsigned int i = 0; i < _count; ++i)
950 v(i) = _sys.solutionOld()(dof++);
954 for (
unsigned int i = 0; i < _count; ++i)
955 v(i) = _sys.solutionOlder()(dof++);
959 mooseError(
"PreviousNL not currently supported for getNodalValue");
964 template <
typename OutputType>
968 unsigned int idx)
const 970 std::vector<dof_id_type> dof_indices;
971 _dof_map.dof_indices(elem, dof_indices, _var_num);
976 return (*_sys.currentSolution())(dof_indices[
idx]);
979 return _sys.solutionOld()(dof_indices[
idx]);
982 return _sys.solutionOlder()(dof_indices[
idx]);
985 mooseError(
"PreviousNL not currently supported for getElementalValue");
993 unsigned int idx)
const 995 std::vector<dof_id_type> dof_indices;
996 _dof_map.dof_indices(elem, dof_indices, _var_num);
1005 for (
unsigned int i = 0; i < _count; ++i)
1006 v(i) = (*_sys.currentSolution())(dof++);
1010 for (
unsigned int i = 0; i < _count; ++i)
1011 v(i) = _sys.solutionOld()(dof++);
1015 for (
unsigned int i = 0; i < _count; ++i)
1016 v(i) = _sys.solutionOlder()(dof++);
1020 mooseError(
"PreviousNL not currently supported for getElementalValue");
1025 template <
typename OutputType>
1028 std::vector<dof_id_type> & dof_indices)
const 1030 _dof_map.dof_indices(elem, dof_indices, _var_num);
1033 template <
typename OutputType>
1047 const auto num_dofs = _dof_indices.size();
1050 unsigned int inc = (isNodal() ? j : j * num_dofs);
1052 sol.
add(_dof_indices[i] + inc, v(p++));
1056 template <
typename OutputType>
1060 if (_sys.solutionUDot())
1062 _need_dof_values_dot =
true;
1063 return _dof_values_dot;
1066 mooseError(
"MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set " 1067 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1070 template <
typename OutputType>
1074 if (_sys.solutionUDotDot())
1076 _need_dof_values_dotdot =
true;
1077 return _dof_values_dotdot;
1080 mooseError(
"MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. " 1081 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 1085 template <
typename OutputType>
1089 if (_sys.solutionUDotOld())
1091 _need_dof_values_dot_old =
true;
1092 return _dof_values_dot_old;
1095 mooseError(
"MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. " 1096 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 1100 template <
typename OutputType>
1104 if (_sys.solutionUDotDotOld())
1106 _need_dof_values_dotdot_old =
true;
1107 return _dof_values_dotdot_old;
1110 mooseError(
"MooseVariableData: Old second time derivative of solution (`u_dotdot_old`) is not " 1111 "stored. Please set uDotDotOldRequested() to true in FEProblemBase before " 1112 "requesting `u_dotdot_old`.");
1115 template <
typename OutputType>
1119 _need_dof_du_dot_du =
true;
1120 return _dof_du_dot_du;
1123 template <
typename OutputType>
1127 _need_dof_du_dotdot_du =
true;
1128 return _dof_du_dotdot_du;
1131 template <
typename OutputType>
1135 unsigned int nqp = _qrule->n_points();
1137 _increment.resize(nqp);
1139 unsigned int num_dofs = _dof_indices.size();
1142 _increment[qp] = 0.;
1144 _increment[qp] += (*_phi)[i][qp] * increment_vec(_dof_indices[i]);
1153 unsigned int nqp = _qrule->n_points();
1155 _increment.resize(nqp);
1157 unsigned int num_dofs = _dof_indices.size();
1164 _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + j);
1175 _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + n);
1182 template <
typename OutputType>
1187 mooseError(
"computeIncrementAtNode can only be called for nodal variables");
1189 _increment.resize(1);
1192 _increment[0] = increment_vec(_dof_indices[0]);
1201 mooseError(
"computeIncrementAtNode can only be called for nodal variables");
1203 _increment.resize(1);
1207 for (
unsigned int j = 0; j < _count; j++)
1208 _increment[0](j) = increment_vec(_dof_indices[0] + j);
1212 const auto n_dof_indices = _dof_indices.size();
1215 _increment[0](j) = increment_vec(_dof_indices[0] + n);
1221 template <
typename OutputType>
1227 if (_sys.solutionUDot())
1229 _need_dof_values_dot =
true;
1230 return _nodal_value_dot;
1234 "MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set " 1235 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1238 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1243 template <
typename OutputType>
1249 if (_sys.solutionUDotDot())
1251 _need_dof_values_dotdot =
true;
1252 return _nodal_value_dotdot;
1256 "MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. " 1257 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 1261 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1266 template <
typename OutputType>
1272 if (_sys.solutionUDotOld())
1274 _need_dof_values_dot_old =
true;
1275 return _nodal_value_dot_old;
1278 mooseError(
"MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. " 1279 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 1283 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1288 template <
typename OutputType>
1294 if (_sys.solutionUDotDotOld())
1296 _need_dof_values_dotdot_old =
true;
1297 return _nodal_value_dotdot_old;
1301 "MooseVariableData: Old second time derivative of solution (`u_dotdot_old`) is not " 1302 "stored. Please set uDotDotOldRequested() to true in FEProblemBase before " 1303 "requesting `u_dotdot_old`.");
1306 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1311 template <
typename OutputType>
1315 if (_has_dof_indices)
1321 fetchADNodalValues();
1324 zeroSizeDofValues();
1327 template <
typename OutputType>
1331 auto n = _dof_indices.size();
1333 _ad_dof_values.resize(n);
1336 _ad_dofs_dot.resize(n);
1337 if (_need_ad_u_dotdot)
1338 _ad_dofs_dotdot.resize(n);
1340 const bool do_derivatives =
1341 ADReal::do_derivatives && _sys.number() == _subproblem.currentNlSysNum();
1343 for (decltype(n) i = 0; i < n; ++i)
1345 _ad_dof_values[i] = _vector_tags_dof_u[_solution_tag][i];
1348 assignADNodalValue(_ad_dof_values[i], i);
1352 if (_time_integrator && _time_integrator->dt())
1354 _ad_dofs_dot[i] = _ad_dof_values[i];
1355 _time_integrator->computeADTimeDerivatives(_ad_dofs_dot[i],
1357 _need_ad_u_dotdot ? _ad_dofs_dotdot[i]
1361 else if (_time_integrator && !_time_integrator->dt())
1362 _ad_dofs_dot[i] = 0.;
1364 mooseError(
"AD nodal time derivatives not implemented for variables without a time " 1365 "integrator (auxiliary variables)");
1374 mooseError(
"I do not know how to support AD with array variables");
1381 _ad_nodal_value =
value;
1387 const unsigned int & component)
1389 _ad_nodal_value(component) =
value;
1392 template <
typename OutputType>
1396 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1397 _vector_tags_dof_u[_solution_tag].resize(_dof_indices.size());
1399 unsigned int nqp = _qrule->n_points();
1400 _vector_tag_u[_solution_tag].resize(nqp);
1403 template <
typename OutputType>
1407 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1408 _has_dof_values =
false;
1412 _has_dof_indices = _dof_indices.size();
1415 template <
typename OutputType>
1419 if (std::size_t n_dofs = _node->n_dofs(_sys.number(), _var_num))
1421 _dof_indices.resize(n_dofs);
1422 for (std::size_t i = 0; i < n_dofs; ++i)
1423 _dof_indices[i] = _node->dof_number(_sys.number(), _var_num, i);
1426 _nodal_dof_index = _dof_indices[0];
1427 _has_dof_indices =
true;
1431 _dof_indices.clear();
1432 _has_dof_indices =
false;
1436 template <
typename OutputType>
1444 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1445 if (_elem->n_dofs(_sys.number(), _var_num) > 0)
1448 _nodal_dof_index = _elem->dof_number(_sys.number(), _var_num, 0);
1452 const auto num_dofs = _dof_indices.size();
1453 for (
auto & dof_u : _vector_tags_dof_u)
1454 dof_u.resize(num_dofs);
1456 for (
auto & dof_u : _matrix_tags_dof_u)
1457 dof_u.resize(num_dofs);
1459 _has_dof_indices =
true;
1462 _has_dof_indices =
false;
1465 _has_dof_indices =
false;
1468 template <
typename OutputType>
1472 _dof_indices.clear();
1473 for (
const auto & node_id : nodes)
1475 auto && nd = _subproblem.mesh().getMesh().query_node_ptr(node_id);
1476 if (nd && (_subproblem.mesh().isSemiLocal(const_cast<Node *>(nd))))
1478 if (nd->n_dofs(_sys.number(), _var_num) > 0)
1480 dof_id_type dof = nd->dof_number(_sys.number(), _var_num, 0);
1481 _dof_indices.push_back(dof);
1486 if (!_dof_indices.empty())
1487 _has_dof_indices =
true;
1489 _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