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)
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),
44 _has_dof_indices(false),
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),
59 _displaced(dynamic_cast<const
DisplacedSystem *>(&_sys) ? true : false),
60 _current_side(_assembly.side())
69 const auto old_do = ADReal::do_derivatives;
70 ADReal::do_derivatives =
true;
72 ADReal::do_derivatives = old_do;
140 template <
typename OutputType>
148 _current_qrule = _qrule;
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;
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;
171 template <
typename OutputType>
175 if (_sys.solutionUDot())
181 mooseError(
"MooseVariableFE: Time derivative of solution (`u_dot`) is not stored. Please set " 182 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
185 template <
typename OutputType>
189 if (_sys.solutionUDotDot())
191 _need_u_dotdot =
true;
195 mooseError(
"MooseVariableFE: Second time derivative of solution (`u_dotdot`) is not stored. " 196 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 200 template <
typename OutputType>
204 if (_sys.solutionUDotOld())
206 _need_u_dot_old =
true;
210 mooseError(
"MooseVariableFE: Old time derivative of solution (`u_dot_old`) is not stored. " 211 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 215 template <
typename OutputType>
219 if (_sys.solutionUDotDotOld())
221 _need_u_dotdot_old =
true;
222 return _u_dotdot_old;
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`");
230 template <
typename OutputType>
234 if (_sys.solutionUDot())
236 _need_grad_dot =
true;
240 mooseError(
"MooseVariableFE: Time derivative of solution (`u_dot`) is not stored. Please set " 241 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
244 template <
typename OutputType>
248 if (_sys.solutionUDotDot())
250 _need_grad_dotdot =
true;
251 return _grad_u_dotdot;
254 mooseError(
"MooseVariableFE: Second time derivative of solution (`u_dotdot`) is not stored. " 255 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 259 template <
typename OutputType>
275 _need_second_old =
true;
276 return _second_u_old;
281 _need_second_older =
true;
282 return _second_u_older;
287 _need_second_previous_nl =
true;
288 return _second_u_previous_nl;
298 template <
typename OutputType>
314 _need_curl_old =
true;
320 _need_curl_older =
true;
321 return _curl_u_older;
325 mooseError(
"We don't currently support curl from the previous non-linear iteration");
329 template <
typename OutputType>
345 _need_div_old =
true;
351 _need_div_older =
true;
356 mooseError(
"We don't currently support divergence from the previous non-linear iteration");
360 template <
typename OutputType>
364 _second_phi = &_second_phi_assembly_method(_assembly, _fe_type);
368 template <
typename OutputType>
372 _second_phi_face = &_second_phi_face_assembly_method(_assembly, _fe_type);
373 return *_second_phi_face;
376 template <
typename OutputType>
380 _curl_phi = &_curl_phi_assembly_method(_assembly, _fe_type);
384 template <
typename OutputType>
388 _curl_phi_face = &_curl_phi_face_assembly_method(_assembly, _fe_type);
389 return *_curl_phi_face;
392 template <
typename OutputType>
396 _div_phi = &_div_phi_assembly_method(_assembly, _fe_type);
400 template <
typename OutputType>
404 _div_phi_face = &_div_phi_face_assembly_method(_assembly, _fe_type);
405 return *_div_phi_face;
408 template <
typename OutputType>
409 template <
bool constant_monomial,
410 typename DestinationType,
412 typename DofValuesType>
416 const DofValuesType & dof_values,
417 const unsigned int nqp,
418 const std::size_t num_shapes)
420 if constexpr (constant_monomial)
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");
430 if constexpr (!is_eigen)
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");
451 const auto set_zero = [
this, &dest](
const auto qp)
453 if constexpr (!is_eigen)
456 if constexpr (is_real || is_real_vector)
458 else if constexpr (is_eigen)
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);
467 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
470 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
474 const auto accumulate = [&dest, &phi, &dof_values](
const auto i,
const auto qp)
476 if constexpr (is_real || is_real_vector || (is_eigen && is_value))
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]);
483 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
485 else if constexpr (is_eigen)
487 if constexpr (is_gradient)
490 dest[qp].col(d) += phi[i][qp](d) * dof_values[i];
492 else if constexpr (is_second)
494 for (
unsigned int d = 0, d1 = 0; d1 < LIBMESH_DIM; ++d1)
496 dest[qp].col(d++) += phi[i][qp](d1, d2) * dof_values[i];
499 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
502 static_assert(Moose::always_false<OutputType, dest_array_type>,
"Unsupported type");
508 if constexpr (constant_monomial)
510 mooseAssert(num_shapes == 1,
"Should have only one shape function for a constant monomial");
513 for (
unsigned int qp = 1; qp < nqp; ++qp)
527 template <
typename OutputType>
528 template <
bool constant_monomial>
532 const auto num_dofs = _dof_indices.size();
533 const auto num_shapes = num_dofs / _count;
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);
544 if constexpr (std::is_same_v<OutputType, RealEigenVector>)
546 if (_qrule == _current_qrule)
548 _mapped_grad_phi.resize(num_shapes);
551 _mapped_grad_phi[i].resize(nqp, Eigen::Map<RealDIMValue>(
nullptr));
554 new (&_mapped_grad_phi[i][qp])
555 Eigen::Map<RealDIMValue>(const_cast<Real *>(&(*_current_grad_phi)[i][qp](0)));
560 _mapped_grad_phi_face.resize(num_shapes);
563 _mapped_grad_phi_face[i].resize(nqp, Eigen::Map<RealDIMValue>(
nullptr));
566 new (&_mapped_grad_phi_face[i][qp])
567 Eigen::Map<RealDIMValue>(const_cast<Real *>(&(*_current_grad_phi)[i][qp](0)));
573 !(_need_second || _need_second_old || _need_second_older || _need_second_previous_nl) ||
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!");
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);
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);
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],
609 for (
auto tag : _required_vector_tags)
611 if (_need_vector_tag_u[tag] && _sys.hasVector(tag))
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);
617 if (_need_vector_tag_grad[tag] && _sys.hasVector(tag))
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);
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);
634 if (_need_second_old)
635 fill<constant_monomial>(_second_u_old,
636 *_current_second_phi,
637 _vector_tags_dof_u[_old_solution_tag],
640 if (_need_second_older)
641 fill<constant_monomial>(_second_u_older,
642 *_current_second_phi,
643 _vector_tags_dof_u[_older_solution_tag],
647 fill<constant_monomial>(_u_dot, *_current_phi, _dof_values_dot, nqp, num_shapes);
649 fill<constant_monomial>(_u_dotdot, *_current_phi, _dof_values_dotdot, nqp, num_shapes);
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);
658 _du_dot_du.resize(nqp);
661 _du_dot_du[qp] = _dof_du_dot_du[i];
663 if (_need_du_dotdot_du)
665 _du_dotdot_du.resize(nqp);
668 _du_dotdot_du[qp] = _dof_du_dotdot_du[i];
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);
679 computeAD<constant_monomial>(num_dofs, nqp);
682 template <
typename OutputType>
686 computeValuesInternal<
false>();
689 template <
typename OutputType>
693 if (_dof_indices.size() == 0)
697 if (_elem->p_level())
700 computeValuesInternal<
true>();
703 template <
typename OutputType>
707 const auto num_dofs = _dof_indices.size();
711 _ad_dof_values.resize(num_dofs);
713 _ad_dof_values[i] = _vector_tags_dof_u[_solution_tag][i];
719 const bool is_transient = _subproblem.isTransient();
720 if (is_transient && _need_ad_u_dot)
722 _ad_dofs_dot.resize(num_dofs);
723 if (_need_ad_u_dotdot)
724 _ad_dofs_dotdot.resize(num_dofs);
726 if (_time_integrator)
728 if (_time_integrator->dt())
731 _ad_dofs_dot[i] = _ad_dof_values[i];
733 _time_integrator->computeADTimeDerivatives(_ad_dofs_dot[i],
735 _need_ad_u_dotdot ? _ad_dofs_dotdot[i]
742 _ad_dofs_dot[i] = 0.;
743 if (_need_ad_u_dotdot)
744 _ad_dofs_dotdot[i] = 0;
752 _ad_dofs_dot[i] = _dof_values_dot[i];
753 if (_need_ad_u_dotdot)
754 _ad_dofs_dotdot[i] = _dof_values_dotdot[i];
763 const auto num_dofs = _dof_indices.size();
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");
770 _ad_dof_values.resize(n_test);
774 _ad_dof_values[i].resize(_count);
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);
787 template <
typename OutputType>
788 template <
bool constant_monomial>
793 const auto n_test = num_dofs / _count;
797 fill<constant_monomial>(_ad_u, *_current_phi, _ad_dof_values, nqp, n_test);
804 if (_displaced && _current_ad_grad_phi)
805 fill<constant_monomial>(_ad_grad_u, *_current_ad_grad_phi, _ad_dof_values, nqp, n_test);
807 fill<constant_monomial>(_ad_grad_u, *_current_grad_phi, _ad_dof_values, nqp, n_test);
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);
815 fill<constant_monomial>(_ad_curl_u, *_current_curl_phi, _ad_dof_values, nqp, n_test);
817 const bool is_transient = _subproblem.isTransient();
822 if (_time_integrator)
823 fill<constant_monomial>(_ad_u_dot, *_current_phi, _ad_dofs_dot, nqp, n_test);
828 _ad_u_dot.resize(nqp);
830 _ad_u_dot[qp] = _u_dot[qp];
834 if (_need_ad_u_dotdot)
836 if (_time_integrator)
837 fill<constant_monomial>(_ad_u_dotdot, *_current_phi, _ad_dofs_dotdot, nqp, n_test);
840 _ad_u_dotdot.resize(nqp);
842 _ad_u_dotdot[qp] = _u_dotdot[qp];
846 if (_need_ad_grad_u_dot)
848 if (_time_integrator)
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);
856 fill<constant_monomial>(_ad_grad_u_dot, *_current_grad_phi, _ad_dofs_dot, nqp, n_test);
860 _ad_grad_u_dot.resize(nqp);
862 _ad_grad_u_dot[qp] = _grad_u_dot[qp];
868 template <
typename OutputType>
872 auto & dof_values = _vector_tags_dof_u[_solution_tag];
873 dof_values[index] =
value;
874 _has_dof_values =
true;
876 auto & u = _vector_tag_u[_solution_tag];
877 const auto nqps = u.size();
878 const auto ndofs = dof_values.size();
883 u[qp] += (*_phi)[i][qp] * dof_values[i];
886 template <
typename OutputType>
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);
894 _has_dof_values =
true;
896 auto & u = _vector_tag_u[_solution_tag];
897 const auto nqps = u.
size();
898 const auto ndofs = dof_values.size();
903 u[qp] += (*_phi)[i][qp] * dof_values[i];
906 template <
typename OutputType>
911 residual.
set(_nodal_dof_index, v);
920 residual.
set(_nodal_dof_index + j, v(j));
923 template <
typename OutputType>
927 mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)),
"Node is not Semilocal");
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");
941 return (*_sys.currentSolution())(dof);
944 return _sys.solutionOld()(dof);
947 return _sys.solutionOlder()(dof);
950 mooseError(
"PreviousNL not currently supported for getNodalValue");
959 mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)),
"Node is not Semilocal");
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");
974 for (
unsigned int i = 0; i < _count; ++i)
975 v(i) = (*_sys.currentSolution())(dof++);
979 for (
unsigned int i = 0; i < _count; ++i)
980 v(i) = _sys.solutionOld()(dof++);
984 for (
unsigned int i = 0; i < _count; ++i)
985 v(i) = _sys.solutionOlder()(dof++);
989 mooseError(
"PreviousNL not currently supported for getNodalValue");
994 template <
typename OutputType>
998 const unsigned int idx)
const 1000 static thread_local std::vector<dof_id_type> dof_indices;
1001 _dof_map.dof_indices(elem, dof_indices, _var_num);
1006 return (*_sys.currentSolution())(dof_indices[
idx]);
1009 return _sys.solutionOld()(dof_indices[
idx]);
1012 return _sys.solutionOlder()(dof_indices[
idx]);
1015 mooseError(
"PreviousNL not currently supported for getElementalValue");
1023 const unsigned int idx)
const 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 " 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;
1042 for (
unsigned int i = 0; i < _count; ++i)
1043 v(i) = (*_sys.currentSolution())(dof_indices[i * num_shapes +
idx]);
1047 for (
unsigned int i = 0; i < _count; ++i)
1048 v(i) = _sys.solutionOld()(dof_indices[i * num_shapes +
idx]);
1052 for (
unsigned int i = 0; i < _count; ++i)
1053 v(i) = _sys.solutionOlder()(dof_indices[i * num_shapes +
idx]);
1057 mooseError(
"PreviousNL not currently supported for getElementalValue");
1062 template <
typename OutputType>
1065 std::vector<dof_id_type> & dof_indices)
const 1067 if constexpr (std::is_same<OutputType, RealEigenVector>::value)
1068 _dof_map.array_dof_indices(elem, dof_indices, _var_num);
1070 _dof_map.dof_indices(elem, dof_indices, _var_num);
1073 template <
typename OutputType>
1081 template <
typename OutputType>
1085 if (_sys.solutionUDot())
1087 _need_dof_values_dot =
true;
1088 return _dof_values_dot;
1091 mooseError(
"MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set " 1092 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1095 template <
typename OutputType>
1099 if (_sys.solutionUDotDot())
1101 _need_dof_values_dotdot =
true;
1102 return _dof_values_dotdot;
1105 mooseError(
"MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. " 1106 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 1110 template <
typename OutputType>
1114 if (_sys.solutionUDotOld())
1116 _need_dof_values_dot_old =
true;
1117 return _dof_values_dot_old;
1120 mooseError(
"MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. " 1121 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 1125 template <
typename OutputType>
1129 if (_sys.solutionUDotDotOld())
1131 _need_dof_values_dotdot_old =
true;
1132 return _dof_values_dotdot_old;
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`.");
1140 template <
typename OutputType>
1144 _need_dof_du_dot_du =
true;
1145 return _dof_du_dot_du;
1148 template <
typename OutputType>
1152 _need_dof_du_dotdot_du =
true;
1153 return _dof_du_dotdot_du;
1156 template <
typename OutputType>
1160 unsigned int nqp = _qrule->n_points();
1162 _increment.resize(nqp);
1164 unsigned int num_dofs = _dof_indices.size();
1167 _increment[qp] = 0.;
1169 _increment[qp] += (*_phi)[i][qp] * increment_vec(_dof_indices[i]);
1178 unsigned int nqp = _qrule->n_points();
1180 _increment.resize(nqp);
1182 unsigned int num_dofs = _dof_indices.size();
1189 _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + j);
1200 _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + n);
1207 template <
typename OutputType>
1212 mooseError(
"computeIncrementAtNode can only be called for nodal variables");
1214 _increment.resize(1);
1217 _increment[0] = increment_vec(_dof_indices[0]);
1226 mooseError(
"computeIncrementAtNode can only be called for nodal variables");
1228 _increment.resize(1);
1232 for (
unsigned int j = 0; j < _count; j++)
1233 _increment[0](j) = increment_vec(_dof_indices[0] + j);
1237 const auto n_dof_indices = _dof_indices.size();
1240 _increment[0](j) = increment_vec(_dof_indices[0] + n);
1246 template <
typename OutputType>
1252 if (_sys.solutionUDot())
1254 _need_dof_values_dot =
true;
1255 return _nodal_value_dot;
1259 "MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set " 1260 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1263 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1268 template <
typename OutputType>
1274 if (_sys.solutionUDotDot())
1276 _need_dof_values_dotdot =
true;
1277 return _nodal_value_dotdot;
1281 "MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. " 1282 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 1286 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1291 template <
typename OutputType>
1297 if (_sys.solutionUDotOld())
1299 _need_dof_values_dot_old =
true;
1300 return _nodal_value_dot_old;
1303 mooseError(
"MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. " 1304 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 1308 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1313 template <
typename OutputType>
1319 if (_sys.solutionUDotDotOld())
1321 _need_dof_values_dotdot_old =
true;
1322 return _nodal_value_dotdot_old;
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`.");
1331 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1336 template <
typename OutputType>
1340 if (_has_dof_indices)
1348 assignADNodalValue();
1352 zeroSizeDofValues();
1355 template <
typename OutputType>
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];
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");
1371 _ad_nodal_value(i) = _ad_dof_values[i];
1374 template <
typename OutputType>
1378 if constexpr (std::is_same<RealEigenVector, OutputType>::value)
1379 _dof_map.array_dof_indices(_elem, _dof_indices, _var_num);
1381 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
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);
1388 unsigned int nqp = _qrule->n_points();
1389 _vector_tag_u[_solution_tag].resize(nqp);
1392 template <
typename OutputType>
1396 if constexpr (std::is_same<OutputType, RealEigenVector>::value)
1397 _dof_map.array_dof_indices(_elem, _dof_indices, _var_num);
1399 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1401 _has_dof_values =
false;
1405 _has_dof_indices = _dof_indices.size();
1408 template <
typename OutputType>
1412 if constexpr (std::is_same<OutputType, RealEigenVector>::value)
1413 _dof_map.array_dof_indices(_node, _dof_indices, _var_num);
1415 _dof_map.dof_indices(_node, _dof_indices, _var_num);
1417 const auto n_dofs = _dof_indices.size();
1422 _nodal_dof_index = _dof_indices[0];
1423 _has_dof_indices =
true;
1426 _has_dof_indices =
false;
1429 template <
typename OutputType>
1437 if constexpr (std::is_same<RealEigenVector, OutputType>::value)
1438 _dof_map.array_dof_indices(_elem, _dof_indices, _var_num);
1440 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1441 if (_elem->n_dofs(_sys.number(), _var_num) > 0)
1445 _nodal_dof_index = _dof_indices[0];
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);
1455 for (
auto & dof_u : _matrix_tags_dof_u)
1456 dof_u.resize(num_shapes);
1458 _has_dof_indices =
true;
1461 _has_dof_indices =
false;
1464 _has_dof_indices =
false;
1467 template <
typename OutputType>
1471 _dof_indices.clear();
1472 for (
const auto & node_id : nodes)
1474 auto && nd = _subproblem.mesh().getMesh().query_node_ptr(node_id);
1475 if (nd && (_subproblem.mesh().isSemiLocal(const_cast<Node *>(nd))))
1477 if (nd->n_dofs(_sys.number(), _var_num) > 0)
1479 dof_id_type dof = nd->dof_number(_sys.number(), _var_num, 0);
1480 _dof_indices.push_back(dof);
1485 if (!_dof_indices.empty())
1486 _has_dof_indices =
true;
1488 _has_dof_indices =
false;
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.
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...
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.
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...
std::function< const ADTemplateVariablePhiGradient< OutputShape > &(const Assembly &, libMesh::FEType)> _ad_grad_phi_assembly_method
Base class for a system (of equations)
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)
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
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.
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.
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.
DofValue getNodalValue(const Node &node, Moose::SolutionState state) const
const FieldVariableCurl & curlSln(Moose::SolutionState state) const
Local solution curl getter.
const DofValues & dofValuesDotDot() const
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
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'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...
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
DofValue getElementalValue(const Elem *elem, Moose::SolutionState state, unsigned int idx=0) const