Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
c54e9ab
Add skeleton test for testing transfers of variables from MFEM to lib…
alexanderianblair Feb 3, 2026
76cd45d
Add dummy MFEM to libMesh transfer to test
alexanderianblair Feb 5, 2026
5595fff
Interpolate MFEM scalar lagrange field to libMesh variable
alexanderianblair Feb 6, 2026
813d499
Execute MFEM subapp on initial to correct postprocessor output in test
alexanderianblair Feb 6, 2026
915e59c
Add test confirming MFEM to libMesh transfer works on tris
alexanderianblair Feb 6, 2026
0378768
Add support for transfers of constant MONOMIAL elements from MFEM to …
alexanderianblair Feb 6, 2026
ab6822b
Add initial tests for transfers from libMesh to MFEM in serial for lo…
alexanderianblair Feb 11, 2026
7813f9a
Split transfers from MFEM to libMesh and from libMesh to MFEM
alexanderianblair Feb 16, 2026
2ac62e2
Add MultiAppMFEMGeneralFieldTransfer for MFEM-to-MFEM transfers betwe…
alexanderianblair Feb 17, 2026
6a7ef0d
Add tests for H1 to H1 transfers using MFEMGeneralFieldTransfer
alexanderianblair Feb 17, 2026
60cd6a0
Refactor MultiApplibMeshToMFEMGeneralFieldTransfer::transfer to extra…
alexanderianblair Feb 17, 2026
62eb3c8
Fix transfers from libMesh to MFEM in parallel
alexanderianblair Feb 18, 2026
e1c0f5a
Add test for transfers of MONOMIAL variables from libMesh to MFEM
alexanderianblair Feb 18, 2026
e6339f5
Correct test spec for MFEM sub to sub CopyTransfers
alexanderianblair Feb 18, 2026
5319b0e
Add tests for transfers in 3D from MFEM to libMesh
alexanderianblair Feb 18, 2026
14aa0ad
Add 3D tests for transfers from libMesh to MFEM
alexanderianblair Feb 18, 2026
a4e2231
Add missing mesh files for transfer tests
alexanderianblair Feb 19, 2026
8f00a0b
Add tests for transfers of second order LAGRANGE variables from libMe…
alexanderianblair Feb 19, 2026
6e4cfa7
Add tests for transfers of second order LAGRANGE variables from MFEM …
alexanderianblair Feb 19, 2026
1efd4ee
Add tests for MFEM to MFEM transfers of vector variables in 3D
alexanderianblair Feb 19, 2026
52e807d
Add tests for MFEM GeneralFieldTransfers from tet meshes to hex meshes
alexanderianblair Feb 20, 2026
7ee5d86
Add test for MFEMGeneralFieldTransfer transfers from geometrically sm…
alexanderianblair Feb 20, 2026
d5c2d6a
Move duplicated code for projection to MFEM GridFunctions into MFEMTr…
alexanderianblair Feb 23, 2026
d4f13f0
Add MFEMGeneralFieldTransferBase class to further reduce code duplica…
alexanderianblair Feb 24, 2026
ee046ab
Rename MultiAppMFEMGeneralFieldTransferBase to MFEMMultiAppTransfer t…
alexanderianblair Feb 24, 2026
eefe95f
Rename MultiAppMFEMGeneralFieldTransfer classes to MultiAppMFEMShapeE…
alexanderianblair Feb 24, 2026
d5d0d0e
Rename MFEMTransferProjector to MFEMNodalProjector to better reflect …
alexanderianblair Feb 25, 2026
35e3f62
Add markdown documentation for newly added transfers. Refs #31982
alexanderianblair Feb 25, 2026
631eb79
Add bounding box logic to MultiApplibMeshToMFEMShapeEvaluationTransfe…
alexanderianblair Feb 25, 2026
a21a2e1
Revert addition of bounding box logic in MultiApplibMeshToMFEMShapeEv…
alexanderianblair Feb 26, 2026
1a82ca4
Move method to create a libMesh::Point from an mfem::Vector into MFEM…
alexanderianblair Feb 26, 2026
7ea5163
Cleanup and rename of MFEMVectorUtils
alexanderianblair Feb 27, 2026
3d2077b
Add doxygen for methods of newly added MFEM transfers
alexanderianblair Mar 2, 2026
a6e3c89
Refactor MFEM transfers to/from libMesh to make point identification/…
alexanderianblair Mar 3, 2026
733dd7c
Add getter and setter for default out-of-mesh value for MFEM transfers
alexanderianblair Mar 3, 2026
922d905
Generalise MultiAppMFEMShapeEvaluationTransfer to support transfers b…
alexanderianblair Mar 4, 2026
0875f53
Apply suggestions from code review
alexanderianblair Mar 12, 2026
16e1eba
Move MFEMNodalProjector from mfem/transfers into mfem/utils and make …
alexanderianblair Mar 12, 2026
050c0da
Add type check to getters for MFEM problems in MFEM transfers
alexanderianblair Mar 12, 2026
967debd
Use SetTrueVector instead of SetFromTrueVector in MFEMNodalProjector …
alexanderianblair Apr 1, 2026
dfb2198
Fix MultiAppMFEMCopyTransfer problem type check in constructor, and c…
alexanderianblair Apr 1, 2026
1d014b1
Rename remaining pointsToMFEMVector following rebase
alexanderianblair Apr 2, 2026
355482c
Remove unnecessary iteration over destination GridFunction vector com…
alexanderianblair Apr 7, 2026
4d52f3c
Add check enforcing that transfers between libMesh and MFEM sub-apps …
alexanderianblair Apr 7, 2026
57c4b4b
Add tests for sibling transfers between MFEM and libMesh subapps
alexanderianblair Apr 7, 2026
9f0ab63
Fix output ordering issues in MFEMNodalProjector
alexanderianblair Apr 8, 2026
2aa4486
Remove redundant iteration over to_problems and from_problems in Mult…
alexanderianblair Apr 9, 2026
41c936a
Add test for nodal transfer from displaced libMesh application to MFE…
alexanderianblair Apr 9, 2026
73f8378
Add test for transfer from MFEM to a libMesh displaced mesh
alexanderianblair Apr 10, 2026
19673c8
Fix Unity build failure from libMesh::EquationSystems not being label…
alexanderianblair Apr 13, 2026
61c30c0
Update MultiApp.C to avoid the construction of mfem::Device multiple …
alexanderianblair Apr 14, 2026
541f4ea
Add support for use of Positions in MultiApps containing MFEM transfers
alexanderianblair Apr 15, 2026
f1dccc4
Fix for 1 to N MFEM to libMesh transfer test in parallel, running Fin…
alexanderianblair Apr 15, 2026
71dae42
Apply suggestions from code review
alexanderianblair Apr 15, 2026
aeb6ed2
Remove spurious ./ from mesh file paths in newly added MFEM transfer …
alexanderianblair Apr 15, 2026
ae4e934
Remove spurious whitespace and implementation details from MFEM trans…
alexanderianblair Apr 15, 2026
b2f8ae1
Move long MFEM transfer getter and checkValidTransferProblemTypes met…
alexanderianblair Apr 16, 2026
01769d8
Replace nsp with nqpt and NE with nelem in MFEMNodalProjector for rea…
alexanderianblair Apr 16, 2026
f4b83e8
Rename variable and source_variable parameters in MFEMMultiAppTransfe…
alexanderianblair Apr 16, 2026
d72fc0d
Add 1 to N app test for MFEM to MFEM transfers
alexanderianblair Apr 17, 2026
38db08b
Add test to check 1-to-N MFEM to MFEM sibling transfers in parallel
alexanderianblair Apr 17, 2026
4973f6d
Support transfers to mixed meshes in MFEMNodalProjector
alexanderianblair Apr 18, 2026
f10ffb1
Add tests for libMesh to MFEM transfers on mixed meshes.
alexanderianblair Apr 20, 2026
3d30808
Move MFEM to MFEM sibling shape evaluation transfer test from mfem_su…
alexanderianblair Apr 21, 2026
9dee216
Fix potential issue where libMesh to MFEM transfers could use an inva…
alexanderianblair Apr 21, 2026
334682e
Apply suggestions from code review
alexanderianblair Apr 23, 2026
d5fab83
Use nqpt for consistency with MFEM, use make_range in MFEMMultiAppTra…
alexanderianblair Apr 23, 2026
d6febef
Clean up outputs in tests/mfem/transfers/sibling_transfers test direc…
alexanderianblair Apr 24, 2026
25b8962
Simplify gather and action functors in MultiApplibMeshToMFEMShapeEval…
alexanderianblair Apr 24, 2026
d8fbb67
Review suggestions
nmnobre Apr 27, 2026
bdb8209
Apply suggestions from code review
alexanderianblair Apr 29, 2026
58a80e6
Revert change to square.e mesh, and rename square_quad.e mesh to squa…
alexanderianblair Apr 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions framework/doc/content/source/mfem/transfers/MFEMNodalProjector.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# MFEMNodalProjector

!if! function=hasCapability('mfem')

Auxiliary class for extracting nodal positions/interpolation points from MFEM FESpaces, and for setting DoFs on MFEM GridFunctions
via projection given a vector of values evaluated at these nodes.

End users should not need to interact with `MFEMNodalProjector` directly. `MFEMNodalProjector` is
used by MFEM transfers that set values of an MFEMGridFunction, such as
[MultiAppMFEMShapeEvaluationTransfer](MultiAppMFEMShapeEvaluationTransfer.md).

!if-end!

!else
!include mfem/mfem_warning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# MultiAppMFEMShapeEvaluationTransfer

!if! function=hasCapability('mfem')

Allows transfers of [MFEM variables](MFEMVariable.md) between MFEM-based applications via local
evaluation of shape functions at target nodal projection points. The variables may be defined on
different meshes and FESpaces of different orders, but must be real, share the same dimensionality,
and both belong to an `MFEMProblem` in their respective applications.

## General Description

`MultiAppMFEMShapeEvaluationTransfer` executes transfers in three steps:

1. Extraction of a vector of node positions in the `ParFiniteElementSpace` of the destination
`mfem::ParGridFunction`, using [`MFEMNodalProjector`](MFEMNodalProjector.md).
2. Interpolation of the source `mfem::ParGridFunction` at this set of node locations, using
`mfem::FindPointsGSLIB` to perform the required gather/scatter operations to obtain a set of
points on the local mesh partition, and perform shape function evaluations at these points.
3. Projection of the evaluated source variable values onto the destination variable nodes, to set
the destination variable degrees of freedom, using [`MFEMNodalProjector`](MFEMNodalProjector.md).

For transfers between identical variables defined on the same mesh, users are recommended to use
[`MultiAppMFEMCopyTransfer`](MultiAppMFEMCopyTransfer.md) for performance.

## Features Supported

All MFEM to MFEM transfers executed from this class should be able to support:

- transfers of scalar and vector variables
- transfers between variables belonging to different finite element spaces and orders
- transfers between complex variables
- transfers between variables defined on submeshes and parent meshes
- arbitrary number of parallel processes for both the source and target application
- transfers between parent and child applications
- transfers between sibling applications (child to child)
- transfers from multiple variables to multiple variables

!syntax parameters /Transfers/MultiAppMFEMShapeEvaluationTransfer

!syntax inputs /Transfers/MultiAppMFEMShapeEvaluationTransfer

!syntax children /Transfers/MultiAppMFEMShapeEvaluationTransfer

!if-end!

!else
!include mfem/mfem_warning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# MultiAppMFEMTolibMeshShapeEvaluationTransfer

!if! function=hasCapability('mfem')

Allows transfers of [MFEM variables](MFEMVariable.md) from MFEM-based applications to libMesh-based [MooseVariables](MooseVariable.md) via local
evaluation of shape functions at target nodal projection points. This class supports transfers between different meshes, from scalar MFEM GridFunctions to first and second order LAGRANGE and constant MONOMIAL libMesh variable types.

For transfers in the opposite direction, from libMesh-based applications to MFEM-based applications, please see [MultiApplibMeshToMFEMShapeEvaluationTransfer](MultiApplibMeshToMFEMShapeEvaluationTransfer.md).

## General Description

`MultiAppMFEMTolibMeshShapeEvaluationTransfer` executes transfers in three steps:

1. Extraction of a vector of node positions or element centroids of the destination libMesh solution
variable (similar to the method used in
[`MultiAppGeneralFieldTransfer`](MultiAppGeneralFieldTransfer.md)).
2. Interpolation of the source `mfem::ParGridFunction` at this set of node locations, using
`mfem::FindPointsGSLIB` to perform the required gather/scatter operations to obtain a set of
points on the local mesh partition, and perform shape function evaluations at these points.
Comment thread
alexanderianblair marked this conversation as resolved.
3. Projection of the evaluated source variable values onto the destination libMesh variable nodes,
to set the destination variable degrees of freedom.

## Features Supported

All MFEM to libMesh transfers executed from this class should be able to support:

- transfers to lowest order scalar LAGRANGE and MONOMIAL variables
- transfers to second order scalar LAGRANGE variables
- transfers between variables belonging to dissimilar meshes
Comment thread
lindsayad marked this conversation as resolved.
- arbitrary number of parallel processes for both the source and target application
- transfers between parent and child applications
- transfers between sibling applications (child to child)
- transfers from multiple variables to multiple variables
- transfers between displaced meshes

!syntax parameters /Transfers/MultiAppMFEMTolibMeshShapeEvaluationTransfer

!syntax inputs /Transfers/MultiAppMFEMTolibMeshShapeEvaluationTransfer

!syntax children /Transfers/MultiAppMFEMTolibMeshShapeEvaluationTransfer

!if-end!

!else
!include mfem/mfem_warning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# MultiApplibMeshToMFEMShapeEvaluationTransfer

!if! function=hasCapability('mfem')

Allows transfers of libMesh-based [MooseVariables](MooseVariable.md) to
[MFEM variables](MFEMVariable.md),
via local evaluation of shape functions at target nodal projection points. This class supports
transfers between different meshes, from first and second order LAGRANGE and constant MONOMIAL libMesh
variable types to scalar MFEM GridFunctions defined on H1 and L2 conforming finite element spaces.

For transfers in the opposite direction, from MFEM-based applications to libMesh-based applications, please see [MultiAppMFEMTolibMeshShapeEvaluationTransfer](MultiAppMFEMTolibMeshShapeEvaluationTransfer.md).

## General Description

`MultiApplibMeshToMFEMShapeEvaluationTransfer` executes transfers in three steps:

1. Extraction of a vector of node positions in the `ParFiniteElementSpace` of the destination
`mfem::ParGridFunction`, using [`MFEMNodalProjector`](MFEMNodalProjector.md).
2. Interpolation of the source libMesh-based `MooseVariable` at this set of node locations. Required
gather/scatter operations are performed similarly to those in
[`MultiAppGeneralFieldTransfer`](MultiAppGeneralFieldTransfer.md), with interpolation analagous
to [`MultiAppGeneralFieldShapeEvaluationTransfer`](MultiAppGeneralFieldShapeEvaluationTransfer.md).
3. Projection of the evaluated source variable values onto the destination variable nodes, to set
the destination variable degrees of freedom, using [`MFEMNodalProjector`](MFEMNodalProjector.md).

## Features Supported

All libMesh to MFEM transfers executed from this class should be able to support:

- transfers from lowest order scalar LAGRANGE and MONOMIAL variables
- transfers from second order scalar LAGRANGE variables
- transfers between variables belonging to dissimilar meshes
Comment thread
lindsayad marked this conversation as resolved.
- arbitrary number of parallel processes for both the source and target application
- transfers between parent and child applications
- transfers between sibling applications (child to child)
- transfers from multiple variables to multiple variables
- transfers between displaced meshes

!syntax parameters /Transfers/MultiApplibMeshToMFEMShapeEvaluationTransfer

!syntax inputs /Transfers/MultiApplibMeshToMFEMShapeEvaluationTransfer

!syntax children /Transfers/MultiApplibMeshToMFEMShapeEvaluationTransfer

!if-end!

!else
!include mfem/mfem_warning.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MFEMFunctorMaterial : public MFEMObject,
{
public:
static InputParameters validParams();
static libMesh::Point pointFromMFEMVector(const mfem::Vector & vec);
static libMesh::Point libMeshPointFromMFEMVector(const mfem::Vector & vec);

MFEMFunctorMaterial(const InputParameters & parameters);
virtual ~MFEMFunctorMaterial();
Expand Down
5 changes: 4 additions & 1 deletion framework/include/mfem/outputs/MFEMDataCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ class MFEMDataCollection : public FileOutput
virtual mfem::DataCollection & getDataCollection() = 0;

protected:
/// Register fields (GridFunctions) to be saved in the DataCollection
void registerFields();
/// Write out data
void output() override;

/// Update the DataCollection path when the internal file base path is set
void setFileBaseInternal(const std::string & file_base) override;
/// Reference to the MFEMProblemData struct storing the output variables.
MFEMProblemData & _problem_data;
/// Mesh set of output variables are defined on. May differ from main problem mesh if SubMesh
Expand Down
156 changes: 156 additions & 0 deletions framework/include/mfem/transfers/MFEMMultiAppTransfer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
//* This file is part of the MOOSE framework
//* https://mooseframework.inl.gov
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#ifdef MOOSE_MFEM_ENABLED

#pragma once

#include "MultiAppTransfer.h"

/**
* Virtual base class for MultiApp transfers to and/or from MFEMProblems.
*/
class MFEMMultiAppTransfer : public MultiAppTransfer
{
public:
static InputParameters validParams();
MFEMMultiAppTransfer(InputParameters const & params);
/// Set active source and destination problems, and execute variable transfer
void execute() override;
/// Allow sibling transfers
void checkSiblingsTransferSupported() const override {}

/// Getter for source variable name
const VariableName & getFromVarName(int i) const { return _from_var_names.at(i); }
/// Getter for destination variable name
const VariableName & getToVarName(int i) const { return _to_var_names.at(i); }
/// Return the number of source variables
unsigned int numFromVar() const { return _from_var_names.size(); }
/// Return for the number of destination variables
unsigned int numToVar() const { return _to_var_names.size(); }

protected:
/// Transfer all variables from active source problem to active destination problem.
virtual void transferVariables(bool is_target_local) = 0;

/// Set current problem to fetch source variables from
void setActiveFromProblem(FEProblemBase & from_problem, const unsigned int global_app_index)
{
_active_from_problem = &from_problem;
_active_from_global_app_index = global_app_index;
}
/// Set current problem to fetch destination variables from
void setActiveToProblem(FEProblemBase & to_problem, const unsigned int global_app_index)
{
_active_to_problem = &to_problem;
_active_to_global_app_index = global_app_index;
}
/// Getter for current problem containing source variables
virtual FEProblemBase & getActiveFromProblem() { return *_active_from_problem; }
/// Getter for current problem containing destination variables
virtual FEProblemBase & getActiveToProblem() { return *_active_to_problem; }
Comment thread
lindsayad marked this conversation as resolved.
/// Getter for current destination problem global app index.
virtual unsigned int & getActiveToProblemGlobalAppIndex() { return _active_to_global_app_index; }
/// Getter for current destination problem global app index.
virtual unsigned int & getActiveFromProblemGlobalAppIndex()
{
return _active_from_global_app_index;
}

/// Getter for the active source transform
const MultiAppCoordTransform & getActiveFromTransform() const
{
return *_from_transforms[_active_from_global_app_index];
}
/// Getter for the active destination transform
const MultiAppCoordTransform & getActiveToTransform() const
{
return *_to_transforms[_active_to_global_app_index];
}
/// Map a point in the active destination app frame to the active source app frame
libMesh::Point mapPointToActiveSourceFrame(const Point & point_in_target_frame) const
{
return getActiveFromTransform().mapBack(getActiveToTransform()(point_in_target_frame));
}
/// Get libMesh EquationSystem, which may or may not be displaced
libMesh::EquationSystems & getlibMeshEquationSystem(FEProblemBase & problem,
bool use_displaced) const;

/// Set default value for transfers evaluated at points outside source mesh
void setMFEMOutOfMeshValue(mfem::real_t mfem_out_of_mesh_value)
{
_mfem_out_of_mesh_value = mfem_out_of_mesh_value;
}
/// Getter for default value for transfers evaluated at points outside source mesh
mfem::real_t getMFEMOutOfMeshValue() const { return _mfem_out_of_mesh_value; }

/// Templated method to check source and destination problems are of the expected types
template <typename TO_PROBLEM, typename FROM_PROBLEM>
void checkValidTransferProblemTypes();

private:
/// Vector of source variable names to be transferred
const std::vector<VariableName> & _from_var_names;
/// Vector of destination variable names to transfer to
const std::vector<VariableName> & _to_var_names;
/// Pointer to active destination problem variable is being transferred to
FEProblemBase * _active_to_problem{nullptr};
/// Pointer to active source problem variable is being transferred from
FEProblemBase * _active_from_problem{nullptr};
/// Global app index for the active destination problem
unsigned int _active_to_global_app_index{0};
/// Global app index for the active source problem
unsigned int _active_from_global_app_index{0};
/// Default value to return for transfers from points outside the source mesh
mfem::real_t _mfem_out_of_mesh_value{std::numeric_limits<mfem::real_t>::infinity()};
};

template <typename TO_PROBLEM, typename FROM_PROBLEM>
inline void
MFEMMultiAppTransfer::checkValidTransferProblemTypes()
{
auto bad_problem = [this]()
{
mooseError(
type(),
" is not compatible with the provided source and/or destination Problem types of the "
"provided variables.");
};

if (hasFromMultiApp())
{
// Check if source sub-apps exist, and if so, if they are of the expected type
if (getFromMultiApp()->numGlobalApps())
{
for (const auto i : make_range(getFromMultiApp()->numGlobalApps()))
if (getFromMultiApp()->hasLocalApp(i) &&
!dynamic_cast<FROM_PROBLEM *>(&getFromMultiApp()->appProblemBase(i)))
bad_problem();
}
else // check source sub-app is of the expected type if it is the transfer source
if (!dynamic_cast<FROM_PROBLEM *>(&getFromMultiApp()->problemBase()))
bad_problem();
}
if (hasToMultiApp())
{
// Check if destination sub-apps exist, and if so, if they are of the expected type
if (getToMultiApp()->numGlobalApps())
{
for (const auto i : make_range(getToMultiApp()->numGlobalApps()))
if (getToMultiApp()->hasLocalApp(i) &&
!dynamic_cast<TO_PROBLEM *>(&getToMultiApp()->appProblemBase(i)))
bad_problem();
}
else // check destination sub-app is of the expected type if it is the transfer destination
if (!dynamic_cast<TO_PROBLEM *>(&getToMultiApp()->problemBase()))
bad_problem();
}
}

#endif
39 changes: 15 additions & 24 deletions framework/include/mfem/transfers/MultiAppMFEMCopyTransfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,30 @@

#pragma once

#include <vector>

#include "MultiAppTransfer.h"
#include "MultiApp.h"
#include "MooseAppCoordTransform.h"
#include "MFEMMultiAppTransfer.h"
#include "MFEMProblem.h"

class MooseMesh;

//*
// Copy MFEMVariables between multiapps
// The variables must be of the same type and dimension
// and the MFEMMesh must be identical in both multiapps
// */

class MultiAppMFEMCopyTransfer : public MultiAppTransfer
/**
* Transfer to copy MFEMVariables between multiapps.
* The variables must be of the same type and dimension
* and the MFEMMesh must be identical in both multiapps
*/
class MultiAppMFEMCopyTransfer : public MFEMMultiAppTransfer
{
public:
static InputParameters validParams();
MultiAppMFEMCopyTransfer(InputParameters const & params);
void execute() override;
auto const & getFromVarName(int i) { return _from_var_names.at(i); };
auto const & getToVarName(int i) { return _to_var_names.at(i); };
auto numFromVar() { return _from_var_names.size(); }
auto numToVar() { return _to_var_names.size(); }

protected:
std::vector<VariableName> _from_var_names;
std::vector<AuxVariableName> _to_var_names;

void transfer(MFEMProblem & to_problem, MFEMProblem & from_problem);

/// Transfer all variables from active source problem to active destination problem.
virtual void transferVariables(bool is_target_local) override;
/// Check number of source and target child apps match for sibling transfer
void checkSiblingsTransferSupported() const override;

/// Set current MFEM problem to fetch source variables from
virtual MFEMProblem & getActiveFromProblem() override;
/// Set current MFEM problem to fetch destination variables from
virtual MFEMProblem & getActiveToProblem() override;
};

#endif
Loading