Skip to content

Commit 52c5d71

Browse files
authored
Merge pull request #32701 from lindsayad/mfem-object-refactor-31434
Refactor MFEM objects away from MFEMGeneralUserObject
2 parents 217deaa + 1c3e5c0 commit 52c5d71

100 files changed

Lines changed: 1342 additions & 511 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

framework/doc/content/source/mfem/auxkernels/MFEMAuxKernel.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ Base class for MFEM auxkernels used to evaluate real auxiliary variables to the
88

99
## Overview
1010

11-
MFEM auxkernels are responsible for updating real auxiliary variables in the system, during pre- or
12-
post-processing steps.
11+
MFEM auxkernels are responsible for updating real auxiliary variables in the system during MFEM
12+
execution passes.
1313

14-
An `MFEMAuxKernel` is derived from `MFEMGeneralUserObject`, and thus the order of their execution
15-
can be controlled similar to other MOOSE UserObjects using the `execution_order_group` input
16-
parameter.
14+
An `MFEMAuxKernel` is derived from `MFEMExecutedObject`. Its ordering relative to other MFEM
15+
executed objects is determined automatically from detected data dependencies rather than by manual
16+
execution groups.
1717

1818
`MFEMAuxKernel` is a base class. Derived classes should override the `execute`
1919
method to update the `_result_var` during execution.

framework/doc/content/source/mfem/auxkernels/MFEMComplexAuxKernel.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ Base class for MFEM auxkernels used to evaluate complex auxiliary variables to t
88

99
## Overview
1010

11-
Complex MFEM auxkernels are responsible for updating complex auxiliary variables in the system, during pre- or
12-
post-processing steps.
11+
Complex MFEM auxkernels are responsible for updating complex auxiliary variables in the system
12+
during MFEM execution passes.
1313

14-
An `MFEMComplexAuxKernel` is derived from `MFEMGeneralUserObject`, and thus the order of their execution
15-
can be controlled similar to other MOOSE UserObjects using the `execution_order_group` input
16-
parameter.
14+
An `MFEMComplexAuxKernel` is derived from `MFEMExecutedObject`. Its ordering relative to other MFEM
15+
executed objects is determined automatically from detected data dependencies rather than by manual
16+
execution groups.
1717

1818
`MFEMComplexAuxKernel` is a base class. Derived classes should override the `execute`
1919
method to update the `_result_var` during execution.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# MFEMExecutedObject
2+
3+
!if! function=hasCapability('mfem')
4+
5+
## Overview
6+
7+
`MFEMExecutedObject` is the base class for MFEM objects that are scheduled and executed by
8+
[MFEMProblem](problem/MFEMProblem.md) during a solve. It derives from
9+
[MFEMObject](base/MFEMObject.md), `SetupInterface`, and `DependencyResolverInterface`.
10+
11+
## Execution ordering
12+
13+
Execution order among `MFEMExecutedObject` instances is determined automatically by
14+
`DependencyResolverInterface`: the MFEM scheduler builds a dependency graph from the variable,
15+
postprocessor, and vector postprocessor names that each object declares it consumes or produces,
16+
then performs a topological sort.
17+
18+
Derived class authors register dependency-bearing parameters at `validParams` time using the
19+
provided helpers:
20+
21+
- `addDependencyParam<T>` — adds an optional parameter whose value names a consumed resource.
22+
- `addRequiredDependencyParam<T>` — adds a required parameter whose value names a consumed resource.
23+
24+
The template parameter `T` must be one of `VariableName`, `std::vector<VariableName>`,
25+
`PostprocessorName`, `std::vector<PostprocessorName>`, `VectorPostprocessorName`, or
26+
`std::vector<VectorPostprocessorName>`. The scheduler infers the resource category from the type.
27+
28+
The resource supplied by this object is declared by overriding one of:
29+
30+
- `suppliedVariableName()` — name of the MFEM variable written by this object.
31+
- `suppliedPostprocessorName()` — name of the postprocessor written by this object.
32+
- `suppliedVectorPostprocessorName()` — name of the vector postprocessor written by this object.
33+
34+
Each returns `std::optional<std::string>`; return `std::nullopt` (the default) if the object supplies no resource in that category.
35+
36+
## Lifecycle methods
37+
38+
Each `MFEMExecutedObject` has three lifecycle methods that `MFEMProblem` calls in order for every
39+
execution pass:
40+
41+
| Method | Purpose |
42+
| - | - |
43+
| `initialize()` | Pre-execution setup (zero accumulators, clear state, etc.). |
44+
| `execute()` | Main work: read variables/coefficients, write results. |
45+
| `finalize()` | Post-execution cleanup or reduction (e.g., parallel reduction for postprocessors). |
46+
47+
All three have empty default implementations. Derived classes override whichever they need.
48+
49+
## Derived classes
50+
51+
The following MFEM object types derive from `MFEMExecutedObject`:
52+
53+
- [MFEMAuxKernel](auxkernels/MFEMAuxKernel.md) — updates real auxiliary variables.
54+
- [MFEMComplexAuxKernel](auxkernels/MFEMComplexAuxKernel.md) — updates complex auxiliary variables.
55+
- [MFEMPostprocessor](postprocessors/MFEMPostprocessor.md) — computes a scalar quantity.
56+
- [MFEMVectorPostprocessor](vectorpostprocessors/MFEMVectorPostprocessor.md) — computes an array of values.
57+
- [MFEMSubMeshTransfer](transfers/MFEMSubMeshTransfer.md) — transfers variable data between a mesh and a submesh.
58+
- `MFEMInitialCondition` — sets the initial value on an MFEM variable.
59+
60+
!if-end!
61+
62+
!else
63+
!include mfem/mfem_warning.md
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# MFEMObject
2+
3+
!if! function=hasCapability('mfem')
4+
5+
## Overview
6+
7+
`MFEMObject` is the common base class for all MFEM objects. It provides every MFEM object with a
8+
typed reference to the owning [MFEMProblem](problem/MFEMProblem.md) and a set of helpers for
9+
retrieving MFEM coefficients by name.
10+
11+
`MFEMObject` also mixes in `FunctionInterface`, `PostprocessorInterface`,
12+
`VectorPostprocessorInterface`, and `ReporterInterface` so that derived classes can consume MOOSE
13+
functions, postprocessors, vector postprocessors, and reporters in the normal way.
14+
15+
## Problem access
16+
17+
The `getMFEMProblem()` method returns a typed reference to the owning `MFEMProblem`.
18+
19+
## Coefficient access
20+
21+
MFEM coefficients declared through [MFEMFunctorMaterial](functormaterials/MFEMFunctorMaterial.md)
22+
objects are stored in the `CoefficientManager` owned by `MFEMProblem`. `MFEMObject` exposes two
23+
families of accessor methods for them:
24+
25+
| Method | Looks up by |
26+
| - | - |
27+
| `getScalarCoefficient(param_name)` | Value of an `MFEMScalarCoefficientName` input parameter |
28+
| `getVectorCoefficient(param_name)` | Value of an `MFEMVectorCoefficientName` input parameter |
29+
| `getMatrixCoefficient(param_name)` | Value of an `MFEMMatrixCoefficientName` input parameter |
30+
| `getScalarCoefficientByName(name)` | Declared coefficient name directly |
31+
| `getVectorCoefficientByName(name)` | Declared coefficient name directly |
32+
| `getMatrixCoefficientByName(name)` | Declared coefficient name directly |
33+
34+
The `param_name` variants are the most common: they read the coefficient name from an input
35+
parameter, so the caller does not need to extract the string itself.
36+
37+
## Derived classes
38+
39+
`MFEMObject` is the root of the MFEM object hierarchy. Direct subclasses include:
40+
41+
- [MFEMExecutedObject](base/MFEMExecutedObject.md) — objects that are scheduled and executed by `MFEMProblem` (aux kernels, postprocessors, transfers, initial conditions, etc.).
42+
- `MFEMSolverBase` — MFEM linear solver and preconditioner objects.
43+
- `MFEMKernel` / `MFEMComplexKernel` — weak-form contributions to the equation system.
44+
- `MFEMBoundaryCondition` — boundary conditions applied to the equation system.
45+
46+
!if-end!
47+
48+
!else
49+
!include mfem/mfem_warning.md

framework/doc/content/source/mfem/postprocessors/MFEMPostprocessor.md

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,12 @@ Base class for MFEM postprocessors used to evaluate a single scalar.
88

99
## Overview
1010

11-
MFEM postprocessors calculate scalar quantities from the
12-
(aux)variables, typically after each timestep.
11+
MFEM postprocessors calculate scalar quantities from the (aux)variables, typically after each
12+
timestep.
1313

14-
An `MFEMPostprocessor` is derived from `MFEMGeneralUserObject`.
15-
Therefore, the order of their execution can be controlled similar to other
16-
MOOSE UserObjects using the `execution_order_group` input parameter, e.g.,
17-
to require the execution of a postprocessor computing on an [AuxVariable.md]
18-
strictly after the execution of the [MFEMAuxKernel.md] computing the variable
19-
field itself. For example:
20-
21-
!listing mfem/kernels/irrotational.i block=AuxKernels Postprocessors/velocity_error
14+
An `MFEMPostprocessor` is derived from `MFEMExecutedObject`. Its ordering relative to MFEM initial
15+
conditions, aux kernels, transfers, and other MFEM postprocessors is determined automatically from
16+
detected data dependencies instead of manual execution groups.
2217

2318
`MFEMPostprocessor` is a purely virtual base class. Derived classes
2419
should override the `execute` and `getValue` methods.

framework/doc/content/source/mfem/userobjects/MFEMGeneralUserObject.md

Lines changed: 0 additions & 21 deletions
This file was deleted.

framework/doc/content/source/mfem/vectorpostprocessors/MFEMVectorPostprocessor.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@ Base class for MFEM vectorpostprocessors used to evaluate an array of values.
88

99
## Overview
1010

11-
MFEM vectorpostprocessors calculate an array of values from the (aux)variables,
12-
typically after each timestep.
13-
14-
An `MFEMVectorPostprocessor` is derived from `MFEMGeneralUserObject`.
15-
Therefore, the order of their execution can be controlled similar to other
16-
MOOSE UserObjects using the `execution_order_group` input parameter, e.g., to
17-
require the execution of a vectorpostprocessor computing on an [AuxVariable.md]
18-
strictly after the execution of the [MFEMAuxKernel.md] computing the variable
19-
field itself.
11+
MFEM vectorpostprocessors calculate an array of values from the (aux)variables, typically after
12+
each timestep.
13+
14+
An `MFEMVectorPostprocessor` is derived from `MFEMExecutedObject`. Its ordering relative to other
15+
MFEM executed objects is determined automatically from detected data dependencies instead of manual
16+
execution groups.
2017

2118
`MFEMVectorPostprocessor` is a virtual base class. Derived classes should use
2219
the `VectorPostprocessor::declareVector` method to get a reference to a vector

framework/include/base/MooseBase.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ class MooseBase : public ConsoleStreamInterface
157157
/**
158158
* Query a parameter for the object
159159
*
160-
* If the parameter is not valid, nullptr will be returned
161-
*
160+
* If a parameter of the given name and type does not exist or if the
161+
* parameter is not valid, nullptr will be returned
162162
* @param name The name of the parameter
163163
* @return A pointer to the parameter value, if it exists
164164
*/
@@ -192,6 +192,16 @@ class MooseBase : public ConsoleStreamInterface
192192
template <typename T>
193193
T getCheckedPointerParam(const std::string & name, const std::string & error_string = "") const;
194194

195+
/**
196+
* Test if a parameter of the given name and type exists
197+
* @param name The name of the parameter to test
198+
*/
199+
template <typename T>
200+
inline bool haveParameter(const std::string & name) const
201+
{
202+
return _pars.have_parameter<T>(name);
203+
}
204+
195205
/**
196206
* Test if the supplied parameter is valid
197207
* @param name The name of the parameter to test
@@ -412,7 +422,7 @@ template <typename T>
412422
const T *
413423
MooseBase::queryParam(const std::string & name) const
414424
{
415-
return isParamValid(name) ? &getParam<T>(name) : nullptr;
425+
return haveParameter<T>(name) && isParamValid(name) ? &getParam<T>(name) : nullptr;
416426
}
417427

418428
template <typename T>

framework/include/interfaces/DependencyResolverInterface.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ class DependencyResolverInterface
6565
/**
6666
* A helper method for cyclic errors.
6767
*/
68+
template <typename T, typename T2, typename NameFunc>
69+
static void cyclicDependencyError(CyclicDependencyException<T2> & e,
70+
const std::string & header,
71+
NameFunc && name_func);
72+
6873
template <typename T, typename T2>
6974
static void cyclicDependencyError(CyclicDependencyException<T2> & e, const std::string & header);
7075
};
@@ -124,18 +129,27 @@ DependencyResolverInterface::sortDFS(typename std::vector<T> & vector)
124129
vector = sorted;
125130
}
126131

127-
template <typename T, typename T2>
132+
template <typename T, typename T2, typename NameFunc>
128133
void
129134
DependencyResolverInterface::cyclicDependencyError(CyclicDependencyException<T2> & e,
130-
const std::string & header)
135+
const std::string & header,
136+
NameFunc && name_func)
131137
{
132138
std::ostringstream oss;
133139

134140
oss << header << ":\n";
135141
const auto cycle = e.getCyclicDependencies();
136142
std::vector<std::string> names(cycle.size());
137143
for (const auto i : index_range(cycle))
138-
names[i] = static_cast<T>(cycle[i])->name();
144+
names[i] = name_func(cycle[i]);
139145
oss << MooseUtils::join(names, " <- ");
140146
mooseError(oss.str());
141147
}
148+
149+
template <typename T, typename T2>
150+
void
151+
DependencyResolverInterface::cyclicDependencyError(CyclicDependencyException<T2> & e,
152+
const std::string & header)
153+
{
154+
cyclicDependencyError<T>(e, header, [](const auto & obj) { return static_cast<T>(obj)->name(); });
155+
}

framework/include/mfem/auxkernels/MFEMAuxKernel.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111

1212
#pragma once
1313

14-
#include "MFEMGeneralUserObject.h"
14+
#include "MFEMExecutedObject.h"
1515
#include "MFEMContainers.h"
1616

1717
/**
1818
* Class to construct an auxiliary solver used to update a real auxvariable.
1919
*/
20-
class MFEMAuxKernel : public MFEMGeneralUserObject
20+
class MFEMAuxKernel : public MFEMExecutedObject
2121
{
2222
public:
2323
static InputParameters validParams();
@@ -26,7 +26,9 @@ class MFEMAuxKernel : public MFEMGeneralUserObject
2626
virtual ~MFEMAuxKernel() = default;
2727

2828
/// Method called to update any owned objects upon an FE space update
29-
virtual void update() {};
29+
virtual void update() {}
30+
31+
virtual std::optional<std::string> suppliedVariableName() const override;
3032

3133
protected:
3234
/// Name of auxvariable to store the result of the auxkernel in.

0 commit comments

Comments
 (0)