Skip to content

Commit

Permalink
Add between multiapp transfer
Browse files Browse the repository at this point in the history
Refs #19451
  • Loading branch information
GiudGiud committed Dec 22, 2021
1 parent ed4553c commit 5117850
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 14 deletions.
3 changes: 3 additions & 0 deletions framework/include/problems/FEProblemBase.h
Expand Up @@ -2072,6 +2072,9 @@ class FEProblemBase : public SubProblem, public Restartable
/// Transfers executed just after MultiApps to transfer data from them
ExecuteMooseObjectWarehouse<Transfer> _from_multi_app_transfers;

/// Transfers executed just before MultiApps to transfer data between them
ExecuteMooseObjectWarehouse<Transfer> _between_multi_app_transfers;

/// A map of objects that consume random numbers
std::map<std::string, std::unique_ptr<RandomData>> _random_data_objects;

Expand Down
1 change: 1 addition & 0 deletions framework/include/transfers/MultiAppTransfer.h
Expand Up @@ -53,6 +53,7 @@ class MultiAppTransfer : public Transfer
protected:
/// The MultiApp this Transfer is transferring data to or from
std::shared_ptr<MultiApp> _multi_app;
std::shared_ptr<MultiApp> _to_multi_app;

/**
* This method will fill information into the convenience member variables
Expand Down
5 changes: 3 additions & 2 deletions framework/include/transfers/Transfer.h
Expand Up @@ -69,11 +69,12 @@ class Transfer : public MooseObject, public SetupInterface, public Restartable
enum DIRECTION
{
TO_MULTIAPP,
FROM_MULTIAPP
FROM_MULTIAPP,
BETWEEN_MULTIAPP
};

/// Used to construct InputParameters
static std::string possibleDirections() { return "to_multiapp from_multiapp"; }
static std::string possibleDirections() { return "to_multiapp from_multiapp between_multiapp"; }

/// The directions this Transfer should be executed on
const MultiMooseEnum & directions() { return _directions; }
Expand Down
53 changes: 42 additions & 11 deletions framework/src/problems/FEProblemBase.C
Expand Up @@ -260,6 +260,7 @@ FEProblemBase::FEProblemBase(const InputParameters & parameters)
_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
_to_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
_from_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
_between_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
#ifdef LIBMESH_ENABLE_AMR
_adaptivity(*this),
_cycles_completed(0),
Expand Down Expand Up @@ -1024,6 +1025,14 @@ FEProblemBase::initialSetup()
transfer->setCurrentDirection(Transfer::DIRECTION::FROM_MULTIAPP);
transfer->initialSetup();
}

// Call initialSetup on the MultiAppTransfers to be executed on BETWEEN_MULTIAPP
const auto & between_multi_app_objects = _between_multi_app_transfers.getActiveObjects();
for (const auto & transfer : between_multi_app_objects)
{
transfer->setCurrentDirection(Transfer::DIRECTION::BETWEEN_MULTIAPP);
transfer->initialSetup();
}
}

if (!_app.isRecovering())
Expand Down Expand Up @@ -4067,6 +4076,7 @@ FEProblemBase::updateActiveObjects()
_transfers.updateActive();
_to_multi_app_transfers.updateActive();
_from_multi_app_transfers.updateActive();
_between_multi_app_transfers.updateActive();
}

void
Expand Down Expand Up @@ -4260,9 +4270,19 @@ void
FEProblemBase::execMultiAppTransfers(ExecFlagType type, Transfer::DIRECTION direction)
{
bool to_multiapp = direction == MultiAppTransfer::TO_MULTIAPP;
std::string string_direction = to_multiapp ? " To " : " From ";
bool from_multiapp = direction == MultiAppTransfer::FROM_MULTIAPP;
std::string string_direction;
if (to_multiapp)
string_direction = " To ";
else if (from_multiapp)
string_direction = " From ";
else
string_direction = " between ";


const MooseObjectWarehouse<Transfer> & wh =
to_multiapp ? _to_multi_app_transfers[type] : _from_multi_app_transfers[type];
to_multiapp ? _to_multi_app_transfers[type] :
from_multiapp ? _from_multi_app_transfers[type] : _between_multi_app_transfers;

if (wh.hasActiveObjects())
{
Expand Down Expand Up @@ -4291,28 +4311,34 @@ FEProblemBase::execMultiAppTransfers(ExecFlagType type, Transfer::DIRECTION dire
std::vector<std::shared_ptr<Transfer>>
FEProblemBase::getTransfers(ExecFlagType type, Transfer::DIRECTION direction) const
{
const MooseObjectWarehouse<Transfer> & wh = direction == MultiAppTransfer::TO_MULTIAPP
? _to_multi_app_transfers[type]
: _from_multi_app_transfers[type];
return wh.getActiveObjects();
if (direction == MultiAppTransfer::TO_MULTIAPP)
return _to_multi_app_transfers[type].getActiveObjects();
else if (direction == MultiAppTransfer::FROM_MULTIAPP)
return _from_multi_app_transfers[type].getActiveObjects();
else
return _between_multi_app_transfers[type].getActiveObjects();
}

std::vector<std::shared_ptr<Transfer>>
FEProblemBase::getTransfers(Transfer::DIRECTION direction) const
{
const MooseObjectWarehouse<Transfer> & wh = direction == MultiAppTransfer::TO_MULTIAPP
? _to_multi_app_transfers
: _from_multi_app_transfers;
return wh.getActiveObjects();
if (direction == MultiAppTransfer::TO_MULTIAPP)
return _to_multi_app_transfers.getActiveObjects();
else if (direction == MultiAppTransfer::FROM_MULTIAPP)
return _from_multi_app_transfers.getActiveObjects();
else
return _between_multi_app_transfers.getActiveObjects();
}

const ExecuteMooseObjectWarehouse<Transfer> &
FEProblemBase::getMultiAppTransferWarehouse(Transfer::DIRECTION direction) const
{
if (direction == MultiAppTransfer::TO_MULTIAPP)
return _to_multi_app_transfers;
else
else if (direction == MultiAppTransfer::FROM_MULTIAPP)
return _from_multi_app_transfers;
else
return _between_multi_app_transfers;
}

bool
Expand All @@ -4329,6 +4355,9 @@ FEProblemBase::execMultiApps(ExecFlagType type, bool auto_advance)
// Execute Transfers _to_ MultiApps
execMultiAppTransfers(type, MultiAppTransfer::TO_MULTIAPP);

// Execute Transfers _between_ Multiapps
execMultiAppTransfers(type, MultiAppTransfer::BETWEEN_MULTIAPP);

// Execute MultiApps
if (multi_apps.size())
{
Expand Down Expand Up @@ -4535,6 +4564,8 @@ FEProblemBase::addTransfer(const std::string & transfer_name,
_to_multi_app_transfers.addObject(multi_app_transfer);
if (multi_app_transfer->directions().contains(MultiAppTransfer::FROM_MULTIAPP))
_from_multi_app_transfers.addObject(multi_app_transfer);
if (multi_app_transfer->directions().contains(MultiAppTransfer::BETWEEN_MULTIAPP))
_between_multi_app_transfers.addObject(multi_app_transfer);
}
else
_transfers.addObject(transfer);
Expand Down
21 changes: 21 additions & 0 deletions framework/src/transfers/MultiAppCopyTransfer.C
Expand Up @@ -61,5 +61,26 @@ MultiAppCopyTransfer::execute()
transfer(to_problem, _multi_app->appProblemBase(i));
}

else if (_current_direction == BETWEEN_MULTIAPP)
{
bool transfer_done = false;
for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
{
if (_multi_app->hasLocalApp(i))
{
for (unsigned int j = 0; j < _to_multi_app->numGlobalApps(); j++)
{
if (_to_multi_app->hasLocalApp(j))
{
transfer(_to_multi_app->appProblemBase(j), _multi_app->appProblemBase(i));
transfer_done = true;
}
}
}
}
if (!transfer_done)
mooseError("BETWEEN_MULTIAPP transfer not supported with more than one rank");
}

_console << "Finished MultiAppCopyTransfer " << name() << std::endl;
}
7 changes: 7 additions & 0 deletions framework/src/transfers/MultiAppFieldTransfer.C
Expand Up @@ -44,9 +44,16 @@ MultiAppFieldTransfer::initialSetup()
if (_current_direction == TO_MULTIAPP)
for (auto & to_var : getToVarNames())
variableIntegrityCheck(to_var);
else if (_current_direction == FROM_MULTIAPP)
for (auto & from_var : getFromVarNames())
variableIntegrityCheck(from_var);
else
{
for (auto & to_var : getToVarNames())
variableIntegrityCheck(to_var);
for (auto & from_var : getFromVarNames())
variableIntegrityCheck(from_var);
}
}

void
Expand Down
46 changes: 45 additions & 1 deletion framework/src/transfers/MultiAppTransfer.C
Expand Up @@ -26,6 +26,8 @@ MultiAppTransfer::validParams()
{
InputParameters params = Transfer::validParams();
params.addRequiredParam<MultiAppName>("multi_app", "The name of the MultiApp to use.");
params.addParam<MultiAppName>("to_multi_app",
"The name of the MultiApp to transfer the data to, in between_multiapp mode.");

// MultiAppTransfers by default will execute with their associated MultiApp. These flags will be
// added by FEProblemBase when the transfer is added.
Expand All @@ -50,6 +52,9 @@ MultiAppTransfer::validParams()
MultiAppTransfer::MultiAppTransfer(const InputParameters & parameters)
: Transfer(parameters),
_multi_app(_fe_problem.getMultiApp(getParam<MultiAppName>("multi_app"))),
_to_multi_app(isParamValid("to_multi_app") ?
_fe_problem.getMultiApp(getParam<MultiAppName>("to_multi_app")) :
_fe_problem.getMultiApp(getParam<MultiAppName>("multi_app"))),
_displaced_source_mesh(getParam<bool>("displaced_source_mesh")),
_displaced_target_mesh(getParam<bool>("displaced_target_mesh"))
{
Expand All @@ -67,6 +72,10 @@ MultiAppTransfer::MultiAppTransfer(const InputParameters & parameters)
_current_direction = only_direction;
_direction = only_direction;
}

for (auto dir : _directions)
if (dir == BETWEEN_MULTIAPP && !isParamValid("to_multi_app"))
paramError("direction", "Need to specify a to_multi_app for a BETWEEN_MULTIAPP direction");
}

void
Expand All @@ -75,13 +84,19 @@ MultiAppTransfer::checkMultiAppExecuteOn()
if (getExecuteOnEnum() != _multi_app->getExecuteOnEnum())
mooseDoOnce(mooseWarning("MultiAppTransfer execute_on flags do not match associated Multiapp "
"execute_on flags"));
if (getExecuteOnEnum() != _to_multi_app->getExecuteOnEnum())
mooseDoOnce(mooseWarning("MultiAppTransfer execute_on flags do not match associated to_Multiapp "
"execute_on flags"));
}

void
MultiAppTransfer::variableIntegrityCheck(const AuxVariableName & var_name) const
{
for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
if (_multi_app->hasLocalApp(i) && !_multi_app->appProblemBase(i).hasVariable(var_name))
if ((_multi_app->hasLocalApp(i) && !_multi_app->appProblemBase(i).hasVariable(var_name)) &&
(_to_multi_app &&
_to_multi_app->hasLocalApp(i) &&
!_to_multi_app->appProblemBase(i).hasVariable(var_name)))
mooseError("Cannot find variable ", var_name, " for ", name(), " Transfer");
}

Expand Down Expand Up @@ -145,6 +160,31 @@ MultiAppTransfer::getAppInfo()
_from_positions.push_back(_multi_app->position(i_app));
}
break;

case BETWEEN_MULTIAPP:
_to_problems.push_back(&_multi_app->problemBase());
_to_positions.push_back(Point(0., 0., 0.));
for (unsigned int i_app = 0; i_app < _multi_app->numGlobalApps(); i_app++)
{
if (!_multi_app->hasLocalApp(i_app))
continue;
for (unsigned int j_app = 0; j_app < _multi_app->numGlobalApps(); j_app++)
{
if (!_multi_app->hasLocalApp(i_app))
continue;

if (i_app == j_app)
continue;

_local2global_map.push_back(i_app);
_from_problems.push_back(&_multi_app->appProblemBase(i_app));
_from_positions.push_back(_multi_app->position(i_app));

_to_problems.push_back(&_multi_app->appProblemBase(j_app));
_to_positions.push_back(_multi_app->position(j_app));
}
}
break;
}

// Build the from and to equation systems and mesh vectors.
Expand Down Expand Up @@ -267,6 +307,10 @@ MultiAppTransfer::getFromsPerProc()
froms_per_proc.resize(n_processors());
_communicator.allgather(_multi_app->numLocalApps(), froms_per_proc);
break;
case BETWEEN_MULTIAPP:
froms_per_proc.resize(n_processors());
_communicator.allgather(_multi_app->numLocalApps(), froms_per_proc);
break;
}
return froms_per_proc;
}
Expand Down
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,32 @@
[Problem]
solve = false
[]

[Mesh]
type = GeneratedMesh
dim = 2
[]

[MultiApps/sub1]
type = TransientMultiApp
input_files = sub1.i
[]

[MultiApps/sub2]
type = TransientMultiApp
input_files = sub2.i
[]

[Transfers/from_sub1_to_sub2]
type = MultiAppCopyTransfer
direction = between_multiapp
multi_app = sub1
to_multi_app = sub2
source_variable = x1
variable = x2
[]

[Executioner]
type = Transient
num_steps = 1
[]
@@ -0,0 +1,22 @@
[Problem]
type = FEProblem
solve = false
[]

[Mesh]
type = GeneratedMesh
dim = 2
[]

[AuxVariables/x1]
initial_condition = 10
[]

[Executioner]
type = Transient
[]

[Outputs]
execute_on = 'FINAL'
exodus = true
[]
@@ -0,0 +1,22 @@
[Problem]
type = FEProblem
solve = false
[]

[Mesh]
type = GeneratedMesh
dim = 2
[]

[AuxVariables/x2]
initial_condition = 1980
[]

[Executioner]
type = Transient
[]

[Outputs]
execute_on = 'FINAL'
exodus = true
[]
@@ -0,0 +1,16 @@
[Tests]
issues = '#13754 #19451'
design = 'MultiAppCopyTransfer.md'

[transfer]
requirement = "The system shall support the transfer of auxiliary field variables between identical meshes:"
[from_sub_to_sub]
type = Exodiff
input = main.i
exodiff = 'main_out_sub10.e main_out_sub20.e'
recover = false # uses output on final

detail = 'between two subapps'
[]
[]
[]

0 comments on commit 5117850

Please sign in to comment.