https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MooseVariableScalar.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
10#include "MooseVariableScalar.h"
11#include "SubProblem.h"
12#include "SystemBase.h"
13#include "Assembly.h"
14#include "SystemBase.h"
15
16// libMesh
17#include "libmesh/numeric_vector.h"
18#include "libmesh/dof_map.h"
19
20#include <limits>
21
23
26{
27 auto params = MooseVariableBase::validParams();
28 params.addClassDescription("Moose wrapper class around scalar variables");
29 params.set<MooseEnum>("family") = "SCALAR";
30 return params;
31}
32
34 : MooseVariableBase(parameters),
35 Moose::FunctorBase<ADReal>(name()),
36 _need_u_dot(false),
37 _need_u_dotdot(false),
38 _need_u_dot_old(false),
39 _need_u_dotdot_old(false),
40 _need_du_dot_du(false),
41 _need_du_dotdot_du(false),
42 _need_u_old(false),
43 _need_u_older(false),
44 _need_ad(false),
45 _need_ad_u(false),
46 _need_ad_u_dot(false)
47{
48 auto num_vector_tags = _sys.subproblem().numVectorTags();
49
50 _vector_tag_u.resize(num_vector_tags);
51 _need_vector_tag_u.resize(num_vector_tags);
52}
53
54void
56{
57 auto num_matrix_tags = _sys.subproblem().numMatrixTags();
58
59 _matrix_tag_u.resize(num_matrix_tags);
60 _need_matrix_tag_u.resize(num_matrix_tags);
61}
62
64{
65 _u.release();
66 _u_old.release();
67 _u_older.release();
68
69 _u_dot.release();
70 _u_dotdot.release();
71 _u_dot_old.release();
72 _u_dotdot_old.release();
73 _du_dot_du.release();
74 _du_dotdot_du.release();
75
76 for (auto & _tag_u : _vector_tag_u)
77 _tag_u.release();
78
79 _vector_tag_u.clear();
80
81 for (auto & _tag_u : _matrix_tag_u)
82 _tag_u.release();
83
84 _matrix_tag_u.clear();
85}
86
87void
88MooseVariableScalar::reinit(bool reinit_for_derivative_reordering /* = false*/)
89{
90 if (reinit_for_derivative_reordering)
91 {
92 // We've already calculated everything in an earlier reinit. All we have to do is re-sort the
93 // derivative vector for AD calculations
94 if (_need_ad)
95 computeAD(/*nodal_ordering=*/true);
96 return;
97 }
98
99 // We want to make sure that we're not allocating data with any of the
100 // accessors that follow, but _sys is non-const
101 const SystemBase & sys = _sys;
102
103 const NumericVector<Real> & current_solution = *sys.currentSolution();
104 const NumericVector<Real> * u_dot = sys.solutionUDot();
105 const NumericVector<Real> * u_dotdot = sys.solutionUDotDot();
106 const NumericVector<Real> * u_dot_old = sys.solutionUDotOld();
107 const NumericVector<Real> * u_dotdot_old = sys.solutionUDotDotOld();
108 const Real & du_dot_du = sys.duDotDu(number());
109 const Real & du_dotdot_du = sys.duDotDotDu();
110 auto safe_access_tagged_vectors = sys.subproblem().safeAccessTaggedVectors();
111 auto safe_access_tagged_matrices = sys.subproblem().safeAccessTaggedMatrices();
112 auto & active_coupleable_matrix_tags =
114
116
117 auto n = _dof_indices.size();
118 _u.resize(n);
119 if (_need_u_old)
120 _u_old.resize(n);
121 if (_need_u_older)
122 _u_older.resize(n);
123
124 for (auto & _tag_u : _vector_tag_u)
125 _tag_u.resize(n);
126
127 for (auto & _tag_u : _matrix_tag_u)
128 _tag_u.resize(n);
129
130 _du_dot_du.clear();
131 _du_dot_du.resize(n, du_dot_du);
132
133 if (_need_u_dot)
134 _u_dot.resize(n);
135
136 if (_need_u_dotdot)
137 _u_dotdot.resize(n);
138
139 if (_need_u_dot_old)
140 _u_dot_old.resize(n);
141
143 _u_dotdot_old.resize(n);
144
145 if (_need_du_dot_du)
146 {
147 _du_dot_du.clear();
148 _du_dot_du.resize(n, du_dot_du);
149 }
150
152 {
153 _du_dotdot_du.clear();
154 _du_dotdot_du.resize(n, du_dotdot_du);
155 }
156
157 // If we have an empty partition, or if we have a partition which
158 // does not include any of the subdomains of a subdomain-restricted
159 // variable, then we do not have access to that variable! Hopefully
160 // we won't need the indices we lack.
162 {
163 current_solution.get(_dof_indices, &_u[0]);
164 if (_need_u_old)
166 if (_need_u_older)
168
169 for (auto tag : _required_vector_tags)
171 safe_access_tagged_vectors) ||
173 if (sys.hasVector(tag) && _need_vector_tag_u[tag])
175
176 if (safe_access_tagged_matrices)
177 for (auto tag : active_coupleable_matrix_tags)
178 if (sys.hasMatrix(tag) && sys.getMatrix(tag).closed() && _need_matrix_tag_u[tag])
179 for (std::size_t i = 0; i != n; ++i)
180 _matrix_tag_u[tag][i] = sys.getMatrix(tag)(_dof_indices[i], _dof_indices[i]);
181
182 if (_need_u_dot)
183 (*u_dot).get(_dof_indices, &_u_dot[0]);
184
185 if (_need_u_dotdot)
186 (*u_dotdot).get(_dof_indices, &_u_dotdot[0]);
187
188 if (_need_u_dot_old)
189 (*u_dot_old).get(_dof_indices, &_u_dot_old[0]);
190
192 (*u_dotdot_old).get(_dof_indices, &_u_dotdot_old[0]);
193 }
194 else
195 {
196 for (std::size_t i = 0; i != n; ++i)
197 {
198 const dof_id_type dof_index = _dof_indices[i];
199 std::vector<dof_id_type> one_dof_index(1, dof_index);
200 if (_dof_map.all_semilocal_indices(one_dof_index))
201 {
202 libmesh_assert_less(i, _u.size());
203
204 current_solution.get(one_dof_index, &_u[i]);
205 if (_need_u_old)
206 sys.solutionOld().get(one_dof_index, &_u_old[i]);
207 if (_need_u_older)
208 sys.solutionOlder().get(one_dof_index, &_u_older[i]);
209
210 if (safe_access_tagged_vectors)
211 {
212 for (auto tag : _required_vector_tags)
213 if (sys.hasVector(tag) && _need_vector_tag_u[tag])
214 sys.getVector(tag).get(one_dof_index, &_vector_tag_u[tag][i]);
215 }
216
217 if (safe_access_tagged_matrices)
218 for (auto tag : active_coupleable_matrix_tags)
219 if (sys.hasMatrix(tag) && sys.getMatrix(tag).closed() && _need_matrix_tag_u[tag])
220 _matrix_tag_u[tag][i] = sys.getMatrix(tag)(dof_index, dof_index);
221
222 if (_need_u_dot)
223 (*u_dot).get(one_dof_index, &_u_dot[i]);
224
225 if (_need_u_dotdot)
226 (*u_dotdot).get(one_dof_index, &_u_dotdot[i]);
227
228 if (_need_u_dot_old)
229 (*u_dot_old).get(one_dof_index, &_u_dot_old[i]);
230
232 (*u_dotdot_old).get(one_dof_index, &_u_dotdot_old[i]);
233 }
234 else
235 {
236#ifdef _GLIBCXX_DEBUG
237 // Let's make it possible to catch invalid accesses to these
238 // variables immediately via a thrown exception, if our
239 // libstdc++ compiler flags allow for that.
240 _u.resize(i);
241 if (_need_u_old)
242 _u_old.resize(i);
243 if (_need_u_older)
244 _u_older.resize(i);
245
246 for (auto tag : _required_vector_tags)
247 if (sys.hasVector(tag) && _need_vector_tag_u[tag])
248 _vector_tag_u[tag].resize(i);
249
250 for (auto tag : active_coupleable_matrix_tags)
251 if (sys.hasMatrix(tag) && sys.getMatrix(tag).closed() && _need_matrix_tag_u[tag])
252 _matrix_tag_u[tag].resize(i);
253
254 if (_need_u_dot)
255 _u_dot.resize(i);
256
257 if (_need_u_dotdot)
258 _u_dotdot.resize(i);
259
260 if (_need_u_dot_old)
261 _u_dot_old.resize(i);
262
264 _u_dotdot_old.resize(i);
265#else
266 // If we can't catch errors at run-time, we can at least
267 // propagate NaN values rather than invalid values, so that
268 // users won't trust the result.
269 _u[i] = std::numeric_limits<Real>::quiet_NaN();
270 if (_need_u_old)
271 _u_old[i] = std::numeric_limits<Real>::quiet_NaN();
272 if (_need_u_older)
273 _u_older[i] = std::numeric_limits<Real>::quiet_NaN();
274
275 for (auto tag : _required_vector_tags)
276 if (sys.hasVector(tag) && _need_vector_tag_u[tag])
277 _vector_tag_u[tag][i] = std::numeric_limits<Real>::quiet_NaN();
278
279 for (auto tag : active_coupleable_matrix_tags)
280 if (sys.hasMatrix(tag) && sys.getMatrix(tag).closed() && _need_matrix_tag_u[tag])
281 _matrix_tag_u[tag][i] = std::numeric_limits<Real>::quiet_NaN();
282
283 if (_need_u_dot)
284 _u_dot[i] = std::numeric_limits<Real>::quiet_NaN();
285
286 if (_need_u_dotdot)
287 _u_dotdot[i] = std::numeric_limits<Real>::quiet_NaN();
288
289 if (_need_u_dot_old)
290 _u_dot_old[i] = std::numeric_limits<Real>::quiet_NaN();
291
293 _u_dotdot_old[i] = std::numeric_limits<Real>::quiet_NaN();
294#endif
295 }
296 }
297 }
298
299 // Automatic differentiation
300 if (_need_ad)
301 computeAD(/*nodal_ordering=*/false);
302}
303
304void
306{
307 auto n_dofs = _dof_indices.size();
308 const bool do_derivatives =
309 ADReal::do_derivatives && _sys.number() == _subproblem.currentNlSysNum();
310
311 if (_need_ad_u)
312 {
313 _ad_u.resize(n_dofs);
314 for (MooseIndex(n_dofs) i = 0; i < n_dofs; ++i)
315 {
316 _ad_u[i] = _u[i];
317 if (do_derivatives)
318 Moose::derivInsert(_ad_u[i].derivatives(), _dof_indices[i], 1.);
319 }
320 }
321
322 if (_need_ad_u_dot)
323 {
324 _ad_u_dot.resize(n_dofs);
325 for (MooseIndex(n_dofs) i = 0; i < n_dofs; ++i)
326 {
327 _ad_u_dot[i] = _u_dot[i];
328 if (do_derivatives)
329 Moose::derivInsert(_ad_u_dot[i].derivatives(), _dof_indices[i], _du_dot_du[i]);
330 }
331 }
332}
333
334void
335MooseVariableScalar::setValue(unsigned int i, Number value)
336{
337// In debug modes, we might have set a "trap" to catch reads of
338// uninitialized values, but this trap shouldn't prevent setting
339// values.
340#ifdef DEBUG
341 if (i >= _u.size())
342 {
343 libmesh_assert_less(i, _dof_indices.size());
344 _u.resize(i + 1);
345 }
346#endif
347 _u[i] = value; // update variable value
348}
349
350void
352{
353 unsigned int n = _dof_indices.size();
354// In debug modes, we might have set a "trap" to catch reads of
355// uninitialized values, but this trap shouldn't prevent setting
356// values.
357#ifdef DEBUG
358 _u.resize(n);
359#endif
360 for (unsigned int i = 0; i < n; i++)
361 _u[i] = value;
362}
363
364void
365MooseVariableScalar::insert(NumericVector<Number> & soln)
366{
367 // We may have redundantly computed this value on many different
368 // processors, but only the processor which actually owns it should
369 // be saving it to the solution vector, to avoid O(N_scalar_vars)
370 // unnecessary communication.
371
372 const dof_id_type first_dof = _dof_map.first_dof();
373 const dof_id_type end_dof = _dof_map.end_dof();
374 if (_dof_indices.size() > 0 && first_dof <= _dof_indices[0] && _dof_indices[0] < end_dof)
375 soln.insert(&_u[0], _dof_indices);
376}
377
378const ADVariableValue &
380{
381 _need_ad = _need_ad_u = true;
382 return _ad_u;
383}
384
385const VariableValue &
387{
388 _need_u_old = true;
389 return _u_old;
390}
391
392const VariableValue &
394{
395 _need_u_older = true;
396 return _u_older;
397}
398
399const VariableValue &
401{
402 _need_vector_tag_u[tag] = true;
403 return _vector_tag_u[tag];
404}
405
406const VariableValue &
408{
409 _need_matrix_tag_u[tag] = true;
410 return _matrix_tag_u[tag];
411}
412
413const ADVariableValue &
415{
416 if (_sys.solutionUDot())
417 {
419 return _ad_u_dot;
420 }
421 else
422 mooseError("MooseVariableScalar: Time derivative of solution (`u_dot`) is not stored. Please "
423 "set uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
424}
425
426const VariableValue &
428{
429 if (_sys.solutionUDot())
430 {
431 _need_u_dot = true;
432 return _u_dot;
433 }
434 else
435 mooseError("MooseVariableScalar: Time derivative of solution (`u_dot`) is not stored. Please "
436 "set uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
437}
438
439const VariableValue &
441{
442 if (_sys.solutionUDotDot())
443 {
444 _need_u_dotdot = true;
445 return _u_dotdot;
446 }
447 else
448 mooseError("MooseVariableScalar: Second time derivative of solution (`u_dotdot`) is not "
449 "stored. Please set uDotDotRequested() to true in FEProblemBase before requesting "
450 "`u_dotdot`.");
451}
452
453const VariableValue &
455{
456 if (_sys.solutionUDotOld())
457 {
458 _need_u_dot_old = true;
459 return _u_dot_old;
460 }
461 else
462 mooseError("MooseVariableScalar: Old time derivative of solution (`u_dot_old`) is not "
463 "stored. Please set uDotOldRequested() to true in FEProblemBase before requesting "
464 "`u_dot_old`.");
465}
466
467const VariableValue &
469{
471 {
472 _need_u_dotdot_old = true;
473 return _u_dotdot_old;
474 }
475 else
476 mooseError("MooseVariableScalar: Old second time derivative of solution (`u_dotdot_old`) is "
477 "not stored. Please set uDotDotOldRequested() to true in FEProblemBase before "
478 "requesting `u_dotdot_old`.");
479}
480
481const VariableValue &
483{
484 _need_du_dot_du = true;
485 return _du_dot_du;
486}
487
488const VariableValue &
490{
491 _need_du_dotdot_du = true;
492 return _du_dotdot_du;
493}
494
495unsigned int
497{
498 if (_need_u_older)
499 return 2;
500 if (_need_u_old)
501 return 1;
502 return 0;
503}
504
506MooseVariableScalar::evaluate(const ElemArg & /*elem_arg*/, const Moose::StateArg & state) const
507{
508 return evaluate(state);
509}
510
512MooseVariableScalar::evaluate(const FaceArg & /*face*/, const Moose::StateArg & state) const
513{
514 return evaluate(state);
515}
516
518MooseVariableScalar::evaluate(const ElemQpArg & /*elem_qp*/, const Moose::StateArg & state) const
519{
520 return evaluate(state);
521}
522
525 const Moose::StateArg & state) const
526{
527 return evaluate(state);
528}
529
532 const Moose::StateArg & state) const
533{
534 return evaluate(state);
535}
536
538MooseVariableScalar::evaluate(const NodeArg & /*node_arg*/, const Moose::StateArg & state) const
539{
540 return evaluate(state);
541}
542
545{
546 mooseAssert(_dof_indices.size() == 1,
547 "MooseVariableScalar::evaluate may only be used for first-order scalar variables");
548
549 const auto & solution = getSolution(state);
550 ADReal value = solution(_dof_indices[0]);
551 if (state.state == 0 && Moose::doDerivatives(_subproblem, _sys))
552 Moose::derivInsert(value.derivatives(), _dof_indices[0], 1.0);
553
554 return value;
555}
556
559 const Moose::StateArg & /*state*/) const
560{
561 return 0;
562}
563
566 const Moose::StateArg & /*state*/) const
567{
568 return 0;
569}
570
573 const Moose::StateArg & /*state*/) const
574{
575 return 0;
576}
577
580 const Moose::StateArg & /*state*/) const
581{
582 return 0;
583}
584
587 const Moose::StateArg & /*state*/) const
588{
589 return 0;
590}
591
594 const Moose::StateArg & /*state*/) const
595{
596 return 0;
597}
DualNumber< Real, DNDerivativeType, true > ADReal
unsigned int TagID
Definition MooseTypes.h:238
OutputTools< Real >::VariableValue VariableValue
Definition MooseTypes.h:348
registerMooseObject("MooseApp", MooseVariableScalar)
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void resize(unsigned int size)
Change the number of elements the array can store.
Definition MooseArray.h:216
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
Base variable class.
unsigned int _var_num
variable number (from libMesh)
SubProblem & _subproblem
Problem this variable is part of.
static InputParameters validParams()
THREAD_ID _tid
Thread ID.
const libMesh::NumericVector< libMesh::Number > & getSolution(const Moose::StateArg &state) const
Get the solution corresponding to the provided state.
SystemBase & sys()
Get the system this variable is part of.
const libMesh::DofMap & _dof_map
DOF map.
std::vector< dof_id_type > _dof_indices
DOF indices.
SystemBase & _sys
System this variable is part of.
unsigned int number() const
Get variable number coming from libMesh.
Class for scalar variables (they are different).
const VariableValue & uDotOld() const
ADVariableValue _ad_u_dot
The first derivative of the scalar solution with derivative information.
const VariableValue & uDot() const
bool _need_ad_u_dot
whether ad_u_dot is needed
ADVariableValue _ad_u
The scalar solution with derivative information.
std::vector< bool > _need_vector_tag_u
Only cache data when need it.
MooseVariableScalar(const InputParameters &parameters)
const VariableValue & duDotDotDu() const
static InputParameters validParams()
const VariableValue & uDotDotOld() const
const ADVariableValue & adUDot() const
Return the first derivative of the solution with derivative information.
const VariableValue & duDotDu() const
const VariableValue & uDotDot() const
const VariableValue & matrixTagSln(TagID tag) const
std::set< TagID > _required_vector_tags
The set of vector tags we need to evaluate.
VariableValue _u_older
The older value of scalar variable.
std::vector< bool > _need_matrix_tag_u
Only cache data when need it.
const VariableValue & slnOld() const
void setValue(unsigned int i, Number value)
Set the nodal value for this variable (to keep everything up to date.
std::vector< VariableValue > _matrix_tag_u
Tagged matrices.
std::vector< VariableValue > _vector_tag_u
Tagged vectors.
bool _need_u_old
Whether or not the old solution is needed.
unsigned int oldestSolutionStateRequested() const
The oldest solution state that is requested for this variable (0 = current, 1 = old,...
bool _need_ad_u
whether ad_u is needed
GradientType evaluateGradient(const ElemArg &elem, const Moose::StateArg &state) const override final
Evaluate the functor gradient with a given element.
void insert(NumericVector< Number > &soln)
void reinit(bool reinit_for_derivative_reordering=false)
Fill out the VariableValue arrays from the system solution vector.
const VariableValue & slnOlder() const
virtual void sizeMatrixTagData() override
Size data structures related to matrix tagging.
bool _need_u_older
Whether or not the older solution is needed.
VariableValue _u_old
The old value of scalar variable.
void computeAD(bool nodal_ordering)
Adds derivative information to the scalar variable value arrays.
const ADVariableValue & adSln() const
Return the solution with derivative information.
VariableValue _u
The value of scalar variable.
ValueType evaluate(const ElemArg &elem, const Moose::StateArg &state) const override final
Evaluate the functor with a given element.
bool _need_ad
Whether any AD calculations are needed.
const VariableValue & vectorTagSln(TagID tag) const
void setValues(Number value)
Set all of the values of this scalar variable to the same value.
typename FunctorReturnType< ADReal, FunctorEvaluationKind::Gradient >::type GradientType
This rigmarole makes it so that a user can create functors that return containers (std::vector,...
virtual unsigned int currentNlSysNum() const =0
virtual Moose::VectorTagType vectorTagType(const TagID tag_id) const
Definition SubProblem.C:232
virtual bool safeAccessTaggedMatrices() const
Is it safe to access the tagged matrices.
Definition SubProblem.h:739
virtual unsigned int numMatrixTags() const
The total number of tags.
Definition SubProblem.h:248
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:196
const std::set< TagID > & getActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid) const
Definition SubProblem.C:432
virtual bool safeAccessTaggedVectors() const
Is it safe to access the tagged vectors.
Definition SubProblem.h:742
Base class for a system (of equations)
Definition SystemBase.h:87
virtual const NumericVector< Number > *const & currentSolution() const =0
The solution vector that is currently being operated on.
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
bool hasVector(const std::string &tag_name) const
Check if the named vector exists in the system.
Definition SystemBase.C:923
virtual NumericVector< Number > * solutionUDot()
Definition SystemBase.h:280
unsigned int number() const
Gets the number of this system.
virtual NumericVector< Number > & getVector(const std::string &name)
Get a raw NumericVector by name.
Definition SystemBase.C:932
NumericVector< Number > & solutionOld()
Definition SystemBase.h:204
SubProblem & subproblem()
Definition SystemBase.h:102
virtual NumericVector< Number > * solutionUDotOld()
Definition SystemBase.h:282
virtual const Number & duDotDu(unsigned int var_num=0) const
NumericVector< Number > & solutionOlder()
Definition SystemBase.h:205
virtual bool hasMatrix(TagID tag) const
Check if the tagged matrix exists in the system.
Definition SystemBase.h:379
virtual NumericVector< Number > * solutionUDotDotOld()
Definition SystemBase.h:283
virtual Number & duDotDotDu()
Definition SystemBase.h:276
virtual NumericVector< Number > * solutionUDotDot()
Definition SystemBase.h:281
dof_id_type first_dof(const processor_id_type proc) const
dof_id_type end_dof(const processor_id_type proc) const
bool all_semilocal_indices(const std::vector< dof_id_type > &dof_indices) const
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
virtual bool closed() const=0
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
bool doDerivatives(const SubProblem &subproblem, const SystemBase &sys)
Definition ADUtils.C:83
@ VECTOR_TAG_SOLUTION
@ VECTOR_TAG_RESIDUAL
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N > > &derivs, libMesh::dof_id_type index, Real value)
Definition ADReal.h:21
A structure that is used to evaluate Moose functors logically at an element/cell center.
A structure that is used to evaluate Moose functors at an arbitrary physical point contained within a...
Argument for requesting functor evaluation at a quadrature point location in an element.
Argument for requesting functor evaluation at quadrature point locations on an element side.
A structure defining a "face" evaluation calling argument for Moose functors.
State argument for evaluating functors.
unsigned int state
The state.