20 #include "libmesh/quadrature.h" 21 #include "libmesh/fe_base.h" 22 #include "libmesh/system.h" 23 #include "libmesh/type_n_tensor.h" 25 template <
typename OutputType>
30 const QBase *
const & qrule_in,
31 const QBase *
const & qrule_face_in,
32 const Node *
const & node,
33 const Elem *
const & elem)
36 _fe_type(var.feType()),
37 _var_num(var.number()),
38 _assembly(_subproblem.assembly(_tid, var.kind() ==
Moose::
VAR_NONLINEAR ? sys.number() : 0)),
39 _element_type(element_type),
41 _need_ad_u_dot(false),
42 _need_ad_u_dotdot(false),
44 _need_second_old(false),
45 _need_second_older(false),
46 _need_second_previous_nl(false),
48 _need_curl_old(false),
49 _need_curl_older(false),
52 _need_div_older(false),
55 _need_ad_grad_u(false),
56 _need_ad_grad_u_dot(false),
57 _need_ad_second_u(false),
58 _has_dof_indices(false),
60 _qrule_face(qrule_face_in),
61 _use_dual(var.useDual()),
62 _second_phi_assembly_method(nullptr),
63 _second_phi_face_assembly_method(nullptr),
64 _curl_phi_assembly_method(nullptr),
65 _curl_phi_face_assembly_method(nullptr),
66 _div_phi_assembly_method(nullptr),
67 _div_phi_face_assembly_method(nullptr),
68 _ad_grad_phi_assembly_method(nullptr),
69 _ad_grad_phi_face_assembly_method(nullptr),
70 _time_integrator(nullptr),
73 _displaced(dynamic_cast<const
DisplacedSystem *>(&_sys) ? true : false),
74 _current_side(_assembly.side())
154 template <
typename OutputType>
162 _current_qrule = _qrule;
164 _current_grad_phi = _grad_phi;
165 _current_second_phi = _second_phi;
166 _current_curl_phi = _curl_phi;
167 _current_div_phi = _div_phi;
168 _current_ad_grad_phi = _ad_grad_phi;
173 _current_qrule = _qrule_face;
174 _current_phi = _phi_face;
175 _current_grad_phi = _grad_phi_face;
176 _current_second_phi = _second_phi_face;
177 _current_curl_phi = _curl_phi_face;
178 _current_div_phi = _div_phi_face;
179 _current_ad_grad_phi = _ad_grad_phi_face;
185 template <
typename OutputType>
189 if (_sys.solutionUDot())
195 mooseError(
"MooseVariableFE: Time derivative of solution (`u_dot`) is not stored. Please set " 196 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
199 template <
typename OutputType>
203 if (_sys.solutionUDotDot())
205 _need_u_dotdot =
true;
209 mooseError(
"MooseVariableFE: Second time derivative of solution (`u_dotdot`) is not stored. " 210 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 214 template <
typename OutputType>
218 if (_sys.solutionUDotOld())
220 _need_u_dot_old =
true;
224 mooseError(
"MooseVariableFE: Old time derivative of solution (`u_dot_old`) is not stored. " 225 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 229 template <
typename OutputType>
233 if (_sys.solutionUDotDotOld())
235 _need_u_dotdot_old =
true;
236 return _u_dotdot_old;
239 mooseError(
"MooseVariableFE: Old second time derivative of solution (`u_dotdot_old`) is not " 240 "stored. Please set uDotDotOldRequested() to true in FEProblemBase before " 241 "requesting `u_dotdot_old`");
244 template <
typename OutputType>
248 if (_sys.solutionUDot())
250 _need_grad_dot =
true;
254 mooseError(
"MooseVariableFE: Time derivative of solution (`u_dot`) is not stored. Please set " 255 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
258 template <
typename OutputType>
262 if (_sys.solutionUDotDot())
264 _need_grad_dotdot =
true;
265 return _grad_u_dotdot;
268 mooseError(
"MooseVariableFE: Second time derivative of solution (`u_dotdot`) is not stored. " 269 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 273 template <
typename OutputType>
289 _need_second_old =
true;
290 return _second_u_old;
295 _need_second_older =
true;
296 return _second_u_older;
301 _need_second_previous_nl =
true;
302 return _second_u_previous_nl;
312 template <
typename OutputType>
328 _need_curl_old =
true;
334 _need_curl_older =
true;
335 return _curl_u_older;
339 mooseError(
"We don't currently support curl from the previous non-linear iteration");
343 template <
typename OutputType>
359 _need_div_old =
true;
365 _need_div_older =
true;
370 mooseError(
"We don't currently support divergence from the previous non-linear iteration");
374 template <
typename OutputType>
378 _second_phi = &_second_phi_assembly_method(_assembly, _fe_type);
382 template <
typename OutputType>
386 _second_phi_face = &_second_phi_face_assembly_method(_assembly, _fe_type);
387 return *_second_phi_face;
390 template <
typename OutputType>
394 _curl_phi = &_curl_phi_assembly_method(_assembly, _fe_type);
398 template <
typename OutputType>
402 _curl_phi_face = &_curl_phi_face_assembly_method(_assembly, _fe_type);
403 return *_curl_phi_face;
406 template <
typename OutputType>
410 _div_phi = &_div_phi_assembly_method(_assembly, _fe_type);
414 template <
typename OutputType>
418 _div_phi_face = &_div_phi_face_assembly_method(_assembly, _fe_type);
419 return *_div_phi_face;
422 template <
typename OutputType>
426 unsigned int num_dofs = _dof_indices.size();
431 bool is_transient = _subproblem.isTransient();
432 unsigned int nqp = _current_qrule->n_points();
433 auto && active_coupleable_matrix_tags = _subproblem.getActiveFEVariableCoupleableMatrixTags(_tid);
435 for (
auto tag : _required_vector_tags)
437 if (_need_vector_tag_u[tag])
438 _vector_tag_u[tag].resize(nqp);
439 if (_need_vector_tag_grad[tag])
440 _vector_tag_grad[tag].resize(nqp);
443 for (
auto tag : active_coupleable_matrix_tags)
444 if (_need_matrix_tag_u[tag])
445 _matrix_tag_u[tag].resize(nqp);
448 _second_u.resize(nqp);
456 if (_need_second_previous_nl)
457 _second_u_previous_nl.resize(nqp);
465 _u_dotdot.resize(nqp);
468 _u_dot_old.resize(nqp);
470 if (_need_u_dotdot_old)
471 _u_dotdot_old.resize(nqp);
474 _du_dot_du.resize(nqp);
476 if (_need_du_dotdot_du)
477 _du_dotdot_du.resize(nqp);
480 _grad_u_dot.resize(nqp);
482 if (_need_grad_dotdot)
483 _grad_u_dotdot.resize(nqp);
485 if (_need_second_old)
486 _second_u_old.resize(nqp);
489 _curl_u_old.resize(nqp);
492 _div_u_old.resize(nqp);
494 if (_need_second_older)
495 _second_u_older.resize(nqp);
498 for (
unsigned int i = 0; i < nqp; ++i)
500 for (
auto tag : _required_vector_tags)
502 if (_need_vector_tag_u[tag])
503 _vector_tag_u[tag][i] = 0;
504 if (_need_vector_tag_grad[tag])
505 _vector_tag_grad[tag][i] = 0;
508 for (
auto tag : active_coupleable_matrix_tags)
509 if (_need_matrix_tag_u[tag])
510 _matrix_tag_u[tag][i] = 0;
521 if (_need_second_previous_nl)
522 _second_u_previous_nl[i] = 0;
535 if (_need_u_dotdot_old)
536 _u_dotdot_old[i] = 0;
541 if (_need_du_dotdot_du)
542 _du_dotdot_du[i] = 0;
547 if (_need_grad_dotdot)
548 _grad_u_dotdot[i] = 0;
550 if (_need_second_old)
551 _second_u_old[i] = 0;
553 if (_need_second_older)
554 _second_u_older[i] = 0;
564 bool second_required =
565 _need_second || _need_second_old || _need_second_older || _need_second_previous_nl;
566 bool curl_required = _need_curl || _need_curl_old;
567 bool div_required = _need_div || _need_div_old;
569 for (
unsigned int i = 0; i < num_dofs; i++)
571 for (
unsigned int qp = 0; qp < nqp; qp++)
573 const OutputType phi_local = (*_current_phi)[i][qp];
579 _u_dot[qp] += phi_local * _dof_values_dot[i];
582 _u_dotdot[qp] += phi_local * _dof_values_dotdot[i];
585 _u_dot_old[qp] += phi_local * _dof_values_dot_old[i];
587 if (_need_u_dotdot_old)
588 _u_dotdot_old[qp] += phi_local * _dof_values_dotdot_old[i];
591 _grad_u_dot[qp].add_scaled(dphi_qp, _dof_values_dot[i]);
593 if (_need_grad_dotdot)
594 _grad_u_dotdot[qp].add_scaled(dphi_qp, _dof_values_dotdot[i]);
597 _du_dot_du[qp] = _dof_du_dot_du[i];
599 if (_need_du_dotdot_du)
600 _du_dotdot_du[qp] = _dof_du_dotdot_du[i];
607 "We're requiring a second calculation but have not set a second shape function!");
609 (*_current_second_phi)[i][qp];
612 _second_u[qp].add_scaled(d2phi_local, _vector_tags_dof_u[_solution_tag][i]);
614 if (_need_second_previous_nl)
615 _second_u_previous_nl[qp].add_scaled(d2phi_local,
616 _vector_tags_dof_u[_previous_nl_solution_tag][i]);
620 if (_need_second_old)
621 _second_u_old[qp].add_scaled(d2phi_local, _vector_tags_dof_u[_old_solution_tag][i]);
623 if (_need_second_older)
624 _second_u_older[qp].add_scaled(d2phi_local, _vector_tags_dof_u[_older_solution_tag][i]);
630 mooseAssert(_current_curl_phi,
631 "We're requiring a curl calculation but have not set a curl shape function!");
632 const OutputType curl_phi_local = (*_current_curl_phi)[i][qp];
635 _curl_u[qp] += curl_phi_local * _vector_tags_dof_u[_solution_tag][i];
637 if (is_transient && _need_curl_old)
638 _curl_u_old[qp] += curl_phi_local * _vector_tags_dof_u[_old_solution_tag][i];
645 "We're requiring a divergence calculation but have not set a div shape function!");
649 _div_u[qp] += div_phi_local * _vector_tags_dof_u[_solution_tag][i];
651 if (is_transient && _need_div_old)
652 _div_u_old[qp] += div_phi_local * _vector_tags_dof_u[_old_solution_tag][i];
655 for (
auto tag : _required_vector_tags)
657 if (_sys.hasVector(tag) && _sys.getVector(tag).closed())
659 if (_need_vector_tag_u[tag])
660 _vector_tag_u[tag][qp] += phi_local * _vector_tags_dof_u[tag][i];
661 if (_need_vector_tag_grad[tag])
662 _vector_tag_grad[tag][qp].add_scaled(dphi_qp, _vector_tags_dof_u[tag][i]);
666 for (
auto tag : active_coupleable_matrix_tags)
667 if (_need_matrix_tag_u[tag])
668 _matrix_tag_u[tag][qp] += phi_local * _matrix_tags_dof_u[tag][i];
674 computeAD(num_dofs, nqp);
681 unsigned int num_dofs = _dof_indices.size();
686 bool is_transient = _subproblem.isTransient();
687 unsigned int nqp = _current_qrule->n_points();
688 auto && active_coupleable_matrix_tags = _subproblem.getActiveFEVariableCoupleableMatrixTags(_tid);
691 if (_qrule == _current_qrule)
693 _mapped_grad_phi.resize(num_dofs);
694 for (
unsigned int i = 0; i < num_dofs; i++)
696 _mapped_grad_phi[i].resize(nqp, Eigen::Map<RealDIMValue>(
nullptr));
697 for (
unsigned int qp = 0; qp < nqp; qp++)
699 new (&_mapped_grad_phi[i][qp])
700 Eigen::Map<RealDIMValue>(
const_cast<Real *
>(&(*_current_grad_phi)[i][qp](0)));
705 _mapped_grad_phi_face.resize(num_dofs);
706 for (
unsigned int i = 0; i < num_dofs; i++)
708 _mapped_grad_phi_face[i].resize(nqp, Eigen::Map<RealDIMValue>(
nullptr));
709 for (
unsigned int qp = 0; qp < nqp; qp++)
711 new (&_mapped_grad_phi_face[i][qp])
712 Eigen::Map<RealDIMValue>(
const_cast<Real *
>(&(*_current_grad_phi)[i][qp](0)));
716 for (
auto tag : _required_vector_tags)
718 if (_need_vector_tag_u[tag])
719 _vector_tag_u[tag].resize(nqp);
720 if (_need_vector_tag_grad[tag])
721 _vector_tag_grad[tag].resize(nqp);
724 for (
auto tag : active_coupleable_matrix_tags)
725 if (_need_matrix_tag_u[tag])
726 _matrix_tag_u[tag].resize(nqp);
729 _second_u.resize(nqp);
737 if (_need_second_previous_nl)
738 _second_u_previous_nl.resize(nqp);
746 _u_dotdot.resize(nqp);
749 _u_dot_old.resize(nqp);
751 if (_need_u_dotdot_old)
752 _u_dotdot_old.resize(nqp);
755 _du_dot_du.resize(nqp);
757 if (_need_du_dotdot_du)
758 _du_dotdot_du.resize(nqp);
761 _grad_u_dot.resize(nqp);
763 if (_need_grad_dotdot)
764 _grad_u_dotdot.resize(nqp);
766 if (_need_second_old)
767 _second_u_old.resize(nqp);
770 _curl_u_old.resize(nqp);
773 _div_u_old.resize(nqp);
775 if (_need_second_older)
776 _second_u_older.resize(nqp);
779 for (
unsigned int i = 0; i < nqp; ++i)
781 for (
auto tag : _required_vector_tags)
783 if (_need_vector_tag_u[tag])
784 _vector_tag_u[tag][i].setZero(_count);
785 if (_need_vector_tag_grad[tag])
786 _vector_tag_grad[tag][i].setZero(_count, LIBMESH_DIM);
789 for (
auto tag : active_coupleable_matrix_tags)
790 if (_need_matrix_tag_u[tag])
791 _matrix_tag_u[tag][i].setZero(_count);
794 _second_u[i].setZero(_count, LIBMESH_DIM * LIBMESH_DIM);
797 _curl_u[i].setZero(_count);
800 _div_u[i].setZero(_count);
802 if (_need_second_previous_nl)
803 _second_u_previous_nl[i].setZero(_count, LIBMESH_DIM * LIBMESH_DIM);
808 _u_dot[i].setZero(_count);
811 _u_dotdot[i].setZero(_count);
814 _u_dot_old[i].setZero(_count);
816 if (_need_u_dotdot_old)
817 _u_dotdot_old[i].setZero(_count);
822 if (_need_du_dotdot_du)
823 _du_dotdot_du[i] = 0;
826 _grad_u_dot[i].setZero(_count, LIBMESH_DIM);
828 if (_need_grad_dotdot)
829 _grad_u_dotdot[i].setZero(_count, LIBMESH_DIM);
831 if (_need_second_old)
832 _second_u_old[i].setZero(_count, LIBMESH_DIM * LIBMESH_DIM);
834 if (_need_second_older)
835 _second_u_older[i].setZero(_count, LIBMESH_DIM * LIBMESH_DIM);
838 _curl_u_old[i].setZero(_count);
841 _div_u_old[i].setZero(_count);
845 bool second_required =
846 _need_second || _need_second_old || _need_second_older || _need_second_previous_nl;
847 bool curl_required = _need_curl || _need_curl_old;
848 bool div_required = _need_div || _need_div_old;
850 for (
unsigned int i = 0; i < num_dofs; i++)
852 for (
unsigned int qp = 0; qp < nqp; qp++)
854 const OutputShape phi_local = (*_current_phi)[i][qp];
860 _u_dot[qp] += phi_local * _dof_values_dot[i];
863 _u_dotdot[qp] += phi_local * _dof_values_dotdot[i];
866 _u_dot_old[qp] += phi_local * _dof_values_dot_old[i];
868 if (_need_u_dotdot_old)
869 _u_dotdot_old[qp] += phi_local * _dof_values_dotdot_old[i];
873 _grad_u_dot[qp].col(d) += dphi_qp(d) * _dof_values_dot[i];
875 if (_need_grad_dotdot)
877 _grad_u_dotdot[qp].col(d) += dphi_qp(d) * _dof_values_dotdot[i];
880 _du_dot_du[qp] = _dof_du_dot_du[i];
882 if (_need_du_dotdot_du)
883 _du_dotdot_du[qp] = _dof_du_dotdot_du[i];
890 "We're requiring a second calculation but have not set a second shape function!");
894 for (
unsigned int d = 0, d1 = 0; d1 < LIBMESH_DIM; ++d1)
895 for (
unsigned int d2 = 0; d2 < LIBMESH_DIM; ++d2)
896 _second_u[qp].col(d++) += d2phi_local(d1, d2) * _vector_tags_dof_u[_solution_tag][i];
898 if (_need_second_previous_nl)
899 for (
unsigned int d = 0, d1 = 0; d1 < LIBMESH_DIM; ++d1)
900 for (
unsigned int d2 = 0; d2 < LIBMESH_DIM; ++d2)
901 _second_u_previous_nl[qp].col(d++) +=
902 d2phi_local(d1, d2) * _vector_tags_dof_u[_previous_nl_solution_tag][i];
906 if (_need_second_old)
907 for (
unsigned int d = 0, d1 = 0; d1 < LIBMESH_DIM; ++d1)
908 for (
unsigned int d2 = 0; d2 < LIBMESH_DIM; ++d2)
909 _second_u_old[qp].col(d++) +=
910 d2phi_local(d1, d2) * _vector_tags_dof_u[_old_solution_tag][i];
912 if (_need_second_older)
913 for (
unsigned int d = 0, d1 = 0; d1 < LIBMESH_DIM; ++d1)
914 for (
unsigned int d2 = 0; d2 < LIBMESH_DIM; ++d2)
915 _second_u_older[qp].col(d++) +=
916 d2phi_local(d1, d2) * _vector_tags_dof_u[_older_solution_tag][i];
922 mooseAssert(_current_curl_phi,
923 "We're requiring a curl calculation but have not set a curl shape function!");
924 const auto curl_phi_local = (*_current_curl_phi)[i][qp];
927 _curl_u[qp] += curl_phi_local * _vector_tags_dof_u[_solution_tag][i];
929 if (is_transient && _need_curl_old)
930 _curl_u_old[qp] += curl_phi_local * _vector_tags_dof_u[_old_solution_tag][i];
935 mooseAssert(_current_div_phi,
936 "We're requiring a divergence calculation but have not set a divergence shape " 938 const auto div_phi_local = (*_current_div_phi)[i][qp];
941 _div_u[qp] += div_phi_local * _vector_tags_dof_u[_solution_tag][i];
943 if (is_transient && _need_div_old)
944 _div_u_old[qp] += div_phi_local * _vector_tags_dof_u[_old_solution_tag][i];
947 for (
auto tag : _required_vector_tags)
949 if (_need_vector_tag_u[tag])
950 _vector_tag_u[tag][qp] += phi_local * _vector_tags_dof_u[tag][i];
951 if (_need_vector_tag_grad[tag])
953 _vector_tag_grad[tag][qp].col(d) += dphi_qp(d) * _vector_tags_dof_u[tag][i];
956 for (
auto tag : active_coupleable_matrix_tags)
957 if (_need_matrix_tag_u[tag])
958 _matrix_tag_u[tag][qp] += phi_local * _matrix_tags_dof_u[tag][i];
964 template <
typename OutputType>
968 if (_dof_indices.size() == 0)
971 if (_elem->p_level())
978 bool is_transient = _subproblem.isTransient();
979 unsigned int nqp = _current_qrule->n_points();
982 _second_u.resize(nqp);
984 if (_need_second_previous_nl)
985 _second_u_previous_nl.resize(nqp);
993 _u_dotdot.resize(nqp);
996 _u_dot_old.resize(nqp);
998 if (_need_u_dotdot_old)
999 _u_dotdot_old.resize(nqp);
1001 if (_need_du_dot_du)
1002 _du_dot_du.resize(nqp);
1004 if (_need_du_dotdot_du)
1005 _du_dotdot_du.resize(nqp);
1007 if (_need_second_old)
1008 _second_u_old.resize(nqp);
1010 if (_need_second_older)
1011 _second_u_older.resize(nqp);
1016 if (_need_dof_values_dot)
1017 _dof_values_dot.resize(1);
1018 if (_need_dof_values_dotdot)
1019 _dof_values_dotdot.resize(1);
1020 if (_need_dof_values_dot_old)
1021 _dof_values_dot_old.resize(1);
1022 if (_need_dof_values_dotdot_old)
1023 _dof_values_dotdot_old.resize(1);
1030 Real u_dotdot_old = 0;
1031 const Real & du_dot_du = _sys.duDotDu();
1032 const Real & du_dotdot_du = _sys.duDotDotDu();
1036 if (_sys.solutionUDot())
1037 u_dot = (*_sys.solutionUDot())(
idx);
1038 if (_sys.solutionUDotDot())
1039 u_dotdot = (*_sys.solutionUDotDot())(
idx);
1040 if (_sys.solutionUDotOld())
1041 u_dot_old = (*_sys.solutionUDotOld())(
idx);
1042 if (_sys.solutionUDotDotOld())
1043 u_dotdot_old = (*_sys.solutionUDotDotOld())(
idx);
1045 if (_need_dof_values_dot)
1046 _dof_values_dot[0] = u_dot;
1048 if (_need_dof_values_dotdot)
1049 _dof_values_dotdot[0] = u_dotdot;
1052 auto phi = (*_current_phi)[0][0];
1057 _u_dot[0] = phi * u_dot;
1060 _u_dotdot[0] = phi * u_dotdot;
1062 if (_need_u_dot_old)
1063 _u_dot_old[0] = phi * u_dot_old;
1065 if (_need_u_dotdot_old)
1066 _u_dotdot_old[0] = phi * u_dotdot_old;
1068 if (_need_du_dot_du)
1069 _du_dot_du[0] = du_dot_du;
1071 if (_need_du_dotdot_du)
1072 _du_dotdot_du[0] = du_dotdot_du;
1075 for (
unsigned qp = 1; qp < nqp; ++qp)
1080 _u_dot[qp] = _u_dot[0];
1083 _u_dotdot[qp] = _u_dotdot[0];
1085 if (_need_u_dot_old)
1086 _u_dot_old[qp] = _u_dot_old[0];
1088 if (_need_u_dotdot_old)
1089 _u_dotdot_old[qp] = _u_dotdot_old[0];
1091 if (_need_du_dot_du)
1092 _du_dot_du[qp] = _du_dot_du[0];
1094 if (_need_du_dotdot_du)
1095 _du_dotdot_du[qp] = _du_dotdot_du[0];
1099 auto && active_coupleable_matrix_tags = _subproblem.getActiveFEVariableCoupleableMatrixTags(_tid);
1101 for (
auto tag : _required_vector_tags)
1103 if (_need_vector_tag_u[tag] || _need_vector_tag_grad[tag] || _need_vector_tag_dof_u[tag])
1105 _subproblem.safeAccessTaggedVectors()) ||
1108 if (_sys.hasVector(tag) && _sys.getVector(tag).closed())
1110 auto & vec = _sys.getVector(tag);
1111 _vector_tags_dof_u[tag].resize(1);
1112 _vector_tags_dof_u[tag][0] = vec(_dof_indices[0]);
1115 if (_need_vector_tag_u[tag])
1117 _vector_tag_u[tag].resize(nqp);
1118 auto v = phi * _vector_tags_dof_u[tag][0];
1119 for (
unsigned int qp = 0; qp < nqp; ++qp)
1120 _vector_tag_u[tag][qp] = v;
1122 if (_need_vector_tag_grad[tag])
1123 _vector_tag_grad[tag].resize(nqp);
1126 if (_subproblem.safeAccessTaggedMatrices())
1128 auto & active_coupleable_matrix_tags =
1129 _subproblem.getActiveFEVariableCoupleableMatrixTags(_tid);
1130 for (
auto tag : active_coupleable_matrix_tags)
1132 _matrix_tags_dof_u[tag].resize(1);
1133 if (_need_matrix_tag_dof_u[tag] || _need_matrix_tag_u[tag])
1134 if (_sys.hasMatrix(tag) && _sys.matrixTagActive(tag) && _sys.getMatrix(tag).closed())
1136 auto & mat = _sys.getMatrix(tag);
1138 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
1139 _matrix_tags_dof_u[tag][0] = mat(_dof_indices[0], _dof_indices[0]);
1144 for (
auto tag : active_coupleable_matrix_tags)
1145 if (_need_matrix_tag_u[tag])
1147 _matrix_tag_u[tag].resize(nqp);
1148 auto v = phi * _matrix_tags_dof_u[tag][0];
1149 for (
unsigned int qp = 0; qp < nqp; ++qp)
1150 _matrix_tag_u[tag][qp] = v;
1162 template <
typename OutputType>
1170 _ad_dof_values.resize(num_dofs);
1174 if (_need_ad_grad_u)
1175 _ad_grad_u.resize(nqp);
1177 if (_need_ad_second_u)
1178 _ad_second_u.resize(nqp);
1182 _ad_dofs_dot.resize(num_dofs);
1183 _ad_u_dot.resize(nqp);
1185 if (_need_ad_grad_u_dot)
1186 _ad_grad_u_dot.resize(nqp);
1188 if (_need_ad_u_dotdot)
1190 _ad_dofs_dotdot.resize(num_dofs);
1191 _ad_u_dotdot.resize(nqp);
1196 for (
unsigned int qp = 0; qp < nqp; qp++)
1199 _ad_u[qp] = _ad_zero;
1201 if (_need_ad_grad_u)
1202 _ad_grad_u[qp] = _ad_zero;
1204 if (_need_ad_second_u)
1205 _ad_second_u[qp] = _ad_zero;
1208 _ad_u_dot[qp] = _ad_zero;
1210 if (_need_ad_u_dotdot)
1211 _ad_u_dotdot[qp] = _ad_zero;
1213 if (_need_ad_grad_u_dot)
1214 _ad_grad_u_dot[qp] = _ad_zero;
1217 for (
unsigned int i = 0; i < num_dofs; i++)
1219 _ad_dof_values[i] = (*_sys.currentSolution())(_dof_indices[i]);
1225 if (_need_ad_u_dot && _time_integrator && _time_integrator->dt())
1227 _ad_dofs_dot[i] = _ad_dof_values[i];
1228 _time_integrator->computeADTimeDerivatives(_ad_dofs_dot[i],
1230 _need_ad_u_dotdot ? _ad_dofs_dotdot[i]
1236 for (
unsigned int i = 0; i < num_dofs; i++)
1238 for (
unsigned int qp = 0; qp < nqp; qp++)
1241 _ad_u[qp] += _ad_dof_values[i] * (*_current_phi)[i][qp];
1243 if (_need_ad_grad_u)
1248 if (_displaced && _current_ad_grad_phi)
1249 _ad_grad_u[qp] += _ad_dof_values[i] * (*_current_ad_grad_phi)[i][qp];
1251 _ad_grad_u[qp] += _ad_dof_values[i] * (*_current_grad_phi)[i][qp];
1254 if (_need_ad_second_u)
1257 _ad_second_u[qp] += _ad_dof_values[i] * (*_current_second_phi)[i][qp];
1259 if (_need_ad_u_dot && _time_integrator && _time_integrator->dt())
1261 _ad_u_dot[qp] += (*_current_phi)[i][qp] * _ad_dofs_dot[i];
1262 if (_need_ad_u_dotdot)
1263 _ad_u_dotdot[qp] += (*_current_phi)[i][qp] * _ad_dofs_dotdot[i];
1266 if (_need_ad_grad_u_dot && _time_integrator && _time_integrator->dt())
1271 if (_displaced && _current_ad_grad_phi)
1272 _ad_grad_u_dot[qp] += _ad_dofs_dot[i] * (*_current_ad_grad_phi)[i][qp];
1274 _ad_grad_u_dot[qp] += _ad_dofs_dot[i] * (*_current_grad_phi)[i][qp];
1279 if (_need_ad_u_dot && !_time_integrator)
1280 for (MooseIndex(nqp) qp = 0; qp < nqp; ++qp)
1282 _ad_u_dot[qp] = _u_dot[qp];
1283 if (_need_ad_u_dotdot)
1284 _ad_u_dotdot[qp] = _u_dotdot[qp];
1287 if (_need_ad_grad_u_dot && !_time_integrator)
1288 for (MooseIndex(nqp) qp = 0; qp < nqp; ++qp)
1289 _ad_grad_u_dot[qp] = _grad_u_dot[qp];
1295 const unsigned int )
1297 mooseError(
"AD for array variable has not been implemented");
1300 template <
typename OutputType>
1304 auto & dof_values = _vector_tags_dof_u[_solution_tag];
1305 dof_values[index] =
value;
1306 _has_dof_values =
true;
1308 auto & u = _vector_tag_u[_solution_tag];
1309 for (
unsigned int qp = 0; qp < u.size(); qp++)
1311 u[qp] = (*_phi)[0][qp] * dof_values[0];
1313 for (
unsigned int i = 1; i < dof_values.size(); i++)
1314 u[qp] += (*_phi)[i][qp] * dof_values[i];
1318 template <
typename OutputType>
1322 auto & dof_values = _vector_tags_dof_u[_solution_tag];
1323 for (
unsigned int i = 0; i < values.size(); i++)
1324 dof_values[i] = values(i);
1326 _has_dof_values =
true;
1328 auto & u = _vector_tag_u[_solution_tag];
1329 for (
unsigned int qp = 0; qp < u.size(); qp++)
1331 u[qp] = (*_phi)[0][qp] * dof_values[0];
1332 for (
unsigned int i = 1; i < dof_values.size(); i++)
1333 u[qp] += (*_phi)[i][qp] * dof_values[i];
1337 template <
typename OutputType>
1342 residual.
set(_nodal_dof_index, v);
1350 for (
unsigned int j = 0; j < _count; ++j)
1351 residual.
set(_nodal_dof_index + j, v(j));
1354 template <
typename OutputType>
1358 mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)),
"Node is not Semilocal");
1363 mooseAssert(node.n_dofs(_sys.number(), _var_num) > 0,
1364 "Node " << node.id() <<
" does not contain any dofs for the " 1365 << _sys.system().variable_name(_var_num) <<
" variable");
1367 dof_id_type dof = node.dof_number(_sys.number(), _var_num, 0);
1372 return (*_sys.currentSolution())(dof);
1375 return _sys.solutionOld()(dof);
1378 return _sys.solutionOlder()(dof);
1381 mooseError(
"PreviousNL not currently supported for getNodalValue");
1390 mooseAssert(_subproblem.mesh().isSemiLocal(const_cast<Node *>(&node)),
"Node is not Semilocal");
1395 mooseAssert(node.n_dofs(_sys.number(), _var_num) > 0,
1396 "Node " << node.id() <<
" does not contain any dofs for the " 1397 << _sys.system().variable_name(_var_num) <<
" variable");
1399 dof_id_type dof = node.dof_number(_sys.number(), _var_num, 0);
1405 for (
unsigned int i = 0; i < _count; ++i)
1406 v(i) = (*_sys.currentSolution())(dof++);
1410 for (
unsigned int i = 0; i < _count; ++i)
1411 v(i) = _sys.solutionOld()(dof++);
1415 for (
unsigned int i = 0; i < _count; ++i)
1416 v(i) = _sys.solutionOlder()(dof++);
1420 mooseError(
"PreviousNL not currently supported for getNodalValue");
1425 template <
typename OutputType>
1429 unsigned int idx)
const 1431 std::vector<dof_id_type> dof_indices;
1432 _dof_map.dof_indices(elem, dof_indices, _var_num);
1437 return (*_sys.currentSolution())(dof_indices[
idx]);
1440 return _sys.solutionOld()(dof_indices[
idx]);
1443 return _sys.solutionOlder()(dof_indices[
idx]);
1446 mooseError(
"PreviousNL not currently supported for getElementalValue");
1454 unsigned int idx)
const 1456 std::vector<dof_id_type> dof_indices;
1457 _dof_map.dof_indices(elem, dof_indices, _var_num);
1466 for (
unsigned int i = 0; i < _count; ++i)
1467 v(i) = (*_sys.currentSolution())(dof++);
1471 for (
unsigned int i = 0; i < _count; ++i)
1472 v(i) = _sys.solutionOld()(dof++);
1476 for (
unsigned int i = 0; i < _count; ++i)
1477 v(i) = _sys.solutionOlder()(dof++);
1481 mooseError(
"PreviousNL not currently supported for getElementalValue");
1486 template <
typename OutputType>
1489 std::vector<dof_id_type> & dof_indices)
const 1491 _dof_map.dof_indices(elem, dof_indices, _var_num);
1494 template <
typename OutputType>
1508 for (
unsigned int j = 0; j < _count; ++j)
1510 unsigned int inc = (isNodal() ? j : j * _dof_indices.size());
1511 for (
unsigned int i = 0; i < _dof_indices.size(); ++i)
1512 sol.
add(_dof_indices[i] + inc, v(p++));
1516 template <
typename OutputType>
1520 if (_sys.solutionUDot())
1522 _need_dof_values_dot =
true;
1523 return _dof_values_dot;
1526 mooseError(
"MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set " 1527 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1530 template <
typename OutputType>
1534 if (_sys.solutionUDotDot())
1536 _need_dof_values_dotdot =
true;
1537 return _dof_values_dotdot;
1540 mooseError(
"MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. " 1541 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 1545 template <
typename OutputType>
1549 if (_sys.solutionUDotOld())
1551 _need_dof_values_dot_old =
true;
1552 return _dof_values_dot_old;
1555 mooseError(
"MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. " 1556 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 1560 template <
typename OutputType>
1564 if (_sys.solutionUDotDotOld())
1566 _need_dof_values_dotdot_old =
true;
1567 return _dof_values_dotdot_old;
1570 mooseError(
"MooseVariableData: Old second time derivative of solution (`u_dotdot_old`) is not " 1571 "stored. Please set uDotDotOldRequested() to true in FEProblemBase before " 1572 "requesting `u_dotdot_old`.");
1575 template <
typename OutputType>
1579 _need_dof_du_dot_du =
true;
1580 return _dof_du_dot_du;
1583 template <
typename OutputType>
1587 _need_dof_du_dotdot_du =
true;
1588 return _dof_du_dotdot_du;
1591 template <
typename OutputType>
1595 unsigned int nqp = _qrule->n_points();
1597 _increment.resize(nqp);
1599 unsigned int num_dofs = _dof_indices.size();
1600 for (
unsigned int qp = 0; qp < nqp; qp++)
1603 for (
unsigned int i = 0; i < num_dofs; i++)
1604 _increment[qp] += (*_phi)[i][qp] * increment_vec(_dof_indices[i]);
1613 unsigned int nqp = _qrule->n_points();
1615 _increment.resize(nqp);
1617 unsigned int num_dofs = _dof_indices.size();
1620 for (
unsigned int qp = 0; qp < nqp; qp++)
1622 for (
unsigned int i = 0; i < num_dofs; i++)
1623 for (
unsigned int j = 0; j < _count; j++)
1624 _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + j);
1629 for (
unsigned int qp = 0; qp < nqp; qp++)
1632 for (
unsigned int j = 0; j < _count; j++)
1633 for (
unsigned int i = 0; i < num_dofs; i++)
1635 _increment[qp](j) += (*_phi)[i][qp] * increment_vec(_dof_indices[i] + n);
1642 template <
typename OutputType>
1647 mooseError(
"computeIncrementAtNode can only be called for nodal variables");
1649 _increment.resize(1);
1652 _increment[0] = increment_vec(_dof_indices[0]);
1661 mooseError(
"computeIncrementAtNode can only be called for nodal variables");
1663 _increment.resize(1);
1667 for (
unsigned int j = 0; j < _count; j++)
1668 _increment[0](j) = increment_vec(_dof_indices[0] + j);
1672 for (
unsigned int j = 0; j < _count; j++)
1674 _increment[0](j) = increment_vec(_dof_indices[0] + n);
1675 n += _dof_indices.size();
1680 template <
typename OutputType>
1686 if (_sys.solutionUDot())
1688 _need_dof_values_dot =
true;
1689 return _nodal_value_dot;
1693 "MooseVariableData: Time derivative of solution (`u_dot`) is not stored. Please set " 1694 "uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
1697 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1702 template <
typename OutputType>
1708 if (_sys.solutionUDotDot())
1710 _need_dof_values_dotdot =
true;
1711 return _nodal_value_dotdot;
1715 "MooseVariableData: Second time derivative of solution (`u_dotdot`) is not stored. " 1716 "Please set uDotDotRequested() to true in FEProblemBase before requesting " 1720 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1725 template <
typename OutputType>
1731 if (_sys.solutionUDotOld())
1733 _need_dof_values_dot_old =
true;
1734 return _nodal_value_dot_old;
1737 mooseError(
"MooseVariableData: Old time derivative of solution (`u_dot_old`) is not stored. " 1738 "Please set uDotOldRequested() to true in FEProblemBase before requesting " 1742 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1747 template <
typename OutputType>
1753 if (_sys.solutionUDotDotOld())
1755 _need_dof_values_dotdot_old =
true;
1756 return _nodal_value_dotdot_old;
1760 "MooseVariableData: Old second time derivative of solution (`u_dotdot_old`) is not " 1761 "stored. Please set uDotDotOldRequested() to true in FEProblemBase before " 1762 "requesting `u_dotdot_old`.");
1765 mooseError(
"Nodal values can be requested only on nodal variables, variable '",
1770 template <
typename OutputType>
1774 if (_has_dof_indices)
1783 zeroSizeDofValues();
1786 template <
typename OutputType>
1790 auto n = _dof_indices.size();
1792 _ad_dof_values.resize(n);
1794 const bool do_derivatives =
1795 ADReal::do_derivatives && _sys.number() == _subproblem.currentNlSysNum();
1797 for (decltype(n) i = 0; i < n; ++i)
1799 _ad_dof_values[i] = _vector_tags_dof_u[_solution_tag][i];
1802 assignADNodalValue(_ad_dof_values[i], i);
1810 mooseError(
"I do not know how to support AD with array variables");
1817 _ad_nodal_value =
value;
1823 const unsigned int & component)
1825 _ad_nodal_value(component) =
value;
1828 template <
typename OutputType>
1832 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1833 _vector_tags_dof_u[_solution_tag].resize(_dof_indices.size());
1835 unsigned int nqp = _qrule->n_points();
1836 _vector_tag_u[_solution_tag].resize(nqp);
1839 template <
typename OutputType>
1843 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1844 _has_dof_values =
false;
1848 if (_dof_indices.size() > 0)
1849 _has_dof_indices =
true;
1851 _has_dof_indices =
false;
1854 template <
typename OutputType>
1858 if (std::size_t n_dofs = _node->n_dofs(_sys.number(), _var_num))
1860 _dof_indices.resize(n_dofs);
1861 for (std::size_t i = 0; i < n_dofs; ++i)
1862 _dof_indices[i] = _node->dof_number(_sys.number(), _var_num, i);
1865 _nodal_dof_index = _dof_indices[0];
1866 _has_dof_indices =
true;
1870 _dof_indices.clear();
1871 _has_dof_indices =
false;
1875 template <
typename OutputType>
1883 _dof_map.dof_indices(_elem, _dof_indices, _var_num);
1884 if (_elem->n_dofs(_sys.number(), _var_num) > 0)
1887 _nodal_dof_index = _elem->dof_number(_sys.number(), _var_num, 0);
1891 for (
auto & dof_u : _vector_tags_dof_u)
1892 dof_u.resize(_dof_indices.size());
1894 for (
auto & dof_u : _matrix_tags_dof_u)
1895 dof_u.resize(_dof_indices.size());
1897 _has_dof_indices =
true;
1900 _has_dof_indices =
false;
1903 _has_dof_indices =
false;
1906 template <
typename OutputType>
1910 _dof_indices.clear();
1911 for (
const auto & node_id : nodes)
1913 auto && nd = _subproblem.mesh().getMesh().query_node_ptr(node_id);
1914 if (nd && (_subproblem.mesh().isSemiLocal(const_cast<Node *>(nd))))
1916 if (nd->n_dofs(_sys.number(), _var_num) > 0)
1918 dof_id_type dof = nd->dof_number(_sys.number(), _var_num, 0);
1919 _dof_indices.push_back(dof);
1924 if (_dof_indices.size() > 0)
1925 _has_dof_indices =
true;
1927 _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 FEVectorBase *const & getVectorFE(FEType type, unsigned int dim) const
Get a reference to a pointer that will contain the current volume FEVector.
std::function< const typename OutputTools< OutputShape >::VariablePhiSecond &(const Assembly &, FEType)> _second_phi_face_assembly_method
OutputData getNodalValue(const Node &node, Moose::SolutionState state) const
void assignADNodalValue(const DualReal &value, const unsigned int &component)
Helper methods for assigning nodal values from their corresponding solution values (dof values as the...
const FieldVariableValue & uDotDotOld() const
void computeAD(const unsigned int num_dofs, const unsigned int nqp)
compute AD things
void insertNodalValue(NumericVector< Number > &residual, const OutputData &v)
Write a nodal value to the passed-in solution vector.
std::function< const typename OutputTools< OutputShape >::VariablePhiDivergence &(const Assembly &, FEType)> _div_phi_face_assembly_method
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...
std::function< const ADTemplateVariablePhiGradient< OutputShape > &(const Assembly &, FEType)> _ad_grad_phi_assembly_method
void computeValues()
compute the variable values
void computeIncrementAtQps(const NumericVector< Number > &increment_vec)
Compute and store incremental change in solution at QPs based on increment_vec.
virtual void add_vector(const Number *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
DualNumber< Real, DNDerivativeType, true > DualReal
Moose::DOFType< OutputType >::type OutputData
TimeIntegrator * getTimeIntegrator()
const OutputType & nodalValueDotOld() const
TensorTools::IncrementRank< OutputShape >::type OutputShapeGradient
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
const FieldVariableValue & uDot() const
std::function< const typename OutputTools< OutputShape >::VariablePhiGradient &(const Assembly &, FEType)> _grad_phi_assembly_method
FEContinuity _continuity
Continuity type of the variable.
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< Number > & dofValuesDuDotDotDu() const
Base class for a system (of equations)
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< OutputData > &values)
Set local DOF values and evaluate the values on quadrature points.
OutputData getElementalValue(const Elem *elem, Moose::SolutionState state, unsigned int idx=0) const
const DoFValue & dofValuesDotDotOld() const
std::function< const typename OutputTools< OutputShape >::VariablePhiDivergence &(const Assembly &, FEType)> _div_phi_assembly_method
const MooseArray< Number > & dofValuesDuDotDu() const
const DoFValue & dofValuesDot() const
const FieldVariablePhiDivergence & divPhi() const
divergence_phi getter
std::function< const ADTemplateVariablePhiGradient< OutputShape > &(const Assembly &, FEType)> _ad_grad_phi_face_assembly_method
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void addSolution(NumericVector< Number > &sol, const DenseVector< Number > &v) const
Add passed in local DOF values to a solution vector.
const OutputType & nodalValueDot() const
std::function< const typename OutputTools< OutputShape >::VariablePhiCurl &(const Assembly &, FEType)> _curl_phi_face_assembly_method
virtual unsigned int dimension() const
Returns MeshBase::mesh_dimension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh me...
const FieldVariablePhiSecond & secondPhiFace() const
second_phi_face getter
TensorTools::DecrementRank< OutputShape >::type OutputShapeDivergence
const FieldVariableGradient & gradSlnDotDot() const
Local second time derivative of solution gradient getter.
void reinitNode()
Prepare degrees of freedom for the current node.
std::function< const typename OutputTools< OutputShape >::VariablePhiSecond &(const Assembly &, FEType)> _second_phi_assembly_method
const TimeIntegrator * _time_integrator
Pointer to time integrator.
std::function< const typename OutputTools< OutputShape >::VariablePhiValue &(const Assembly &, FEType)> _phi_face_assembly_method
const DoFValue & dofValuesDotDot() const
Moose::ElementType _element_type
The element type this object is storing data for. This is either Element, Neighbor, or Lower.
const ADTemplateVariablePhiGradient< OutputShape > * _ad_grad_phi
const OutputType & nodalValueDotDotOld() const
const FieldVariablePhiValue * _phi_face
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::function< const typename OutputTools< OutputShape >::VariablePhiCurl &(const Assembly &, FEType)> _curl_phi_assembly_method
const FieldVariableCurl & curlSln(Moose::SolutionState state) const
Local solution curl getter.
const FieldVariableValue & uDotOld() const
Moose::ShapeType< OutputType >::type OutputShape
const ADTemplateVariablePhiGradient< OutputShape > * _ad_grad_phi_face
const FieldVariablePhiSecond & secondPhi() const
second_phi getter
const OutputType & nodalValueDotDot() const
virtual MooseMesh & mesh()
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)
const FieldVariablePhiGradient * _grad_phi_face
void derivInsert(NumberArray< N, Real > &derivs, dof_id_type index, Real value)
const FieldVariablePhiCurl & curlPhiFace() const
curl_phi_face getter
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
std::function< const typename OutputTools< OutputType >::VariablePhiValue &(const Assembly &, FEType)> _phi_assembly_method
virtual void set(const numeric_index_type i, const Number 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
const FEBase *const & getFE(FEType type, unsigned int dim) const
Get a reference to a pointer that will contain the current volume FE.
std::function< const typename OutputTools< OutputShape >::VariablePhiGradient &(const Assembly &, FEType)> _grad_phi_face_assembly_method
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 Number value)=0
const FieldVariablePhiDivergence & divPhiFace() const
divergence_phi_face getter
const FieldVariableSecond & secondSln(Moose::SolutionState state) const
Local solution second spatial derivative getter.
void computeIncrementAtNode(const NumericVector< Number > &increment_vec)
Compute and store incremental change at the current node based on increment_vec.
bool _is_nodal
if variable is nodal
const FieldVariablePhiGradient * _grad_phi
const FieldVariablePhiValue * _phi