https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MooseVariableDataBase.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "MooseError.h"
12#include "MooseTypes.h"
13#include "SystemBase.h"
14#include "SubProblem.h"
15#include "MooseVariableField.h"
16#include "MooseMesh.h"
17#include "libmesh/mesh_base.h"
18
19template <typename OutputType>
21 SystemBase & sys,
22 THREAD_ID tid)
23 : _sys(sys),
24 _subproblem(_sys.subproblem()),
25 _tid(tid),
26 _dof_map(_sys.dofMap()),
27 _count(var.count()),
28 _has_dof_values(false),
29 _max_state(0),
30 _solution_tag(_subproblem.getVectorTagID(Moose::SOLUTION_TAG)),
31 _old_solution_tag(Moose::INVALID_TAG_ID),
32 _older_solution_tag(Moose::INVALID_TAG_ID),
33 _previous_nl_solution_tag(Moose::INVALID_TAG_ID),
34 _need_u_dot(false),
35 _need_u_dotdot(false),
36 _need_u_dot_old(false),
37 _need_u_dotdot_old(false),
38 _need_du_dot_du(false),
39 _need_du_dotdot_du(false),
40 _need_grad_dot(false),
41 _need_grad_dotdot(false),
42 _need_dof_values_dot(false),
43 _need_dof_values_dotdot(false),
44 _need_dof_values_dot_old(false),
45 _need_dof_values_dotdot_old(false),
46 _need_dof_du_dot_du(false),
47 _need_dof_du_dotdot_du(false),
48 _var(var)
49{
50 auto num_vector_tags = _subproblem.numVectorTags();
51 // Additional solution tags corresponding to older-than-current solution states may be requested
52 // on-the-fly by consumer objects after variable construction. To accomodate this we should
53 // reserve the possibly requisite memory. As of now we only support old and older solution states
54 // but this could potentially increase in the future
55 const auto max_future_num_vector_tags = num_vector_tags + 2;
56
57 _vector_tags_dof_u.reserve(max_future_num_vector_tags);
58 _vector_tags_dof_u.resize(num_vector_tags);
59 _need_vector_tag_dof_u.reserve(max_future_num_vector_tags);
60 _need_vector_tag_dof_u.resize(num_vector_tags, false);
61
62 _need_vector_tag_u.reserve(max_future_num_vector_tags);
63 _need_vector_tag_u.resize(num_vector_tags, false);
64 _vector_tag_u.reserve(max_future_num_vector_tags);
65 _vector_tag_u.resize(num_vector_tags);
66
67 _need_vector_tag_grad.reserve(max_future_num_vector_tags);
68 _need_vector_tag_grad.resize(num_vector_tags, false);
69 _vector_tag_grad.reserve(max_future_num_vector_tags);
70 _vector_tag_grad.resize(num_vector_tags);
71
72 // Always fetch the dof values for the solution tag
73 const auto soln_tag = _subproblem.getVectorTagID(Moose::SOLUTION_TAG);
74 _need_vector_tag_dof_u[soln_tag] = true;
75 _need_vector_tag_u[soln_tag] = true;
76 insertSolutionTag(soln_tag);
77
78 // These MooseArray objects are used by AuxKernelBase for nodal AuxKernel objects, hence the size
79 // size is always 1 (i.e, nodal kernels work with _qp=0 only).
83}
84
85template <typename OutputType>
86void
88{
89 auto num_matrix_tags = _subproblem.numMatrixTags();
90
91 _matrix_tags_dof_u.resize(num_matrix_tags);
92 _need_matrix_tag_dof_u.resize(num_matrix_tags, false);
93
94 _need_matrix_tag_u.resize(num_matrix_tags, false);
95 _matrix_tag_u.resize(num_matrix_tags);
96}
97
98template <typename OutputType>
101{
102 if (isNodal())
103 {
104 if (tag >= _need_vector_tag_dof_u.size())
105 const_cast<MooseVariableDataBase<OutputType> *>(this)->resizeVectorTagData(tag);
106
107 _need_vector_tag_dof_u[tag] = true;
108
109 if (_sys.hasVector(tag))
110 return _vector_tags_dof_u[tag];
111 else
113 "Tag ", tag, " is not associated with any vector for nodal variable ", _var.name());
114 }
115 else
116 mooseError("Nodal values can be requested only on nodal variables, variable '",
117 _var.name(),
118 "' is not nodal.");
119}
120
121template <typename OutputType>
124{
125 if (isNodal())
126 {
127 if (tag >= _matrix_tags_dof_u.size())
128 {
129 _need_matrix_tag_dof_u.resize(tag + 1, false);
130 const_cast<MooseVariableDataBase<OutputType> *>(this)->_matrix_tags_dof_u.resize(tag + 1);
131 }
132
133 _need_matrix_tag_dof_u[tag] = true;
134
135 if (_sys.hasMatrix(tag))
136 return _matrix_tags_dof_u[tag];
137 else
139 "Tag ", tag, " is not associated with any matrix for nodal variable ", _var.name());
140 }
141 else
142 mooseError("Nodal values can be requested only on nodal variables, variable '",
143 _var.name(),
144 "' is not nodal.");
145}
146
147template <typename OutputType>
148void
150{
151 mooseAssert(_need_vector_tag_dof_u.size() == _need_vector_tag_u.size() &&
152 _need_vector_tag_dof_u.size() == _need_vector_tag_grad.size() &&
153 _need_vector_tag_dof_u.size() == _vector_tags_dof_u.size() &&
154 _need_vector_tag_dof_u.size() == _vector_tag_u.size() &&
155 _need_vector_tag_dof_u.size() == _vector_tag_grad.size(),
156 "These sizes should be in sync.");
157
158 auto check_capacity = [tag](const auto & vector_to_check)
159 {
160 if (tag + 1 > vector_to_check.capacity())
161 mooseError("New size greater than tag capacity. This will cause reallocation which will "
162 "invalidate any stored references.");
163 };
164 check_capacity(_need_vector_tag_dof_u);
165 check_capacity(_need_vector_tag_u);
166 check_capacity(_need_vector_tag_grad);
167 check_capacity(_vector_tags_dof_u);
168 check_capacity(_vector_tag_u);
169 check_capacity(_vector_tag_grad);
170
171 _need_vector_tag_dof_u.resize(tag + 1, false);
172 _need_vector_tag_u.resize(tag + 1, false);
173 _need_vector_tag_grad.resize(tag + 1, false);
174 _vector_tags_dof_u.resize(tag + 1);
175 _vector_tag_u.resize(tag + 1);
176 _vector_tag_grad.resize(tag + 1);
177}
178
179template <typename OutputType>
182{
183 if (tag >= _need_vector_tag_u.size())
184 const_cast<MooseVariableDataBase<OutputType> *>(this)->resizeVectorTagData(tag);
185
186 _var.requireQpComputations();
187
188 _need_vector_tag_u[tag] = true;
189
190 if (_sys.hasVector(tag))
191 return _vector_tag_u[tag];
192 else
193 mooseError("Tag ", tag, " is not associated with any vector for variable ", _var.name());
194}
195
196template <typename OutputType>
199{
200 if (tag >= _need_vector_tag_dof_u.size())
201 const_cast<MooseVariableDataBase<OutputType> *>(this)->resizeVectorTagData(tag);
202
203 _var.requireQpComputations();
204
205 _need_vector_tag_dof_u[tag] = true;
206
207 if (_sys.hasVector(tag))
208 return _vector_tags_dof_u[tag];
209 else
210 mooseError("Tag ", tag, " is not associated with any vector for variable ", _var.name());
211}
212
213template <typename OutputType>
216{
217 if (tag >= _need_vector_tag_grad.size())
218 const_cast<MooseVariableDataBase<OutputType> *>(this)->resizeVectorTagData(tag);
219
220 _var.requireQpComputations();
221
222 _need_vector_tag_grad[tag] = true;
223
224 if (_sys.hasVector(tag))
225 return _vector_tag_grad[tag];
226 else
227 mooseError("Tag ", tag, " is not associated with any vector for variable ", _var.name());
228}
229
230template <typename OutputType>
233{
234 if (tag >= _matrix_tag_u.size())
235 {
236 _need_matrix_tag_u.resize(tag + 1, false);
237 const_cast<MooseVariableDataBase<OutputType> *>(this)->_matrix_tag_u.resize(tag + 1);
238 }
239
240 _var.requireQpComputations();
241
242 _need_matrix_tag_u[tag] = true;
243
244 if (_sys.hasMatrix(tag))
245 return _matrix_tag_u[tag];
246 else
247 mooseError("Tag ", tag, " is not associated with any matrix for variable ", _var.name());
248}
249
250template <typename OutputType>
251unsigned int
256
257template <typename OutputType>
258void
260{
261 if (state > _max_state)
262 {
263 _sys.needSolutionState(state);
264 _max_state = state;
265 }
266}
267
268template <typename OutputType>
269template <typename ReturnType, typename Functor>
270const ReturnType &
272 Functor functor)
273{
274 if (state > 0)
275 {
276 // We need to request all states that are between current and the requested state
277 stateToTagHelper<ReturnType>(Moose::SolutionState(static_cast<int>(state) - 1), functor);
278 needSolutionState(cast_int<unsigned int>(state));
279 }
280
281 switch (state)
282 {
283 case Moose::Current:
284 return functor(_subproblem.getVectorTagID(Moose::SOLUTION_TAG));
285
286 case Moose::Old:
287 {
288 _old_solution_tag = _subproblem.getVectorTagID(Moose::OLD_SOLUTION_TAG);
289 insertSolutionTag(_old_solution_tag);
290 return functor(_old_solution_tag);
291 }
292
293 case Moose::Older:
294 {
295 _older_solution_tag = _subproblem.getVectorTagID(Moose::OLDER_SOLUTION_TAG);
296 insertSolutionTag(_older_solution_tag);
297 return functor(_older_solution_tag);
298 }
299
301 {
302 _previous_nl_solution_tag = _subproblem.getVectorTagID(Moose::PREVIOUS_NL_SOLUTION_TAG);
303 insertSolutionTag(_previous_nl_solution_tag);
304 return functor(_previous_nl_solution_tag);
305 }
306
307 default:
308 // We should never get here but gcc requires that we have a default. See
309 // htpps://stackoverflow.com/questions/18680378/after-defining-case-for-all-enum-values-compiler-still-says-control-reaches-e
310 mooseError("Unknown SolutionState!");
311 }
312}
313
314template <typename OutputType>
317{
318 auto functor = [this](TagID tag_id) -> const FieldVariableValue &
319 { return vectorTagValue(tag_id); };
320
321 _var.requireQpComputations();
322
323 return const_cast<MooseVariableDataBase<OutputType> *>(this)
324 ->stateToTagHelper<FieldVariableValue>(state, functor);
325}
326
327template <typename OutputType>
330{
331 auto functor = [this](TagID tag_id) -> const FieldVariableGradient &
332 { return vectorTagGradient(tag_id); };
333
334 _var.requireQpComputations();
335
336 return const_cast<MooseVariableDataBase<OutputType> *>(this)
337 ->stateToTagHelper<FieldVariableGradient>(state, functor);
338}
339
340template <typename OutputType>
343{
344 auto functor = [this](TagID tag_id) -> const DofValues & { return vectorTagDofValue(tag_id); };
345
346 _var.requireQpComputations();
347
348 return const_cast<MooseVariableDataBase<OutputType> *>(this)->stateToTagHelper<DofValues>(
349 state, functor);
350}
351
352template <typename OutputType>
355{
356 return vectorTagDofValue(Moose::Current);
357}
358
359template <typename OutputType>
362{
363 return vectorTagDofValue(Moose::Old);
364}
365
366template <typename OutputType>
369{
370 return vectorTagDofValue(Moose::Older);
371}
372
373template <typename OutputType>
376{
377 return vectorTagDofValue(Moose::PreviousNL);
378}
379
380template <typename OutputType>
381void
383{
384 // dof_values here is indexed per shape function, with each entry holding all _count array
385 // components packed into a single OutputType value. setNodalValue writes only one shape
386 // function's value, so it is only valid for a variable with a single shape function, e.g. a
387 // nodal Lagrange variable or a CONSTANT-order elemental variable; a variable with more than
388 // one shape function must use setDofValues instead. A subparametric variable, e.g. the pressure
389 // of a Taylor-Hood pair, has nodes on its elements that carry none of its degrees of freedom;
390 // callers query isNodalDefined() to skip those nodes before reaching this method.
391 mooseAssert(_dof_indices.size() == _count,
392 "setNodalValue is only valid for a variable with one shape function per node");
393 auto & dof_values = _vector_tags_dof_u[_solution_tag];
394 dof_values.resize(/*n_shapes=*/1);
395 dof_values[0] = value; // update variable nodal value
396 _has_dof_values = true;
397 _nodal_value = value;
398
399 // Update the qp values as well
400 auto & u = _vector_tag_u[_solution_tag];
401 for (unsigned int qp = 0; qp < u.size(); qp++)
402 u[qp] = value;
403}
404
405template <>
406void
408{
409 // Unlike the generic implementation above, a vector-valued variable is never an array
410 // variable, so _count is always 1 and dof_values is indexed per component of the vector
411 // rather than per shape function -- each shape function contributes one raw degree of
412 // freedom per component given the finite element family and order constraints we set below.
413 mooseAssert(_count == 1, "Vector-valued variables cannot be array variables");
414 mooseAssert(
415 _var.feType().family == LAGRANGE_VEC ||
416 (_var.feType().family == MONOMIAL_VEC && _var.feType().order == CONSTANT &&
417 (!_var.feType().p_refinement || !_subproblem.doingPRefinement())),
418 "setNodalValue only makes sense for LAGRANGE_VEC or non-p-refined CONSTANT MONOMIAL_VEC "
419 "vector variables");
420 mooseAssert(_dof_indices.size() <= _var.sys().mesh().getMesh().mesh_dimension(),
421 "The number of dof indices for a vector variable should be at most the mesh manifold "
422 "dimension. We cannot use an exact equality because it's possible the vector "
423 "variable could live on a lower-dimensional manifold.");
424
425 auto & dof_values = _vector_tags_dof_u[_solution_tag];
426 dof_values.resize(_dof_indices.size());
427 for (const auto i : index_range(dof_values))
428 dof_values[i] = value(i);
429
430 _has_dof_values = true;
431 _nodal_value = value;
432}
433
434template <typename OutputType>
435void
436MooseVariableDataBase<OutputType>::insert(NumericVector<Number> & residual)
437{
438 if (_has_dof_values)
439 {
440 const auto & dof_values = _vector_tags_dof_u[_solution_tag];
441 mooseAssert(dof_values.size() == _dof_indices.size(),
442 "Degree of freedom values size and degree of freedom indices sizes must match.");
443 residual.insert(&dof_values[0], _dof_indices);
444 }
445}
446
447template <>
448void
449MooseVariableDataBase<RealEigenVector>::insert(NumericVector<Number> & residual)
450{
451 if (_has_dof_values)
452 {
453 const auto & dof_values = _vector_tags_dof_u[_solution_tag];
454 mooseAssert(_dof_indices.size() % _count == 0,
455 "Dof indices should be cleanly divisible by the variable count");
456 const auto n_shapes = _dof_indices.size() / _count;
457 for (const auto indx : index_range(_dof_indices))
458 {
459 const auto i = indx % n_shapes;
460 const auto j = indx / n_shapes;
461 residual.set(_dof_indices[indx], dof_values[i](j));
462 }
463 }
464}
465
466template <typename OutputType>
467void
468MooseVariableDataBase<OutputType>::add(NumericVector<Number> & residual)
469{
470 if (_has_dof_values)
471 {
472 const auto & dof_values = _vector_tags_dof_u[_solution_tag];
473 residual.add_vector(&dof_values[0], _dof_indices);
474 }
475}
476
477template <>
478void
479MooseVariableDataBase<RealEigenVector>::add(NumericVector<Number> & residual)
480{
481 if (_has_dof_values)
482 {
483 const auto & dof_values = _vector_tags_dof_u[_solution_tag];
484 mooseAssert(_dof_indices.size() % _count == 0,
485 "Dof indices should be cleanly divisible by the variable count");
486 const auto n_shapes = _dof_indices.size() / _count;
487 for (const auto indx : index_range(_dof_indices))
488 {
489 const auto i = indx % n_shapes;
490 const auto j = indx / n_shapes;
491 residual.add(_dof_indices[indx], dof_values[i](j));
492 }
493 }
494}
495
496template <typename OutputType>
497const OutputType &
499{
500 if (isNodal())
501 {
502 // Request the correct solution states and data members
503 vectorTagDofValue(state);
504 switch (state)
505 {
506 case Moose::Current:
507 return _nodal_value;
508
509 case Moose::Old:
510 return _nodal_value_old;
511
512 case Moose::Older:
513 return _nodal_value_older;
514
516 return _nodal_value_previous_nl;
517
518 default:
519 // We should never get here but gcc requires that we have a default. See
520 // htpps://stackoverflow.com/questions/18680378/after-defining-case-for-all-enum-values-compiler-still-says-control-reaches-e
521 mooseError("Unknown SolutionState!");
522 }
523 }
524 else
525 mooseError("Nodal values can be requested only on nodal variables, variable '",
526 _var.name(),
527 "' is not nodal.");
528}
529
530template <typename OutputType>
533{
534 if (isNodal())
535 {
536 // Request the correct solution states and data members
537 vectorTagDofValue(state);
538 switch (state)
539 {
540 case Moose::Current:
541 return _nodal_value_array;
542
543 case Moose::Old:
544 return _nodal_value_old_array;
545
546 case Moose::Older:
547 return _nodal_value_older_array;
548
549 default:
550 mooseError("No current support for PreviousNL for nodal value array");
551 }
552 }
553 else
554 mooseError("Nodal values can be requested only on nodal variables, variable '",
555 _var.name(),
556 "' is not nodal.");
557}
558
559template <typename OutputType>
560void
562{
563 bool is_transient = _subproblem.isTransient();
564
565 auto n = _dof_indices.size();
566 libmesh_assert(n);
567
568 if (is_transient)
569 {
570 if (_need_u_dot || _need_grad_dot || _need_dof_values_dot)
571 {
572 libmesh_assert(_sys.solutionUDot());
573 _dof_values_dot.resize(n);
574 _sys.solutionUDot()->get(_dof_indices, &_dof_values_dot[0]);
575 }
576 if (_need_u_dotdot || _need_grad_dotdot || _need_dof_values_dotdot)
577 {
578 libmesh_assert(_sys.solutionUDotDot());
579 _dof_values_dotdot.resize(n);
580 _sys.solutionUDotDot()->get(_dof_indices, &_dof_values_dotdot[0]);
581 }
582 if (_need_u_dot_old || _need_dof_values_dot_old)
583 {
584 libmesh_assert(_sys.solutionUDotOld());
585 _dof_values_dot_old.resize(n);
586 _sys.solutionUDotOld()->get(_dof_indices, &_dof_values_dot_old[0]);
587 }
588 if (_need_u_dotdot_old || _need_dof_values_dotdot_old)
589 {
590 libmesh_assert(_sys.solutionUDotDotOld());
591 _dof_values_dotdot_old.resize(n);
592 _sys.solutionUDotDotOld()->get(_dof_indices, &_dof_values_dotdot_old[0]);
593 }
594 if (_need_du_dot_du || _need_dof_du_dot_du)
595 {
596 _dof_du_dot_du.resize(n);
597 for (decltype(n) i = 0; i < n; ++i)
598 _dof_du_dot_du[i] = _sys.duDotDu(_var.number());
599 }
600 if (_need_du_dotdot_du || _need_dof_du_dotdot_du)
601 {
602 _dof_du_dotdot_du.resize(n);
603 for (decltype(n) i = 0; i < n; ++i)
604 _dof_du_dotdot_du[i] = _sys.duDotDotDu();
605 }
606 }
607
608 for (auto tag : _required_vector_tags)
609 if (_need_vector_tag_u[tag] || _need_vector_tag_grad[tag] || _need_vector_tag_dof_u[tag])
610 if ((_subproblem.vectorTagType(tag) == Moose::VECTOR_TAG_RESIDUAL &&
611 _subproblem.safeAccessTaggedVectors()) ||
612 _subproblem.vectorTagType(tag) == Moose::VECTOR_TAG_SOLUTION)
613 {
614 // tag is defined on problem but may not be used by a system
615 // the grain tracker requires being able to read from solution vectors that we are also in
616 // the process of writing :-/
617 // Note: the extra vector tags are also still not closed when a TagVectorAux uses them
618 if (_sys.hasVector(tag) /* && _sys.getVector(tag).closed()*/)
619 {
620 auto & vec = _sys.getVector(tag);
621 _vector_tags_dof_u[tag].resize(n);
622 vec.get(_dof_indices, &_vector_tags_dof_u[tag][0]);
623 }
624 }
625
626 if (_subproblem.safeAccessTaggedMatrices())
627 {
628 auto & active_coupleable_matrix_tags =
629 _subproblem.getActiveFEVariableCoupleableMatrixTags(_tid);
630
631 for (auto tag : active_coupleable_matrix_tags)
632 {
633 if (_need_matrix_tag_dof_u[tag] || _need_matrix_tag_u[tag])
634 if (_sys.hasMatrix(tag) && _sys.matrixTagActive(tag))
635 {
636 mooseAssert(_sys.getMatrix(tag).closed(),
637 "Matrix with tag '" + std::to_string(tag) + "' should be closed");
638 auto & mat = _sys.getMatrix(tag);
639 _matrix_tags_dof_u[tag].resize(n);
640 for (unsigned i = 0; i < n; i++)
641 _matrix_tags_dof_u[tag][i] = mat(_dof_indices[i], _dof_indices[i]);
642 }
643 }
644 }
645}
646
647template <typename OutputType>
648void
650 const unsigned int nshapes,
651 MooseArray<RealEigenVector> & dof_values) const
652{
653 dof_values.resize(nshapes);
654 for (const auto i : make_range(nshapes))
655 {
656 dof_values[i].resize(_count);
657 for (const auto j : make_range(_count))
658 dof_values[i](j) = sol(_dof_indices[j * nshapes + i]);
659 }
660}
661
662template <>
663void
665{
666 bool is_transient = _subproblem.isTransient();
667
668 auto n = _dof_indices.size() / _count;
669 libmesh_assert(n);
670
671 if (is_transient)
672 {
673 if (_need_u_dot || _need_grad_dot || _need_dof_values_dot)
674 {
675 libmesh_assert(_sys.solutionUDot());
676 getArrayDofValues(*_sys.solutionUDot(), n, _dof_values_dot);
677 }
678 if (_need_u_dotdot || _need_grad_dotdot || _need_dof_values_dotdot)
679 {
680 libmesh_assert(_sys.solutionUDotDot());
681 getArrayDofValues(*_sys.solutionUDot(), n, _dof_values_dotdot);
682 }
683 if (_need_u_dot_old || _need_dof_values_dot_old)
684 {
685 libmesh_assert(_sys.solutionUDotOld());
686 getArrayDofValues(*_sys.solutionUDotOld(), n, _dof_values_dot_old);
687 }
688 if (_need_u_dotdot_old || _need_dof_values_dotdot_old)
689 {
690 libmesh_assert(_sys.solutionUDotDotOld());
691 getArrayDofValues(*_sys.solutionUDotDotOld(), n, _dof_values_dotdot_old);
692 }
693 }
694
695 for (auto tag : _required_vector_tags)
696 if ((_subproblem.vectorTagType(tag) == Moose::VECTOR_TAG_RESIDUAL &&
697 _subproblem.safeAccessTaggedVectors()) ||
698 _subproblem.vectorTagType(tag) == Moose::VECTOR_TAG_SOLUTION)
699 // tag is defined on problem but may not be used by a system
700 if (_sys.hasVector(tag))
701 {
702 mooseAssert(_sys.getVector(tag).closed(),
703 "Vector with tag '" + std::to_string(tag) + "' should be closed");
704 getArrayDofValues(_sys.getVector(tag), n, _vector_tags_dof_u[tag]);
705 }
706
707 if (_subproblem.safeAccessTaggedMatrices())
708 {
709 auto & active_coupleable_matrix_tags =
710 _subproblem.getActiveFEVariableCoupleableMatrixTags(_tid);
711 for (auto tag : active_coupleable_matrix_tags)
712 {
713 _matrix_tags_dof_u[tag].resize(n);
714 if (_need_matrix_tag_dof_u[tag] || _need_matrix_tag_u[tag])
715 if (_sys.hasMatrix(tag) && _sys.matrixTagActive(tag))
716 {
717 mooseAssert(_sys.getMatrix(tag).closed(),
718 "Matrix with tag '" + std::to_string(tag) + "' should be closed");
719 auto & mat = _sys.getMatrix(tag);
720 for (unsigned i = 0; i < n; i++)
721 for (unsigned j = 0; j < _count; j++)
722 _matrix_tags_dof_u[tag][i](j) = mat(_dof_indices[i] + j, _dof_indices[i] + j);
723 }
724 }
725 }
726
727 if (_need_du_dot_du || _need_dof_du_dot_du)
728 {
729 _dof_du_dot_du.resize(n);
730 for (decltype(n) i = 0; i < n; ++i)
731 _dof_du_dot_du[i] = _sys.duDotDu(_var.number());
732 }
733 if (_need_du_dotdot_du || _need_dof_du_dotdot_du)
734 {
735 _dof_du_dotdot_du.resize(n);
736 for (decltype(n) i = 0; i < n; ++i)
737 _dof_du_dotdot_du[i] = _sys.duDotDotDu();
738 }
739}
740
741template <typename OutputType>
742void
744{
745 if (_subproblem.isTransient())
746 {
747 _dof_values_dot.resize(0);
748 _dof_values_dotdot.resize(0);
749 _dof_values_dot_old.resize(0);
750 _dof_values_dotdot_old.resize(0);
751 _dof_du_dot_du.resize(0);
752 _dof_du_dotdot_du.resize(0);
753 }
754
755 for (auto & dof_values : _vector_tags_dof_u)
756 dof_values.resize(0);
757
758 _has_dof_values = false;
759}
760
761template <typename OutputType>
762void
764{
765 bool is_transient = _subproblem.isTransient();
766 libmesh_assert(_dof_indices.size());
767
768 auto & dof_values = _vector_tags_dof_u[_solution_tag];
769 _nodal_value = dof_values[0];
770 _nodal_value_array[0] = _nodal_value;
771
772 if (is_transient)
773 {
774 if (oldestSolutionStateRequested() >= 1)
775 {
776 _nodal_value_old = _vector_tags_dof_u[_old_solution_tag][0];
777 _nodal_value_old_array[0] = _nodal_value_old;
778 }
779 if (oldestSolutionStateRequested() >= 2)
780 {
781 _nodal_value_older = _vector_tags_dof_u[_older_solution_tag][0];
782 _nodal_value_older_array[0] = _nodal_value_older;
783 }
784 if (_need_dof_values_dot)
785 _nodal_value_dot = _dof_values_dot[0];
786 if (_need_dof_values_dotdot)
787 _nodal_value_dotdot = _dof_values_dotdot[0];
788 if (_need_dof_values_dot_old)
789 _nodal_value_dot_old = _dof_values_dot_old[0];
790 if (_need_dof_values_dotdot_old)
791 _nodal_value_dotdot_old = _dof_values_dotdot_old[0];
792 }
793 if (_previous_nl_solution_tag != Moose::INVALID_TAG_ID)
794 _nodal_value_previous_nl = _vector_tags_dof_u[_previous_nl_solution_tag][0];
795}
796
797template <>
798void
800{
801 bool is_transient = _subproblem.isTransient();
802
803 auto n = _dof_indices.size();
804 libmesh_assert(n);
805
806 auto & dof_values = _vector_tags_dof_u[_solution_tag];
807 for (decltype(n) i = 0; i < n; ++i)
808 _nodal_value(i) = dof_values[i];
809 _nodal_value_array[0] = _nodal_value;
810
811 if (is_transient)
812 {
813 if (oldestSolutionStateRequested() >= 1)
814 {
815 auto & dof_values_old = _vector_tags_dof_u[_old_solution_tag];
816 for (decltype(n) i = 0; i < n; ++i)
817 _nodal_value_old(i) = dof_values_old[i];
818 _nodal_value_old_array[0] = _nodal_value_old;
819 }
820 if (oldestSolutionStateRequested() >= 2)
821 {
822 auto & dof_values_older = _vector_tags_dof_u[_older_solution_tag];
823 for (decltype(n) i = 0; i < n; ++i)
824 _nodal_value_older(i) = dof_values_older[i];
825 _nodal_value_older_array[0] = _nodal_value_older;
826 }
827 if (_need_dof_values_dot)
828 for (decltype(n) i = 0; i < n; ++i)
829 _nodal_value_dot(i) = _dof_values_dot[i];
830 if (_need_dof_values_dotdot)
831 for (decltype(n) i = 0; i < n; ++i)
832 _nodal_value_dotdot(i) = _dof_values_dotdot[i];
833 if (_need_dof_values_dot_old)
834 for (decltype(n) i = 0; i < n; ++i)
835 _nodal_value_dot_old(i) = _dof_values_dot_old[i];
836 if (_need_dof_values_dotdot_old)
837 for (decltype(n) i = 0; i < n; ++i)
838 _nodal_value_dotdot_old(i) = _dof_values_dotdot_old[i];
839 }
840 if (_previous_nl_solution_tag != Moose::INVALID_TAG_ID)
841 {
842 auto & dof_values_previous_nl = _vector_tags_dof_u[_previous_nl_solution_tag];
843 for (decltype(n) i = 0; i < n; ++i)
844 _nodal_value_previous_nl(i) = dof_values_previous_nl[i];
845 }
846}
847
848template class MooseVariableDataBase<Real>;
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
unsigned int TagID
Definition MooseTypes.h:238
unsigned int THREAD_ID
Definition MooseTypes.h:237
unsigned int count
Definition MortarUtils.C:53
void resize(unsigned int size)
Change the number of elements the array can store.
Definition MooseArray.h:216
MooseVariableDataBase(const MooseVariableField< OutputType > &var, SystemBase &sys, THREAD_ID tid)
void resizeVectorTagData(TagID tag)
resize the vector tag need flags and data containers to accomodate this tag index
std::vector< FieldVariableValue > _vector_tag_u
const FieldVariableValue & vectorTagValue(TagID tag) const
void insert(libMesh::NumericVector< libMesh::Number > &residual)
Set the current local DOF values to the input vector.
const DofValues & nodalMatrixTagValue(TagID tag) const
const DofValues & dofValuesOlder() const
void fetchDofValues()
Helper methods for assigning dof values from their corresponding solution values.
unsigned int oldestSolutionStateRequested() const
The oldest solution state that is requested for this variable (0 = current, 1 = old,...
const OutputType & nodalValue(Moose::SolutionState state) const
std::vector< DofValues > _vector_tags_dof_u
const MooseArray< OutputType > & nodalValueArray(Moose::SolutionState state) const
const FieldVariableValue & sln(Moose::SolutionState state) const
Local solution getter.
const DofValues & nodalVectorTagValue(TagID tag) const
const DofValues & dofValuesPreviousNL() const
const FieldVariableGradient & gradSln(Moose::SolutionState state) const
Local solution gradient getter.
std::vector< bool > _need_vector_tag_u
const FieldVariableGradient & vectorTagGradient(TagID tag) const
MooseArray< OutputType > _nodal_value_old_array
std::vector< FieldVariableGradient > _vector_tag_grad
const DofValues & vectorTagDofValue(TagID tag) const
const DofValues & dofValuesOld() const
void getArrayDofValues(const libMesh::NumericVector< libMesh::Number > &sol, unsigned int n, MooseArray< RealEigenVector > &dof_values) const
void insertSolutionTag(TagID tag_id)
insert a solution tag into our tag containers
MooseArray< OutputType > _nodal_value_array
Nodal values as MooseArrays for use with AuxKernels.
void needSolutionState(unsigned int state)
Request that we have at least state number of older solution states/vectors.
void setNodalValue(const OutputType &value)
Set nodal value.
const DofValues & dofValues() const
void sizeMatrixTagData()
size matrix tag data
std::vector< bool > _need_vector_tag_dof_u
const FieldVariableValue & matrixTagValue(TagID tag) const
const SubProblem & _subproblem
The subproblem which we can query for information related to tagged vectors and matrices.
MooseArray< OutputType > _nodal_value_older_array
void add(libMesh::NumericVector< libMesh::Number > &residual)
Add the current local DOF values to the input vector.
const ReturnType & stateToTagHelper(Moose::SolutionState state, Functor functor)
Helper method that converts a SolutionState argument into a corresponding tag ID, potentially request...
std::vector< bool > _need_vector_tag_grad
Class for stuff related to variables.
virtual TagID getVectorTagID(const TagName &tag_name) const
Get a TagID from a TagName.
Definition SubProblem.C:192
virtual unsigned int numVectorTags(const Moose::VectorTagType type=Moose::VECTOR_TAG_ANY) const
The total number of tags, which can be limited to the tag type.
Definition SubProblem.C:184
Base class for a system (of equations)
Definition SystemBase.h:87
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
const TagID INVALID_TAG_ID
Definition MooseTypes.C:23
const TagName OLDER_SOLUTION_TAG
Definition MooseTypes.C:27
@ VECTOR_TAG_SOLUTION
@ VECTOR_TAG_RESIDUAL
const TagName PREVIOUS_NL_SOLUTION_TAG
Definition MooseTypes.C:28
SolutionState
Definition MooseTypes.h:262
@ Current
Definition MooseTypes.h:263
@ PreviousNL
Definition MooseTypes.h:266
const TagName OLD_SOLUTION_TAG
Definition MooseTypes.C:26
const TagName SOLUTION_TAG
Definition MooseTypes.C:25