www.mooseframework.org
MultiAppPostprocessorTransfer.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
11 
12 // MOOSE includes
13 #include "MooseTypes.h"
14 #include "FEProblem.h"
15 #include "MultiApp.h"
16 
17 // libMesh
18 #include "libmesh/meshfree_interpolation.h"
19 #include "libmesh/system.h"
20 
22 
25 {
27  params.addClassDescription(
28  "Transfers postprocessor data between the master application and sub-application(s).");
29  params.addRequiredParam<PostprocessorName>(
30  "from_postprocessor",
31  "The name of the Postprocessor in the Master to transfer the value from.");
32  params.addRequiredParam<PostprocessorName>(
33  "to_postprocessor",
34  "The name of the Postprocessor in the MultiApp to transfer the value to. "
35  " This should most likely be a Reporter Postprocessor.");
36  MooseEnum reduction_type("average sum maximum minimum");
37  params.addParam<MooseEnum>("reduction_type",
38  reduction_type,
39  "The type of reduction to perform to reduce postprocessor "
40  "values from multiple SubApps to a single value");
41  return params;
42 }
43 
45  : MultiAppTransfer(parameters),
46  _from_pp_name(getParam<PostprocessorName>("from_postprocessor")),
47  _to_pp_name(getParam<PostprocessorName>("to_postprocessor")),
48  _reduction_type(getParam<MooseEnum>("reduction_type"))
49 {
50  if (_directions.size() != 1)
51  paramError("direction", "This transfer is only unidirectional");
52 
54  if (!_reduction_type.isValid())
55  mooseError("In MultiAppPostprocessorTransfer, must specify 'reduction_type' if direction = "
56  "from_multiapp");
57 
58  if (isParamValid("to_multi_app") && isParamValid("from_multi_app") &&
59  isParamValid("reduction_type"))
60  mooseError("Reductions are not supported for multiapp sibling transfers");
61 }
62 
63 void
65 {
66  TIME_SECTION("MultiAppPostprocessorTransfer::execute()", 5, "Transferring a postprocessor");
67 
68  switch (_current_direction)
69  {
70  case BETWEEN_MULTIAPP:
71  for (unsigned int i = 0; i < getFromMultiApp()->numGlobalApps(); i++)
72  {
73  // Get source postprocessor value
75  if (getFromMultiApp()->hasLocalApp(i))
76  {
77  FEProblemBase & from_problem = getFromMultiApp()->appProblemBase(i);
78  pp_value = from_problem.getPostprocessorValueByName(_from_pp_name);
79  }
80 
81  // Find the postprocessor value from another process
82  if (getFromMultiApp()->numGlobalApps() == 1)
83  _communicator.min(pp_value);
84  else
85  mooseAssert(pp_value != std::numeric_limits<Real>::max() ||
86  !getToMultiApp()->hasLocalApp(i),
87  "Source and target app parallel distribution must be the same");
88 
89  // Case 1: a single source app, multiple target apps
90  // All target apps must be local
91  if (getFromMultiApp()->numGlobalApps() == 1)
92  for (const auto j : make_range(getToMultiApp()->numGlobalApps()))
93  {
94  if (getToMultiApp()->hasLocalApp(j))
95  getToMultiApp()->appProblemBase(j).setPostprocessorValueByName(_to_pp_name, pp_value);
96  }
97 
98  // Case 2: same number of source and target apps
99  // The allocation of the child apps on the processors must be the same
100  else if (getToMultiApp()->hasLocalApp(i))
101  getToMultiApp()->appProblemBase(i).setPostprocessorValueByName(_to_pp_name, pp_value);
102  }
103  break;
104  case TO_MULTIAPP:
105  {
106  FEProblemBase & from_problem = getToMultiApp()->problemBase();
107 
108  const Real & pp_value = from_problem.getPostprocessorValueByName(_from_pp_name);
109 
110  for (unsigned int i = 0; i < getToMultiApp()->numGlobalApps(); i++)
111  if (getToMultiApp()->hasLocalApp(i))
112  getToMultiApp()->appProblemBase(i).setPostprocessorValueByName(_to_pp_name, pp_value);
113  break;
114  }
115  case FROM_MULTIAPP:
116  {
117  FEProblemBase & to_problem = getFromMultiApp()->problemBase();
118 
119  Real reduced_pp_value;
120  switch (_reduction_type)
121  {
122  case AVERAGE:
123  case SUM:
124  reduced_pp_value = 0;
125  break;
126  case MAXIMUM:
127  reduced_pp_value = -std::numeric_limits<Real>::max();
128  break;
129  case MINIMUM:
130  reduced_pp_value = std::numeric_limits<Real>::max();
131  break;
132  default:
133  mooseError(
134  "Can't get here unless someone adds a new enum and fails to add it to this switch");
135  }
136 
137  const auto multi_app = hasFromMultiApp() ? getFromMultiApp() : getToMultiApp();
138 
139  for (unsigned int i = 0; i < multi_app->numGlobalApps(); i++)
140  {
141  if (multi_app->hasLocalApp(i) && multi_app->isRootProcessor())
142  {
143  const Real & curr_pp_value =
144  multi_app->appProblemBase(i).getPostprocessorValueByName(_from_pp_name);
145  switch (_reduction_type)
146  {
147  case AVERAGE:
148  case SUM:
149  reduced_pp_value += curr_pp_value;
150  break;
151  case MAXIMUM:
152  reduced_pp_value = std::max(curr_pp_value, reduced_pp_value);
153  break;
154  case MINIMUM:
155  reduced_pp_value = std::min(curr_pp_value, reduced_pp_value);
156  break;
157  default:
158  mooseError("Can't get here unless someone adds a new enum and fails to add it to "
159  "this switch");
160  }
161  }
162  }
163 
164  switch (_reduction_type)
165  {
166  case AVERAGE:
167  _communicator.sum(reduced_pp_value);
168  reduced_pp_value /= static_cast<Real>(multi_app->numGlobalApps());
169  break;
170  case SUM:
171  _communicator.sum(reduced_pp_value);
172  break;
173  case MAXIMUM:
174  _communicator.max(reduced_pp_value);
175  break;
176  case MINIMUM:
177  _communicator.min(reduced_pp_value);
178  break;
179  default:
180  mooseError(
181  "Can't get here unless someone adds a new enum and fails to add it to this switch");
182  }
183 
184  to_problem.setPostprocessorValueByName(_to_pp_name, reduced_pp_value);
185  break;
186  }
187  }
188 }
189 
190 void
192 {
193  // Check that we are in one of the supported configurations
194  // Case 2: same number of source and target apps
195  // The allocation of the child apps on the processors must be the same
196  if (getFromMultiApp()->numGlobalApps() == getToMultiApp()->numGlobalApps())
197  {
198  for (const auto i : make_range(getToMultiApp()->numGlobalApps()))
199  if (getFromMultiApp()->hasLocalApp(i) + getToMultiApp()->hasLocalApp(i) == 1)
200  mooseError("Child application allocation on parallel processes must be the same to support "
201  "siblings postprocessor transfer");
202  }
203  // Unsupported, we dont know how to choose a postprocessor value
204  // We could default to 'any' value is good enough in the future, but it would not be reproducible
205  // in parallel. Also every process will not necessarily have a 'source' value
206  else if (getFromMultiApp()->numGlobalApps() != 1)
207  mooseError("Number of source and target child apps must either match or only a single source "
208  "app may be used");
209 }
virtual void checkSiblingsTransferSupported() const override
Siblings transfers only supported for a single origin app.
const std::shared_ptr< MultiApp > getFromMultiApp() const
Get the MultiApp to transfer data from.
MooseEnum _current_direction
Definition: Transfer.h:106
PostprocessorName _from_pp_name
Name of the postprocessor to transfer data from.
void setPostprocessorValueByName(const PostprocessorName &name, const PostprocessorValue &value, std::size_t t_index=0)
Set the value of a PostprocessorValue.
registerMooseObject("MooseApp", MultiAppPostprocessorTransfer)
MultiAppPostprocessorTransfer(const InputParameters &parameters)
unsigned int size() const
Return the number of active items in the MultiMooseEnum.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const std::shared_ptr< MultiApp > getToMultiApp() const
Get the MultiApp to transfer data to.
const Parallel::Communicator & _communicator
bool hasFromMultiApp() const
Whether the transfer owns a non-null from_multi_app.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
auto max(const L &left, const R &right)
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
void min(const T &r, T &o, Request &req) const
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
static InputParameters validParams()
const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name, std::size_t t_index=0) const
Get a read-only reference to the value associated with a Postprocessor that exists.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
MultiMooseEnum _directions
The directions this Transfer is to be executed on.
Definition: Transfer.h:110
void max(const T &r, T &o, Request &req) const
Base class for all MultiAppTransfer objects.
IntRange< T > make_range(T beg, T end)
MooseEnum _reduction_type
Reduction operation to perform when transferring from multiple child apps to the parent app...
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
PostprocessorName _to_pp_name
Name of the postprocessor to transfer data to.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
auto min(const L &left, const R &right)
Copies the value of a Postprocessor either:
virtual void execute() override
Execute the transfer.
virtual bool isValid() const override
IsValid.
Definition: MooseEnum.h:116