https://mooseframework.inl.gov
Loading...
Searching...
No Matches
NonlinearThread.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 "NonlinearThread.h"
11#include "NonlinearSystem.h"
12#include "Problem.h"
13#include "FEProblem.h"
14#include "KernelBase.h"
15#include "IntegratedBCBase.h"
16#include "DGKernelBase.h"
17#include "InterfaceKernelBase.h"
18#include "Material.h"
19#include "TimeKernel.h"
20#include "SwapBackSentinel.h"
21#include "FVTimeKernel.h"
23
24#include "libmesh/threads.h"
25
27 : ThreadedElementLoop<ConstElemRange>(fe_problem),
28 _nl(fe_problem.currentNonlinearSystem()),
29 _num_cached(0),
30 _integrated_bcs(_nl.getIntegratedBCWarehouse()),
31 _dg_kernels(_nl.getDGKernelWarehouse()),
32 _interface_kernels(_nl.getInterfaceKernelWarehouse()),
33 _kernels(_nl.getKernelWarehouse()),
34 _hdg_kernels(_nl.getHDGKernelWarehouse()),
35 _has_active_objects(_integrated_bcs.hasActiveObjects() || _dg_kernels.hasActiveObjects() ||
36 _interface_kernels.hasActiveObjects() || _kernels.hasActiveObjects() ||
37 _fe_problem.haveFV()),
38 _should_execute_dg(false)
39{
40}
41
42// Splitting Constructor
44 : ThreadedElementLoop<ConstElemRange>(x, split),
45 _nl(x._nl),
46 _num_cached(x._num_cached),
47 _integrated_bcs(x._integrated_bcs),
48 _dg_kernels(x._dg_kernels),
49 _interface_kernels(x._interface_kernels),
50 _kernels(x._kernels),
51 _tag_kernels(x._tag_kernels),
52 _hdg_kernels(x._hdg_kernels),
53 _has_active_objects(x._has_active_objects),
54 _should_execute_dg(x._should_execute_dg)
55{
56}
57
59
60void
61NonlinearThread::operator()(const ConstElemRange & range, bool bypass_threading)
62{
65}
66
67void
69{
70 // This should come first to setup the residual objects before we do dependency determination of
71 // material properties and variables
73
75
76 // Update variable Dependencies
77 std::set<MooseVariableFEBase *> needed_moose_vars;
82
83 // Update FE variable coupleable vector tags
84 std::set<TagID> needed_fe_var_vector_tags;
86 _subdomain, needed_fe_var_vector_tags, _tid);
88 _subdomain, needed_fe_var_vector_tags, _tid);
90 _subdomain, needed_fe_var_vector_tags, _tid);
92 // Update material dependencies
93 std::unordered_set<unsigned int> needed_mat_props;
98
99 if (_fe_problem.haveFV())
100 {
101 // Re-query the finite volume elemental kernels
102 _fv_kernels.clear();
104 .query()
105 .template condition<AttribSysNum>(_nl.number())
106 .template condition<AttribSystem>("FVElementalKernel")
107 .template condition<AttribSubdomains>(_subdomain)
108 .template condition<AttribThread>(_tid)
110 for (const auto fv_kernel : _fv_kernels)
111 {
112 const auto & fv_mv_deps = fv_kernel->getMooseVariableDependencies();
113 needed_moose_vars.insert(fv_mv_deps.begin(), fv_mv_deps.end());
114 const auto & fv_mp_deps = fv_kernel->getMatPropDependencies();
115 needed_mat_props.insert(fv_mp_deps.begin(), fv_mp_deps.end());
116 }
117 }
118
119 // Cache these to avoid computing them on every side
122
124 _fe_problem.setActiveFEVariableCoupleableVectorTags(needed_fe_var_vector_tags, _tid);
125 _fe_problem.prepareMaterials(needed_mat_props, _subdomain, _tid);
126}
127
128void
129NonlinearThread::onElement(const Elem * const elem)
130{
131 // Set up Sentinel class so that, even if reinitMaterials() throws in prepareElement, we
132 // still remember to swap back during stack unwinding.
134
135 prepareElement(elem);
136
137 if (dynamic_cast<ComputeJacobianThread *>(this))
138 if (_nl.getScalarVariables(_tid).size() > 0)
140
142}
143
144void
146{
148 {
149 const auto & kernels = _tag_kernels->getActiveBlockObjects(_subdomain, _tid);
150 for (const auto & kernel : kernels)
151 compute(*kernel);
152 }
153
154 if (_fe_problem.haveFV())
155 for (auto kernel : _fv_kernels)
156 compute(*kernel);
157}
158
159void
160NonlinearThread::onBoundary(const Elem * const elem,
161 const unsigned int side,
162 const BoundaryID bnd_id,
163 const Elem * const lower_d_elem /*=nullptr*/)
164{
166 {
167 // Set up Sentinel class so that, after we swap in reinitMaterialsFace in prepareFace, even if
168 // one of our callees throws we remember to swap back during stack unwinding. We put our
169 // sentinel here as opposed to in prepareFace because we certainly don't want our materials
170 // swapped back before we proceed to residual/Jacobian computation
172
173 prepareFace(elem, side, bnd_id, lower_d_elem);
174 computeOnBoundary(bnd_id, lower_d_elem);
175
176 if (lower_d_elem)
178 }
179}
180
181void
182NonlinearThread::computeOnBoundary(BoundaryID bnd_id, const Elem * /*lower_d_elem*/)
183{
184 const auto & bcs = _ibc_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
185 for (const auto & bc : bcs)
186 if (bc->shouldApply())
187 compute(*bc);
188}
189
190void
191NonlinearThread::onInterface(const Elem * elem, unsigned int side, BoundaryID bnd_id)
192{
194 {
195
196 // Pointer to the neighbor we are currently working on.
197 const Elem * neighbor = elem->neighbor_ptr(side);
198
199 if (neighbor->active())
200 {
201 _fe_problem.reinitNeighbor(elem, side, _tid);
202
203 // Set up Sentinels so that, even if one of the reinitMaterialsXXX() calls throws, we
204 // still remember to swap back during stack unwinding. Note that face, boundary, and interface
205 // all operate with the same MaterialData object
207 _fe_problem.reinitMaterialsFaceOnBoundary(bnd_id, elem->subdomain_id(), _tid);
209
211 _fe_problem.reinitMaterialsNeighborOnBoundary(bnd_id, neighbor->subdomain_id(), _tid);
212
213 // Has to happen after face and neighbor properties have been computed. Note that we don't use
214 // a sentinel here because FEProblem::swapBackMaterialsFace is going to handle face materials,
215 // boundary materials, and interface materials (e.g. it queries the boundary material data
216 // with the current element and side
218
219 computeOnInterface(bnd_id);
220
222 }
223 }
224}
225
226void
228{
229 const auto & int_ks = _ik_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
230 for (const auto & interface_kernel : int_ks)
231 compute(*interface_kernel);
232}
233
234void
235NonlinearThread::onInternalSide(const Elem * elem, unsigned int side)
236{
238 {
239 // Pointer to the neighbor we are currently working on.
240 const Elem * neighbor = elem->neighbor_ptr(side);
241
243
244 // Set up Sentinels so that, even if one of the reinitMaterialsXXX() calls throws, we
245 // still remember to swap back during stack unwinding.
247 _fe_problem.reinitMaterialsFace(elem->subdomain_id(), _tid);
248
250 _fe_problem.reinitMaterialsNeighbor(neighbor->subdomain_id(), _tid);
251
252 computeOnInternalFace(neighbor);
253
255 }
257 {
258 // Set up Sentinel class so that, after we swap in reinitMaterialsFace in prepareFace, even if
259 // one of our callees throws we remember to swap back during stack unwinding. We put our
260 // sentinel here as opposed to in prepareFace because we certainly don't want our materials
261 // swapped back before we proceed to residual/Jacobian computation
263
264 prepareFace(elem, side, Moose::INVALID_BOUNDARY_ID, nullptr);
266 }
267}
268
269void
270NonlinearThread::onExternalSide(const Elem * elem, unsigned int side)
271{
272 // Check that we don't have any interface kernels defined on this boundary
273 const auto boundary_ids = _mesh.getBoundaryIDs(elem, side);
274
275 bool has_interface_kernels = false;
276 for (const auto bid : boundary_ids)
278 has_interface_kernels = true;
279
280 if (has_interface_kernels)
281 mooseError("Element ",
282 elem->id(),
283 " on side ",
284 side,
285 " is missing a neighbor (hence identified as an external side) but "
286 "has interface kernel(s) defined on the boundary.");
287}
288
289void
291{
292 const auto & dgks = _dg_warehouse->getActiveBlockObjects(_subdomain, _tid);
293 for (const auto & dg_kernel : dgks)
294 if (dg_kernel->hasBlocks(neighbor->subdomain_id()))
295 compute(*dg_kernel, neighbor);
296}
297
298void
300{
301 compute(static_cast<ResidualObject &>(kernel));
302}
303
304void
306{
307 compute(static_cast<ResidualObject &>(kernel));
308}
309
310void
312{
313 compute(static_cast<ResidualObject &>(bc));
314}
315
316void
317NonlinearThread::compute(DGKernelBase & dg, const Elem * /*neighbor*/)
318{
319 compute(static_cast<ResidualObject &>(dg));
320}
321
322void
327
328void
329NonlinearThread::postElement(const Elem * /*elem*/)
330{
331 accumulate();
332}
333
334void
339
340void
342{
344 {
345 const auto & console = _fe_problem.console();
346 const auto execute_on = _fe_problem.getCurrentExecuteOnFlag();
347 console << "[DBG] Beginning elemental loop to compute " + objectType() + " on " << execute_on
348 << std::endl;
349 mooseDoOnce(
350 console << "[DBG] Execution order on each element:" << std::endl;
351 console << "[DBG] - kernels on element quadrature points" << std::endl;
352 console << "[DBG] - finite volume elemental kernels on element" << std::endl;
353 console << "[DBG] - integrated boundary conditions on element side quadrature points"
354 << std::endl;
355 console << "[DBG] - DG kernels on element side quadrature points" << std::endl;
356 console << "[DBG] - interface kernels on element side quadrature points" << std::endl;);
357 }
358}
359
360void
362{
363 // Number of objects executing is approximated by size of warehouses
364 const int num_objects = _kernels.size() + _fv_kernels.size() + _integrated_bcs.size() +
366 const auto & console = _fe_problem.console();
367 const auto block_name = _mesh.getSubdomainName(_subdomain);
368
369 if (_fe_problem.shouldPrintExecution(_tid) && num_objects > 0)
370 {
372 return;
373 console << "[DBG] Ordering of " + objectType() + " Objects on block " << block_name << " ("
374 << _subdomain << ")" << std::endl;
376 {
377 console << "[DBG] Ordering of kernels:" << std::endl;
378 console << _kernels.activeObjectsToFormattedString() << std::endl;
379 }
380 if (_fv_kernels.size())
381 {
382 console << "[DBG] Ordering of FV elemental kernels:" << std::endl;
383 std::string fvkernels =
384 std::accumulate(_fv_kernels.begin() + 1,
385 _fv_kernels.end(),
386 _fv_kernels[0]->name(),
387 [](const std::string & str_out, FVElementalKernel * kernel)
388 { return str_out + " " + kernel->name(); });
389 console << ConsoleUtils::formatString(fvkernels, "[DBG]") << std::endl;
390 }
392 {
393 console << "[DBG] Ordering of DG kernels:" << std::endl;
394 console << _dg_kernels.activeObjectsToFormattedString() << std::endl;
395 }
396 }
397 else if (_fe_problem.shouldPrintExecution(_tid) && num_objects == 0 &&
399 console << "[DBG] No Active " + objectType() + " Objects on block " << block_name << " ("
400 << _subdomain << ")" << std::endl;
401
403}
404
405void
407{
411 return;
412
413 const auto & console = _fe_problem.console();
414 const auto b_name = _mesh.getBoundaryName(bid);
415 console << "[DBG] Ordering of " + objectType() + " Objects on boundary " << b_name << " (" << bid
416 << ")" << std::endl;
417
419 {
420 console << "[DBG] Ordering of integrated boundary conditions:" << std::endl;
421 console << _integrated_bcs.activeObjectsToFormattedString() << std::endl;
422 }
423
424 // We have not checked if we have a neighbor. This could be premature for saying we are executing
425 // interface kernels. However, we should assume the execution will happen on another side of the
426 // same boundary
428 {
429 console << "[DBG] Ordering of interface kernels:" << std::endl;
430 console << _interface_kernels.activeObjectsToFormattedString() << std::endl;
431 }
432
433 _boundaries_exec_printed.insert(bid);
434}
435
436void
437NonlinearThread::prepareFace(const Elem * const elem,
438 const unsigned int side,
439 const BoundaryID bnd_id,
440 const Elem * const lower_d_elem)
441{
442 _fe_problem.reinitElemFace(elem, side, _tid);
443
444 // Needed to use lower-dimensional variables on Materials
445 if (lower_d_elem)
446 _fe_problem.reinitLowerDElem(lower_d_elem, _tid);
447
448 if (bnd_id != Moose::INVALID_BOUNDARY_ID)
449 {
450 _fe_problem.reinitMaterialsFaceOnBoundary(bnd_id, elem->subdomain_id(), _tid);
452 }
453 // Currently only used by HDG
454 else
455 _fe_problem.reinitMaterialsFace(elem->subdomain_id(), _tid);
456}
457
458bool
459NonlinearThread::shouldComputeInternalSide(const Elem & elem, const Elem & neighbor) const
460{
461 // ThreadedElementLoop<ConstElemRange>::shouldComputeInternalSide gets expensive on high
462 // h-refinement cases so we avoid it if possible
463 _should_execute_dg = false;
468}
boundary_id_type BoundaryID
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
Serves as a base class for DGKernel and ADDGKernel.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual bool haveFV() const override
returns true if this problem includes/needs finite volume functionality.
void reinitMaterialsFace(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful=true, const std::deque< MaterialBase * > *reinit_mats=nullptr)
reinit materials on element faces
virtual void reinitOffDiagScalars(const THREAD_ID tid) override
virtual void swapBackMaterialsFace(const THREAD_ID tid)
const MaterialWarehouse & getMaterialWarehouse() const
virtual void reinitElemNeighborAndLowerD(const Elem *elem, unsigned int side, const THREAD_ID tid) override
void reinitMaterialsNeighbor(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful=true, const std::deque< MaterialBase * > *reinit_mats=nullptr)
reinit materials on the neighboring element face
virtual void swapBackMaterialsNeighbor(const THREAD_ID tid)
void prepareMaterials(const std::unordered_set< unsigned int > &consumer_needed_mat_props, const SubdomainID blk_id, const THREAD_ID tid)
Add the MooseVariables and the material properties that the current materials depend on to the depend...
void reinitElemFace(const Elem *elem, unsigned int side, BoundaryID, const THREAD_ID tid)
virtual void reinitLowerDElem(const Elem *lower_d_elem, const THREAD_ID tid, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr) override
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
void reinitMaterialsFaceOnBoundary(const BoundaryID boundary_id, const SubdomainID blk_id, const THREAD_ID tid, const bool swap_stateful=true, const std::deque< MaterialBase * > *const reinit_mats=nullptr)
reinit materials on element faces on a boundary (internal or external) This specific routine helps us...
void reinitMaterialsBoundary(BoundaryID boundary_id, const THREAD_ID tid, bool swap_stateful=true, const std::deque< MaterialBase * > *reinit_mats=nullptr)
reinit materials on a boundary
virtual void setActiveElementalMooseVariables(const std::set< MooseVariableFEBase * > &moose_vars, const THREAD_ID tid) override
Set the MOOSE variables to be reinited on each element.
virtual void swapBackMaterials(const THREAD_ID tid)
virtual void setActiveFEVariableCoupleableVectorTags(std::set< TagID > &vtags, const THREAD_ID tid) override
bool shouldPrintExecution(const THREAD_ID tid) const
Check whether the problem should output execution orders at this time.
TheWarehouse & theWarehouse() const
virtual void subdomainSetup(SubdomainID subdomain, const THREAD_ID tid)
void reinitMaterialsNeighborOnBoundary(const BoundaryID boundary_id, const SubdomainID blk_id, const THREAD_ID tid, const bool swap_stateful=true, const std::deque< MaterialBase * > *const reinit_mats=nullptr)
reinit materials on neighbor element (usually faces) on a boundary (internal or external) This specif...
void reinitMaterialsInterface(BoundaryID boundary_id, const THREAD_ID tid, bool swap_stateful=true)
virtual void reinitNeighbor(const Elem *elem, unsigned int side, const THREAD_ID tid) override
FVElemental is used for calculating residual contributions from volume integral terms of a PDE where ...
Base class for deriving any boundary condition of a integrated type.
InterfaceKernelBase is the base class for all InterfaceKernel type classes.
This is the common base class for the three main kernel types implemented in MOOSE,...
Definition KernelBase.h:29
const std::string & getBoundaryName(const BoundaryID boundary_id) const
Return the name of the boundary given the id.
Definition MooseMesh.C:1780
const std::string & getSubdomainName(SubdomainID subdomain_id) const
Return the name of a block given an id.
Definition MooseMesh.C:1751
std::vector< BoundaryID > getBoundaryIDs(const Elem *const elem, const unsigned short int side) const
Returns a vector of boundary IDs for the requested element on the requested side.
Definition MooseMesh.C:3027
unsigned int size(THREAD_ID tid=0) const
Return how many kernels we store in the current warehouse.
std::string activeObjectsToFormattedString(THREAD_ID tid=0, const std::string &prefix="[DBG]") const
Output the active content of the warehouse to a string, meant to be output to the console.
const std::map< SubdomainID, std::vector< std::shared_ptr< T > > > & getActiveBlockObjects(THREAD_ID tid=0) const
void updateBlockMatPropDependency(SubdomainID id, std::unordered_set< unsigned int > &needed_mat_props, THREAD_ID tid=0, const bool producer_only=false) const
void updateBlockFEVariableCoupledVectorTagDependency(SubdomainID id, std::set< TagID > &needed_fe_var_vector_tags, THREAD_ID tid=0) const
void updateBoundaryVariableDependency(std::set< MooseVariableFieldBase * > &needed_moose_vars, THREAD_ID tid=0) const
void updateBlockVariableDependency(SubdomainID id, std::set< MooseVariableFieldBase * > &needed_moose_vars, THREAD_ID tid=0) const
const std::map< BoundaryID, std::vector< std::shared_ptr< T > > > & getActiveBoundaryObjects(THREAD_ID tid=0) const
bool hasActiveBlockObjects(THREAD_ID tid=0) const
void updateBoundaryMatPropDependency(std::unordered_set< unsigned int > &needed_mat_props, THREAD_ID tid=0, const bool producer_only=false) const
bool hasActiveBoundaryObjects(THREAD_ID tid=0) const
MooseObjectTagWarehouse< KernelBase > & _kernels
virtual std::string objectType() const
Return what the loops is meant to compute.
virtual void onBoundary(const Elem *elem, unsigned int side, BoundaryID bnd_id, const Elem *lower_d_elem=nullptr) override
Called when doing boundary assembling.
bool shouldComputeInternalSide(const Elem &elem, const Elem &neighbor) const override
Whether to compute the internal side for the provided element-neighbor pair.
virtual void onInternalSide(const Elem *elem, unsigned int side) override
Called when doing internal edge assembling.
NonlinearThread(FEProblemBase &fe_problem)
MooseObjectTagWarehouse< IntegratedBCBase > & _integrated_bcs
Reference to BC storage structures.
virtual void accumulateNeighbor()=0
Add neighbor residual/Jacobian into assembly global data.
virtual void operator()(const ConstElemRange &range, bool bypass_threading=false) override
virtual void determineObjectWarehouses()=0
Determine the objects we will actually compute based on vector/matrix tag information.
virtual void computeOnInterface(BoundaryID bnd_id)
void prepareFace(const Elem *elem, unsigned int side, BoundaryID bnd_id=Moose::INVALID_BOUNDARY_ID, const Elem *lower_d_elem=nullptr)
Reinitialize variables and materials on a face.
MooseObjectWarehouse< InterfaceKernelBase > * _ik_warehouse
bool _subdomain_has_dg
Whether the subdomain has DGKernels.
virtual void computeOnBoundary(BoundaryID bnd_id, const Elem *lower_d_elem)
MooseObjectTagWarehouse< DGKernelBase > & _dg_kernels
Reference to DGKernel storage structure.
virtual void post() override
Called after the element range loop.
virtual void accumulateNeighborLower()=0
Add neighbor and lower residual/Jacobian into assembly global data.
void printBlockExecutionInformation() const override
Print list of specific objects executed on each block and in which order.
virtual void accumulate()=0
Add element residual/Jacobian into assembly global data.
virtual void onExternalSide(const Elem *elem, unsigned int side) override
Called when iterating over external sides (no side neighbor)
virtual void compute(ResidualObject &ro)=0
Will dispatch to computeResidual/computeJacobian/computeResidualAndJacobian based on the derived clas...
virtual void computeOnElement()
virtual void computeOnInternalFace()=0
std::vector< FVElementalKernel * > _fv_kernels
Current subdomain FVElementalKernels.
bool _subdomain_has_hdg
Whether the subdomain has HDGKernels.
NonlinearSystemBase & _nl
Reference to the underlying NonlinearSystemBase.
void printBoundaryExecutionInformation(const unsigned int bid) const override
Print list of specific objects executed on each boundary and in which order.
virtual void subdomainChanged() override
Called every time the current subdomain changes (i.e.
const bool _has_active_objects
Whether there are any active residual objects; otherwise we will do an early return.
MooseObjectWarehouse< DGKernelBase > * _dg_warehouse
MooseObjectWarehouse< HDGKernel > * _hdg_warehouse
MooseObjectWarehouse< KernelBase > * _tag_kernels
void printGeneralExecutionInformation() const override
Print information about the loop, mostly order of execution of objects.
virtual ~NonlinearThread()
MooseObjectTagWarehouse< InterfaceKernelBase > & _interface_kernels
Reference to interface kernel storage structure.
virtual void accumulateLower()=0
Add lower-d residual/Jacobian into assembly global data.
virtual void onInterface(const Elem *elem, unsigned int side, BoundaryID bnd_id) override
Called when doing interface assembling.
virtual void postElement(const Elem *) override
Called after the element assembly is done (including surface assembling)
MooseObjectWarehouse< IntegratedBCBase > * _ibc_warehouse
bool _should_execute_dg
Whether DG kernels should be executed for a given elem-neighbor pairing.
virtual void onElement(const Elem *elem) override
Assembly of the element (not including surface assembly)
const ConsoleStream & console() const
Return console handle.
Definition Problem.h:48
This is the common base class for objects that give residual contributions.
The "SwapBackSentinel" class's destructor guarantees that FEProblemBase::swapBackMaterials{Face,...
unsigned int number() const
Gets the number of this system.
const std::vector< MooseVariableScalar * > & getScalarVariables(THREAD_ID tid)
Definition SystemBase.h:777
std::vector< T * > & queryInto(std::vector< T * > &results, Args &&... args)
queryInto executes the query and stores the results in the given vector.
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse.
virtual void operator()(const RangeType &range, bool bypass_threading=false)
SubdomainID _subdomain
The subdomain for the current element.
std::set< BoundaryID > _boundaries_exec_printed
Keep track of which boundaries were visited.
virtual bool shouldComputeInternalSide(const Elem &elem, const Elem &neighbor) const
Whether to compute the internal side for the provided element-neighbor pair.
std::set< SubdomainID > _blocks_exec_printed
Keep track of which blocks were visited.
Base class for assembly-like calculations.
std::string formatString(std::string message, const std::string &prefix)
Add new lines and prefixes to a string for pretty display in output NOTE: This makes a copy of the st...
const BoundaryID INVALID_BOUNDARY_ID
Definition MooseTypes.C:22