https://mooseframework.inl.gov
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  _need_u_dot(false),
36  _need_u_dotdot(false),
37  _need_u_dot_old(false),
38  _need_u_dotdot_old(false),
39  _need_du_dot_du(false),
40  _need_du_dotdot_du(false),
41  _need_u_old(false),
42  _need_u_older(false),
43  _need_ad(false),
44  _need_ad_u(false),
45  _need_ad_u_dot(false)
46 {
47  auto num_vector_tags = _sys.subproblem().numVectorTags();
48 
49  _vector_tag_u.resize(num_vector_tags);
50  _need_vector_tag_u.resize(num_vector_tags);
51 }
52 
53 void
55 {
56  auto num_matrix_tags = _sys.subproblem().numMatrixTags();
57 
58  _matrix_tag_u.resize(num_matrix_tags);
59  _need_matrix_tag_u.resize(num_matrix_tags);
60 }
61 
63 {
64  _u.release();
65  _u_old.release();
66  _u_older.release();
67 
68  _u_dot.release();
69  _u_dotdot.release();
70  _u_dot_old.release();
71  _u_dotdot_old.release();
72  _du_dot_du.release();
73  _du_dotdot_du.release();
74 
75  for (auto & _tag_u : _vector_tag_u)
76  _tag_u.release();
77 
78  _vector_tag_u.clear();
79 
80  for (auto & _tag_u : _matrix_tag_u)
81  _tag_u.release();
82 
83  _matrix_tag_u.clear();
84 }
85 
86 void
87 MooseVariableScalar::reinit(bool reinit_for_derivative_reordering /* = false*/)
88 {
89  if (reinit_for_derivative_reordering)
90  {
91  // We've already calculated everything in an earlier reinit. All we have to do is re-sort the
92  // derivative vector for AD calculations
93  if (_need_ad)
94  computeAD(/*nodal_ordering=*/true);
95  return;
96  }
97 
98  // We want to make sure that we're not allocating data with any of the
99  // accessors that follow, but _sys is non-const
100  const SystemBase & sys = _sys;
101 
102  const NumericVector<Real> & current_solution = *sys.currentSolution();
103  const NumericVector<Real> * u_dot = sys.solutionUDot();
104  const NumericVector<Real> * u_dotdot = sys.solutionUDotDot();
105  const NumericVector<Real> * u_dot_old = sys.solutionUDotOld();
106  const NumericVector<Real> * u_dotdot_old = sys.solutionUDotDotOld();
107  const Real & du_dot_du = sys.duDotDu(number());
108  const Real & du_dotdot_du = sys.duDotDotDu();
109  auto safe_access_tagged_vectors = sys.subproblem().safeAccessTaggedVectors();
110  auto safe_access_tagged_matrices = sys.subproblem().safeAccessTaggedMatrices();
111  auto & active_coupleable_matrix_tags =
113 
115 
116  auto n = _dof_indices.size();
117  _u.resize(n);
118  if (_need_u_old)
119  _u_old.resize(n);
120  if (_need_u_older)
121  _u_older.resize(n);
122 
123  for (auto & _tag_u : _vector_tag_u)
124  _tag_u.resize(n);
125 
126  for (auto & _tag_u : _matrix_tag_u)
127  _tag_u.resize(n);
128 
129  _du_dot_du.clear();
130  _du_dot_du.resize(n, du_dot_du);
131 
132  if (_need_u_dot)
133  _u_dot.resize(n);
134 
135  if (_need_u_dotdot)
136  _u_dotdot.resize(n);
137 
138  if (_need_u_dot_old)
139  _u_dot_old.resize(n);
140 
141  if (_need_u_dotdot_old)
142  _u_dotdot_old.resize(n);
143 
144  if (_need_du_dot_du)
145  {
146  _du_dot_du.clear();
147  _du_dot_du.resize(n, du_dot_du);
148  }
149 
150  if (_need_du_dotdot_du)
151  {
152  _du_dotdot_du.clear();
153  _du_dotdot_du.resize(n, du_dotdot_du);
154  }
155 
156  // If we have an empty partition, or if we have a partition which
157  // does not include any of the subdomains of a subdomain-restricted
158  // variable, then we do not have access to that variable! Hopefully
159  // we won't need the indices we lack.
161  {
162  current_solution.get(_dof_indices, &_u[0]);
163  if (_need_u_old)
165  if (_need_u_older)
167 
168  for (auto tag : _required_vector_tags)
170  safe_access_tagged_vectors) ||
172  if (sys.hasVector(tag) && _need_vector_tag_u[tag])
173  sys.getVector(tag).get(_dof_indices, &_vector_tag_u[tag][0]);
174 
175  if (safe_access_tagged_matrices)
176  {
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  {
181  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
182  _matrix_tag_u[tag][i] = sys.getMatrix(tag)(_dof_indices[i], _dof_indices[i]);
183  }
184  }
185 
186  if (_need_u_dot)
187  (*u_dot).get(_dof_indices, &_u_dot[0]);
188 
189  if (_need_u_dotdot)
190  (*u_dotdot).get(_dof_indices, &_u_dotdot[0]);
191 
192  if (_need_u_dot_old)
193  (*u_dot_old).get(_dof_indices, &_u_dot_old[0]);
194 
195  if (_need_u_dotdot_old)
196  (*u_dotdot_old).get(_dof_indices, &_u_dotdot_old[0]);
197  }
198  else
199  {
200  for (std::size_t i = 0; i != n; ++i)
201  {
202  const dof_id_type dof_index = _dof_indices[i];
203  std::vector<dof_id_type> one_dof_index(1, dof_index);
204  if (_dof_map.all_semilocal_indices(one_dof_index))
205  {
206  libmesh_assert_less(i, _u.size());
207 
208  current_solution.get(one_dof_index, &_u[i]);
209  if (_need_u_old)
210  sys.solutionOld().get(one_dof_index, &_u_old[i]);
211  if (_need_u_older)
212  sys.solutionOlder().get(one_dof_index, &_u_older[i]);
213 
214  if (safe_access_tagged_vectors)
215  {
216  for (auto tag : _required_vector_tags)
217  if (sys.hasVector(tag) && _need_vector_tag_u[tag])
218  sys.getVector(tag).get(one_dof_index, &_vector_tag_u[tag][i]);
219  }
220 
221  if (safe_access_tagged_matrices)
222  {
223  for (auto tag : active_coupleable_matrix_tags)
224  if (sys.hasMatrix(tag) && sys.getMatrix(tag).closed() && _need_matrix_tag_u[tag])
225  {
226  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
227  _matrix_tag_u[tag][i] = sys.getMatrix(tag)(dof_index, dof_index);
228  }
229  }
230 
231  if (_need_u_dot)
232  (*u_dot).get(one_dof_index, &_u_dot[i]);
233 
234  if (_need_u_dotdot)
235  (*u_dotdot).get(one_dof_index, &_u_dotdot[i]);
236 
237  if (_need_u_dot_old)
238  (*u_dot_old).get(one_dof_index, &_u_dot_old[i]);
239 
240  if (_need_u_dotdot_old)
241  (*u_dotdot_old).get(one_dof_index, &_u_dotdot_old[i]);
242  }
243  else
244  {
245 #ifdef _GLIBCXX_DEBUG
246  // Let's make it possible to catch invalid accesses to these
247  // variables immediately via a thrown exception, if our
248  // libstdc++ compiler flags allow for that.
249  _u.resize(i);
250  if (_need_u_old)
251  _u_old.resize(i);
252  if (_need_u_older)
253  _u_older.resize(i);
254 
255  for (auto tag : _required_vector_tags)
256  if (sys.hasVector(tag) && _need_vector_tag_u[tag])
257  _vector_tag_u[tag].resize(i);
258 
259  for (auto tag : active_coupleable_matrix_tags)
260  if (sys.hasMatrix(tag) && sys.getMatrix(tag).closed() && _need_matrix_tag_u[tag])
261  _matrix_tag_u[tag].resize(i);
262 
263  if (_need_u_dot)
264  _u_dot.resize(i);
265 
266  if (_need_u_dotdot)
267  _u_dotdot.resize(i);
268 
269  if (_need_u_dot_old)
270  _u_dot_old.resize(i);
271 
272  if (_need_u_dotdot_old)
273  _u_dotdot_old.resize(i);
274 #else
275  // If we can't catch errors at run-time, we can at least
276  // propagate NaN values rather than invalid values, so that
277  // users won't trust the result.
278  _u[i] = std::numeric_limits<Real>::quiet_NaN();
279  if (_need_u_old)
280  _u_old[i] = std::numeric_limits<Real>::quiet_NaN();
281  if (_need_u_older)
282  _u_older[i] = std::numeric_limits<Real>::quiet_NaN();
283 
284  for (auto tag : _required_vector_tags)
285  if (sys.hasVector(tag) && _need_vector_tag_u[tag])
286  _vector_tag_u[tag][i] = std::numeric_limits<Real>::quiet_NaN();
287 
288  for (auto tag : active_coupleable_matrix_tags)
289  if (sys.hasMatrix(tag) && sys.getMatrix(tag).closed() && _need_matrix_tag_u[tag])
290  _matrix_tag_u[tag][i] = std::numeric_limits<Real>::quiet_NaN();
291 
292  if (_need_u_dot)
293  _u_dot[i] = std::numeric_limits<Real>::quiet_NaN();
294 
295  if (_need_u_dotdot)
296  _u_dotdot[i] = std::numeric_limits<Real>::quiet_NaN();
297 
298  if (_need_u_dot_old)
299  _u_dot_old[i] = std::numeric_limits<Real>::quiet_NaN();
300 
301  if (_need_u_dotdot_old)
302  _u_dotdot_old[i] = std::numeric_limits<Real>::quiet_NaN();
303 #endif
304  }
305  }
306  }
307 
308  // Automatic differentiation
309  if (_need_ad)
310  computeAD(/*nodal_ordering=*/false);
311 }
312 
313 void
315 {
316  auto n_dofs = _dof_indices.size();
317  const bool do_derivatives =
318  ADReal::do_derivatives && _sys.number() == _subproblem.currentNlSysNum();
319 
320  if (_need_ad_u)
321  {
322  _ad_u.resize(n_dofs);
323  for (MooseIndex(n_dofs) i = 0; i < n_dofs; ++i)
324  {
325  _ad_u[i] = _u[i];
326  if (do_derivatives)
327  Moose::derivInsert(_ad_u[i].derivatives(), _dof_indices[i], 1.);
328  }
329  }
330 
331  if (_need_ad_u_dot)
332  {
333  _ad_u_dot.resize(n_dofs);
334  for (MooseIndex(n_dofs) i = 0; i < n_dofs; ++i)
335  {
336  _ad_u_dot[i] = _u_dot[i];
337  if (do_derivatives)
338  Moose::derivInsert(_ad_u_dot[i].derivatives(), _dof_indices[i], _du_dot_du[i]);
339  }
340  }
341 }
342 
343 void
344 MooseVariableScalar::setValue(unsigned int i, Number value)
345 {
346 // In debug modes, we might have set a "trap" to catch reads of
347 // uninitialized values, but this trap shouldn't prevent setting
348 // values.
349 #ifdef DEBUG
350  if (i >= _u.size())
351  {
352  libmesh_assert_less(i, _dof_indices.size());
353  _u.resize(i + 1);
354  }
355 #endif
356  _u[i] = value; // update variable value
357 }
358 
359 void
361 {
362  unsigned int n = _dof_indices.size();
363 // In debug modes, we might have set a "trap" to catch reads of
364 // uninitialized values, but this trap shouldn't prevent setting
365 // values.
366 #ifdef DEBUG
367  _u.resize(n);
368 #endif
369  for (unsigned int i = 0; i < n; i++)
370  _u[i] = value;
371 }
372 
373 void
375 {
376  // We may have redundantly computed this value on many different
377  // processors, but only the processor which actually owns it should
378  // be saving it to the solution vector, to avoid O(N_scalar_vars)
379  // unnecessary communication.
380 
381  const dof_id_type first_dof = _dof_map.first_dof();
382  const dof_id_type end_dof = _dof_map.end_dof();
383  if (_dof_indices.size() > 0 && first_dof <= _dof_indices[0] && _dof_indices[0] < end_dof)
384  soln.insert(&_u[0], _dof_indices);
385 }
386 
387 const ADVariableValue &
389 {
390  _need_ad = _need_ad_u = true;
391  return _ad_u;
392 }
393 
394 const VariableValue &
396 {
397  _need_u_old = true;
398  return _u_old;
399 }
400 
401 const VariableValue &
403 {
404  _need_u_older = true;
405  return _u_older;
406 }
407 
408 const VariableValue &
410 {
411  _need_vector_tag_u[tag] = true;
412  return _vector_tag_u[tag];
413 }
414 
415 const VariableValue &
417 {
418  _need_matrix_tag_u[tag] = true;
419  return _matrix_tag_u[tag];
420 }
421 
422 const ADVariableValue &
424 {
425  if (_sys.solutionUDot())
426  {
428  return _ad_u_dot;
429  }
430  else
431  mooseError("MooseVariableScalar: Time derivative of solution (`u_dot`) is not stored. Please "
432  "set uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
433 }
434 
435 const VariableValue &
437 {
438  if (_sys.solutionUDot())
439  {
440  _need_u_dot = true;
441  return _u_dot;
442  }
443  else
444  mooseError("MooseVariableScalar: Time derivative of solution (`u_dot`) is not stored. Please "
445  "set uDotRequested() to true in FEProblemBase before requesting `u_dot`.");
446 }
447 
448 const VariableValue &
450 {
451  if (_sys.solutionUDotDot())
452  {
453  _need_u_dotdot = true;
454  return _u_dotdot;
455  }
456  else
457  mooseError("MooseVariableScalar: Second time derivative of solution (`u_dotdot`) is not "
458  "stored. Please set uDotDotRequested() to true in FEProblemBase before requesting "
459  "`u_dotdot`.");
460 }
461 
462 const VariableValue &
464 {
465  if (_sys.solutionUDotOld())
466  {
467  _need_u_dot_old = true;
468  return _u_dot_old;
469  }
470  else
471  mooseError("MooseVariableScalar: Old time derivative of solution (`u_dot_old`) is not "
472  "stored. Please set uDotOldRequested() to true in FEProblemBase before requesting "
473  "`u_dot_old`.");
474 }
475 
476 const VariableValue &
478 {
479  if (_sys.solutionUDotDotOld())
480  {
481  _need_u_dotdot_old = true;
482  return _u_dotdot_old;
483  }
484  else
485  mooseError("MooseVariableScalar: Old second time derivative of solution (`u_dotdot_old`) is "
486  "not stored. Please set uDotDotOldRequested() to true in FEProblemBase before "
487  "requesting `u_dotdot_old`.");
488 }
489 
490 const VariableValue &
492 {
493  _need_du_dot_du = true;
494  return _du_dot_du;
495 }
496 
497 const VariableValue &
499 {
500  _need_du_dotdot_du = true;
501  return _du_dotdot_du;
502 }
503 
504 unsigned int
506 {
507  if (_need_u_older)
508  return 2;
509  if (_need_u_old)
510  return 1;
511  return 0;
512 }
static InputParameters validParams()
std::set< TagID > _required_vector_tags
The set of vector tags we need to evaluate.
virtual void insert(const Number *v, const std::vector< numeric_index_type > &dof_indices)
const VariableValue & uDotOld() const
virtual const NumericVector< Number > *const & currentSolution() const =0
The solution vector that is currently being operated on.
dof_id_type end_dof(const processor_id_type proc) const
const VariableValue & uDotDot() const
const ADVariableValue & adUDot() const
Return the first derivative of the solution with derivative information.
bool hasVector(const std::string &tag_name) const
Check if the named vector exists in the system.
Definition: SystemBase.C:916
void computeAD(bool nodal_ordering)
Adds derivative information to the scalar variable value arrays.
ADVariableValue _ad_u_dot
The first derivative of the scalar solution with derivative information.
unsigned int TagID
Definition: MooseTypes.h:210
virtual void get(const std::vector< numeric_index_type > &index, Number *values) const
void reinit(bool reinit_for_derivative_reordering=false)
Fill out the VariableValue arrays from the system solution vector.
unsigned int number() const
Get variable number coming from libMesh.
virtual unsigned int currentNlSysNum() const =0
bool _need_u_older
Whether or not the older solution is needed.
virtual bool safeAccessTaggedVectors() const
Is it safe to access the tagged vectors.
Definition: SubProblem.h:734
VariableValue _u
The value of scalar variable.
MooseVariableScalar(const InputParameters &parameters)
const VariableValue & slnOlder() const
bool _need_ad_u
whether ad_u is needed
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
ADVariableValue _ad_u
The scalar solution with derivative information.
virtual void sizeMatrixTagData() override
Size data structures related to matrix tagging.
const VariableValue & duDotDotDu() const
virtual bool hasMatrix(TagID tag) const
Check if the tagged matrix exists in the system.
Definition: SystemBase.h:360
VariableValue _u_older
The older value of scalar variable.
virtual NumericVector< Number > * solutionUDotDotOld()
Definition: SystemBase.h:264
NumericVector< Number > & solutionOlder()
Definition: SystemBase.h:198
const VariableValue & uDotDotOld() const
Base class for a system (of equations)
Definition: SystemBase.h:84
THREAD_ID _tid
Thread ID.
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
std::vector< dof_id_type > _dof_indices
DOF indices.
const std::set< TagID > & getActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid) const
Definition: SubProblem.C:431
std::vector< VariableValue > _vector_tag_u
Tagged vectors.
const VariableValue & slnOld() const
std::vector< bool > _need_vector_tag_u
Only cache data when need it.
registerMooseObject("MooseApp", MooseVariableScalar)
const VariableValue & uDot() const
const VariableValue & vectorTagSln(TagID tag) const
bool _need_ad
Whether any AD calculations are needed.
const libMesh::DofMap & _dof_map
DOF map.
virtual Number & duDotDotDu()
Definition: SystemBase.h:257
virtual const Number & duDotDu(unsigned int var_num=0) const
Definition: SystemBase.C:1693
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
SubProblem & _subproblem
Problem this variable is part of.
unsigned int oldestSolutionStateRequested() const
The oldest solution state that is requested for this variable (0 = current, 1 = old, 2 = older, etc).
SystemBase & _sys
System this variable is part of.
virtual NumericVector< Number > * solutionUDot()
Definition: SystemBase.h:261
static InputParameters validParams()
SubProblem & subproblem()
Definition: SystemBase.h:101
virtual NumericVector< Number > * solutionUDotOld()
Definition: SystemBase.h:263
virtual Moose::VectorTagType vectorTagType(const TagID tag_id) const
Definition: SubProblem.C:231
void setValue(unsigned int i, Number value)
Set the nodal value for this variable (to keep everything up to date.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
void setValues(Number value)
Set all of the values of this scalar variable to the same value.
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1149
std::vector< bool > _need_matrix_tag_u
Only cache data when need it.
const VariableValue & matrixTagSln(TagID tag) const
virtual bool closed() const=0
std::vector< VariableValue > _matrix_tag_u
Tagged matrices.
OutputTools< Real >::VariableValue VariableValue
Definition: MooseTypes.h:315
virtual unsigned int numMatrixTags() const
The total number of tags.
Definition: SubProblem.h:248
bool _need_ad_u_dot
whether ad_u_dot is needed
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:1016
const VariableValue & duDotDu() const
unsigned int _var_num
variable number (from libMesh)
bool _need_u_old
Whether or not the old solution is needed.
Class for scalar variables (they are different).
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:267
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:195
void insert(NumericVector< Number > &soln)
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N >> &derivs, libMesh::dof_id_type index, Real value)
Definition: ADReal.h:21
const ADVariableValue & adSln() const
Return the solution with derivative information.
bool all_semilocal_indices(const std::vector< dof_id_type > &dof_indices) const
dof_id_type first_dof(const processor_id_type proc) const
virtual bool safeAccessTaggedMatrices() const
Is it safe to access the tagged matrices.
Definition: SubProblem.h:731
Real Number
virtual NumericVector< Number > * solutionUDotDot()
Definition: SystemBase.h:262
NumericVector< Number > & solutionOld()
Definition: SystemBase.h:197
SystemBase & sys()
Get the system this variable is part of.
virtual NumericVector< Number > & getVector(const std::string &name)
Get a raw NumericVector by name.
Definition: SystemBase.C:925
Base variable class.
uint8_t dof_id_type
VariableValue _u_old
The old value of scalar variable.