Skip to content

Commit

Permalink
Allow PP transfer to do 1-N or N-N siblings transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
GiudGiud committed Jan 31, 2024
1 parent 9aa6ce3 commit 7b71a17
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 6 deletions.
Expand Up @@ -2,6 +2,13 @@

!syntax description /Transfers/MultiAppPostprocessorTransfer

## Siblings transfer behavior

This transfer supports sending data from a multiapp to a multiapp. There are two supported configurations:

- only one subapp in the source multiapp, the source postprocessor value is sent to all target multiapps.
- the same number of subapps in the source and target multiapp, the source postprocessor is matched to a target postprocessor based on a matching subapp index.

## Example Input File Syntax

The MultiAppPostprocessorTransfer allows for a Postprocessor value to be transfer between the
Expand Down
3 changes: 3 additions & 0 deletions framework/include/transfers/MultiAppPostprocessorTransfer.h
Expand Up @@ -35,6 +35,9 @@ class MultiAppPostprocessorTransfer : public MultiAppTransfer
};

protected:
/// Siblings transfers only supported for a single origin app
virtual void checkSiblingsTransferSupported() const override;

/// Name of the postprocessor to transfer data from
PostprocessorName _from_pp_name;

Expand Down
51 changes: 45 additions & 6 deletions framework/src/transfers/MultiAppPostprocessorTransfer.C
Expand Up @@ -70,15 +70,33 @@ MultiAppPostprocessorTransfer::execute()
case BETWEEN_MULTIAPP:
for (unsigned int i = 0; i < getFromMultiApp()->numGlobalApps(); i++)
{
// Get source postprocessor value
Real pp_value = std::numeric_limits<Real>::max();
if (getFromMultiApp()->hasLocalApp(i))
{
// Get source postprocessor value
FEProblemBase & from_problem = getFromMultiApp()->appProblemBase(i);
const Real & pp_value = from_problem.getPostprocessorValueByName(_from_pp_name);

if (getToMultiApp()->hasLocalApp(i))
getToMultiApp()->appProblemBase(i).setPostprocessorValueByName(_to_pp_name, pp_value);
pp_value = from_problem.getPostprocessorValueByName(_from_pp_name);
}

// Find the postprocessor value from another process
if (getFromMultiApp()->numGlobalApps() == 1)
_communicator.min(pp_value);
else if (pp_value == std::numeric_limits<Real>::max() && getToMultiApp()->hasLocalApp(i))
mooseError("Source and target app parallel distribution must be the same");

// Case 1: a single source app, multiple target apps
// All target apps must be local
if (getFromMultiApp()->numGlobalApps() == 1)
for (const auto j : make_range(getToMultiApp()->numGlobalApps()))
{
if (getToMultiApp()->hasLocalApp(j))
getToMultiApp()->appProblemBase(j).setPostprocessorValueByName(_to_pp_name, pp_value);
}

// Case 2: same number of source and target apps
// The allocation of the child apps on the processors must be the same
else if (getToMultiApp()->hasLocalApp(i))
getToMultiApp()->appProblemBase(i).setPostprocessorValueByName(_to_pp_name, pp_value);
}
break;
case TO_MULTIAPP:
Expand Down Expand Up @@ -114,7 +132,7 @@ MultiAppPostprocessorTransfer::execute()
"Can't get here unless someone adds a new enum and fails to add it to this switch");
}

const auto multi_app = getFromMultiApp() ? getFromMultiApp() : getToMultiApp();
const auto multi_app = hasFromMultiApp() ? getFromMultiApp() : getToMultiApp();

for (unsigned int i = 0; i < multi_app->numGlobalApps(); i++)
{
Expand Down Expand Up @@ -166,3 +184,24 @@ MultiAppPostprocessorTransfer::execute()
}
}
}

void
MultiAppPostprocessorTransfer::checkSiblingsTransferSupported() const
{
// Check that we are in one of the supported configurations
// Case 2: same number of source and target apps
// The allocation of the child apps on the processors must be the same
if (getFromMultiApp()->numGlobalApps() == getToMultiApp()->numGlobalApps())
{
for (const auto i : make_range(getToMultiApp()->numGlobalApps()))
if (getFromMultiApp()->hasLocalApp(i) + getToMultiApp()->hasLocalApp(i) == 1)
mooseError("Child application allocation on parallel processes must be the same to support "
"siblings postprocessor transfer");
}
// Unsupported, we dont know how to choose a postprocessor value
// We could default to 'any' value is good enough in the future, but it would not be reproducible
// in parallel. Also every process will not necessarily have a 'source' value
else if (getFromMultiApp()->numGlobalApps() != 1)
mooseError("Number of source and target child apps must either match or only a single source "
"app may be used");
}

0 comments on commit 7b71a17

Please sign in to comment.