https://mooseframework.inl.gov
Loading...
Searching...
No Matches
AuxKernel.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 "AuxKernel.h"
11
12// local includes
13#include "FEProblem.h"
14#include "SubProblem.h"
15#include "AuxiliarySystem.h"
16#include "MooseTypes.h"
17#include "Assembly.h"
19
20#include "libmesh/numeric_vector.h"
21#include "libmesh/dof_map.h"
22#include "libmesh/quadrature.h"
23#include "libmesh/boundary_info.h"
24
25template <typename ComputeValueType>
28{
31 if (typeid(AuxKernelTempl<ComputeValueType>).name() == typeid(VectorAuxKernel).name())
32 params.registerBase("VectorAuxKernel");
33 if (typeid(AuxKernelTempl<ComputeValueType>).name() == typeid(ArrayAuxKernel).name())
34 params.registerBase("ArrayAuxKernel");
35
36 params.registerSystemAttributeName("AuxKernel");
38 return params;
39}
40
41template <typename ComputeValueType>
43 : AuxKernelBase(parameters),
44 MooseVariableInterface<ComputeValueType>(
45 this,
46 parameters.getCheckedPointerParam<SystemBase *>("_sys")
47 ->getVariable(parameters.get<THREAD_ID>("_tid"),
48 parameters.get<AuxVariableName>("variable"))
49 .isNodal(),
50 "variable",
51 Moose::VarKindType::VAR_AUXILIARY,
52 std::is_same<Real, ComputeValueType>::value
53 ? Moose::VarFieldType::VAR_FIELD_STANDARD
54 : (std::is_same<RealVectorValue, ComputeValueType>::value
55 ? Moose::VarFieldType::VAR_FIELD_VECTOR
56 : Moose::VarFieldType::VAR_FIELD_ARRAY)),
57
58 _var(_aux_sys.getActualFieldVariable<ComputeValueType>(
59 _tid, parameters.get<AuxVariableName>("variable"))),
60 _nodal(_var.isNodal()),
61 _u(_nodal ? _var.nodalValueArray() : _var.sln()),
62
63 _test(_bnd ? _var.phiFace() : _var.phi()),
64 _q_point(_bnd ? _assembly.qPointsFace() : _assembly.qPoints()),
65 _qrule(_bnd ? _assembly.qRuleFace() : _assembly.qRule()),
66 _JxW(_bnd ? _assembly.JxWFace() : _assembly.JxW()),
67 _coord(_assembly.coordTransformation()),
68
69 _current_elem(_assembly.elem()),
70 _current_side(_assembly.side()),
71 _current_elem_volume(_assembly.elemVolume()),
72 _current_side_volume(_assembly.sideElemVolume()),
73
74 _current_node(_assembly.node()),
75 _current_boundary_id(_assembly.currentBoundaryID()),
76 _solution(_aux_sys.solution()),
77
78 _current_lower_d_elem(_assembly.lowerDElem())
79{
81 if (!_bnd || _nodal)
82 // If we're not boundary restricted then we cannot be a coincident lower-d calculation
83 _coincident_lower_d_calc = false;
84}
85
86template <typename ComputeValueType>
87const VariableValue &
88AuxKernelTempl<ComputeValueType>::coupledDot(const std::string & var_name, unsigned int comp) const
90 auto var = getVar(var_name, comp);
91 if (var->kind() == Moose::VAR_AUXILIARY)
93 name(),
94 ": Unable to couple time derivative of an auxiliary variable into the auxiliary system.");
95
96 return Coupleable::coupledDot(var_name, comp);
97}
98
99template <typename ComputeValueType>
100const VariableValue &
102 unsigned int comp) const
104 auto var = getVar(var_name, comp);
105 if (var->kind() == Moose::VAR_AUXILIARY)
107 name(),
108 ": Unable to couple time derivative of an auxiliary variable into the auxiliary system.");
109
110 return Coupleable::coupledDotDu(var_name, comp);
111}
112
113template <>
114void
116{
117 mooseAssert(_n_shapes == 1,
118 "Should only be calling setDofValue if there is one dof for the aux var");
119 _var.setDofValue(value, 0);
120}
121
122template <>
123void
125{
126 mooseError("Not implemented");
127}
128
129template <typename ComputeValueType>
130void
132{
133 mooseAssert(_coincident_lower_d_calc.has_value(),
134 "We should have set _coincident_lower_d_calc by now");
135 if (_coincident_lower_d_calc.value())
136 _var.insertLower(_aux_sys.solution());
137 else
138 _var.insert(_aux_sys.solution());
139}
140
141template <typename ComputeValueType>
142void
144{
145 precalculateValue();
146
147 if (isNodal()) /* nodal variables */
148 {
149 if (_var.isNodalDefined())
150 {
151 _qp = 0;
152 ComputeValueType value = computeValue();
153 // update variable data, which is referenced by other kernels, so the value is up-to-date
154 _var.setNodalValue(value);
155 }
156 }
157 else /* elemental variables */
158 {
159 _n_shapes =
160 _coincident_lower_d_calc.value() ? _var.dofIndicesLower().size() : _var.numberOfDofs();
161
162 if (_n_shapes == 1) /* p0 */
163 {
164 ComputeValueType value = 0;
165 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
166 value += _JxW[_qp] * _coord[_qp] * computeValue();
167 value /= (_bnd ? _current_side_volume : _current_elem_volume);
168 if (_var.isFV())
169 setDofValueHelper(value);
170 else
171 {
172 // update the variable data referenced by other kernels.
173 // Note that this will update the values at the quadrature points too
174 // (because this is an Elemental variable)
175 if (_coincident_lower_d_calc.value())
176 {
177 _local_sol.resize(1);
178 if constexpr (std::is_same<Real, ComputeValueType>::value)
179 _local_sol(0) = value;
180 else
181 mooseAssert(false, "We should not enter the single dof branch with a vector variable");
182 _var.setLowerDofValues(_local_sol);
183 }
184 else
185 _var.setNodalValue(value);
186 }
187 }
188 else /* high-order */
189 {
190 _local_re.resize(_n_shapes);
191 _local_re.zero();
192 _local_ke.resize(_n_shapes, _n_shapes);
193 _local_ke.zero();
194
195 const auto & test = _coincident_lower_d_calc.value() ? _var.phiLower() : _test;
196
197 // assemble the local mass matrix and the load
198 for (unsigned int i = 0; i < test.size(); i++)
199 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
200 {
201 ComputeValueType t = _JxW[_qp] * _coord[_qp] * test[i][_qp];
202 _local_re(i) += t * computeValue();
203 for (unsigned int j = 0; j < test.size(); j++)
204 _local_ke(i, j) += t * test[j][_qp];
205 }
206 // mass matrix is always SPD but in case of boundary restricted, it will be rank deficient
207 _local_sol.resize(_n_shapes);
208 if (_bnd)
209 _local_ke.svd_solve(_local_re, _local_sol);
210 else
211 _local_ke.cholesky_solve(_local_re, _local_sol);
212
213 _coincident_lower_d_calc.value() ? _var.setLowerDofValues(_local_sol)
214 : _var.setDofValues(_local_sol);
215 }
216 }
217}
218
219template <>
220void
222{
223 precalculateValue();
224
225 if (isNodal()) /* nodal variables */
226 {
227 if (_var.isNodalDefined())
228 {
229 _qp = 0;
230 RealEigenVector value = computeValue();
231 // update variable data, which is referenced by other kernels, so the value is up-to-date
232 _var.setNodalValue(value);
233 }
234 }
235 else /* elemental variables */
236 {
237 mooseAssert(
238 _var.numberOfDofs() % _var.count() == 0,
239 "The number of degrees of freedom should be cleanly divisible by the variable count");
240 _n_shapes = _var.numberOfDofs() / _var.count();
241 if (_n_shapes == 1) /* p0 */
242 {
243 RealEigenVector value = RealEigenVector::Zero(_var.count());
244 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
245 value += _JxW[_qp] * _coord[_qp] * computeValue();
246 value /= (_bnd ? _current_side_volume : _current_elem_volume);
247 // update the variable data referenced by other kernels.
248 // Note that this will update the values at the quadrature points too
249 // (because this is an Elemental variable)
250 _var.setNodalValue(value);
251 }
252 else /* high-order */
253 {
254 _local_re.resize(_n_shapes);
255 for (unsigned int i = 0; i < _local_re.size(); ++i)
256 _local_re(i) = RealEigenVector::Zero(_var.count());
257 _local_ke.resize(_n_shapes, _n_shapes);
258 _local_ke.zero();
259
260 // assemble the local mass matrix and the load
261 for (unsigned int i = 0; i < _test.size(); i++)
262 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
263 {
264 Real t = _JxW[_qp] * _coord[_qp] * _test[i][_qp];
265 _local_re(i) += t * computeValue();
266 for (unsigned int j = 0; j < _test.size(); j++)
267 _local_ke(i, j) += t * _test[j][_qp];
268 }
269
270 // mass matrix is always SPD
271 _local_sol.resize(_n_shapes);
272 for (unsigned int i = 0; i < _local_re.size(); ++i)
273 _local_sol(i) = RealEigenVector::Zero(_var.count());
274 DenseVector<Number> re(_n_shapes);
275 DenseVector<Number> sol(_n_shapes);
276 for (unsigned int i = 0; i < _var.count(); ++i)
277 {
278 for (unsigned int j = 0; j < _n_shapes; ++j)
279 re(j) = _local_re(j)(i);
280
281 if (_bnd)
282 _local_ke.svd_solve(re, sol);
283 else
284 _local_ke.cholesky_solve(re, sol);
285
286 for (unsigned int j = 0; j < _n_shapes; ++j)
287 _local_sol(j)(i) = sol(j);
288 }
289
290 _var.setDofValues(_local_sol);
291 }
292 }
293}
294
295template <typename ComputeValueType>
298{
299 if (_sys.solutionStatesInitialized())
300 mooseError("The solution states have already been initialized when calling ",
301 type(),
302 "::uOld().\n\n",
303 "Make sure to call uOld() within the object constructor.");
304
305 return _nodal ? _var.nodalValueOldArray() : _var.slnOld();
306}
307
308template <typename ComputeValueType>
311{
312 if (_sys.solutionStatesInitialized())
313 mooseError("The solution states have already been initialized when calling ",
314 type(),
315 "::uOlder().\n\n",
316 "Make sure to call uOlder() within the object constructor.");
317
318 return _nodal ? _var.nodalValueOlderArray() : _var.slnOlder();
319}
320
321template <typename ComputeValueType>
322bool
327
328template <typename ComputeValueType>
329void
331{
332 mooseAssert(_bnd && !isNodal(),
333 "We can never be a lower-dimensional calculation if we are not boundary restricted "
334 "or if we are a nodal auxiliary kernel");
335
336 // MOOSE maintains three copies of finite element data. One is for the current canonical element,
337 // one is for the element neighbor, and one is for a lower-d element. These three copies have
338 // supported all of MOOSE's finite element use cases to date, including mortar. For AuxKernel, we
339 // do not use the neighbor data copy, but we do use the other two copies. The numberOfDofs() API
340 // returns the number of degrees of freedom for the canonical element. If there are none, then
341 // there must be degrees of freedom associated with the lower-d element
342 _coincident_lower_d_calc = !_var.numberOfDofs();
343
344 if (_coincident_lower_d_calc.value())
345 {
346 static const std::string lower_error = "Make sure that the lower-d variable lives on a "
347 "lower-d block that is a superset of the boundary";
348 if (!_current_lower_d_elem)
349 mooseError("No lower-dimensional element. ", lower_error);
350 if (!_var.dofIndicesLower().size())
351 mooseError("No degrees of freedom. ", lower_error);
352 }
353}
354
355template <typename ComputeValueType>
356std::set<MooseVariableFieldBase *>
358 const libMesh::Node & node, const std::set<MooseVariableFieldBase *> & vars_to_check)
359{
360 if (node.n_dofs(_var.sys().number(), _var.number()))
361 return MooseVariableDependencyInterface::checkVariables(node, vars_to_check);
362 else
363 // the aux kernel early returns if _var has no dofs
364 return {};
365}
366
367// Explicitly instantiates the three versions of the AuxKernelTempl class
368template class AuxKernelTempl<Real>;
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
OutputTools< Real >::VariableValue VariableValue
Definition MooseTypes.h:348
unsigned int THREAD_ID
Definition MooseTypes.h:237
Base class for auxiliary kernels.
static InputParameters validParams()
Base class for creating new auxiliary kernels and auxiliary boundary conditions.
Definition AuxKernel.h:28
AuxKernelTempl(const InputParameters &parameters)
Definition AuxKernel.C:42
void insert()
Insert the just computed values into the auxiliary solution vector.
Definition AuxKernel.C:131
const OutputTools< ComputeValueType >::VariableValue & uOld() const
Retrieves the old value of the variable that this AuxKernel operates on.
Definition AuxKernel.C:297
virtual void compute() override
Computes the value and stores it in the solution vector.
Definition AuxKernel.C:143
void determineWhetherCoincidentLowerDCalc()
Determines whether we're a coincident lower-d calculation.
Definition AuxKernel.C:330
virtual const VariableValue & coupledDotDu(const std::string &var_name, unsigned int comp=0) const override
Time derivative of a coupled variable with respect to the coefficients.
Definition AuxKernel.C:101
virtual const VariableValue & coupledDot(const std::string &var_name, unsigned int comp=0) const override
Time derivative of a coupled variable.
Definition AuxKernel.C:88
bool isMortar()
Definition AuxKernel.C:323
void setDofValueHelper(const ComputeValueType &dof_value)
Currently only used when the auxiliary variable is a finite volume variable, this helps call through ...
const OutputTools< ComputeValueType >::VariableValue & uOlder() const
Retrieves the older value of the variable that this AuxKernel operates on.
Definition AuxKernel.C:310
virtual std::set< MooseVariableFieldBase * > checkVariables(const libMesh::Node &node, const std::set< MooseVariableFieldBase * > &vars_to_check) override
Check whether all of the supplied variables have degree of freedom indices on the supplied node.
Definition AuxKernel.C:357
static InputParameters validParams()
Definition AuxKernel.C:27
virtual const VariableValue & coupledDot(const std::string &var_name, unsigned int comp=0) const
Time derivative of a coupled variable.
virtual const VariableValue & coupledDotDu(const std::string &var_name, unsigned int comp=0) const
Time derivative of a coupled variable with respect to the coefficients.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void registerSystemAttributeName(const std::string &value)
This method is used to define the MOOSE system name that is used by the TheWarehouse object for stori...
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System.
forward declarations
Definition MooseArray.h:18
virtual std::set< MooseVariableFieldBase * > checkVariables(const libMesh::Node &node, const std::set< MooseVariableFieldBase * > &vars_to_check)
Check whether all of the supplied variables have degree of freedom indices on the supplied node.
Interface for objects that need to get values of MooseVariables.
Base class for creating new nodally-based mortar auxiliary kernels.
Base class for a system (of equations)
Definition SystemBase.h:87
unsigned int n_dofs(const unsigned int s, const unsigned int var=libMesh::invalid_uint) const
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
@ VAR_AUXILIARY
Definition MooseTypes.h:771