https://mooseframework.inl.gov
SerializedSolutionTransfer.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
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 
10 // StochasticTools includes
12 #include "NonlinearSystemBase.h"
13 #include "Sampler.h"
14 
15 registerMooseObject("StochasticToolsApp", SerializedSolutionTransfer);
16 
19 {
21  params.addClassDescription(
22  "Serializes and transfers solution vectors for given variables from sub-applications.");
23  params.addRequiredParam<std::string>("parallel_storage",
24  "The name of the parallel storage reporter.");
25  params.addRequiredParam<std::string>("solution_container",
26  "The name of the solution container on the subapp.");
27  params.addRequiredParam<std::vector<VariableName>>(
28  "variables",
29  "The names of the variables which should be serialized and transferred to this application.");
30  params.addParam<bool>("serialize_on_root",
31  false,
32  "If we want to gather the solution fields only on the root processors of "
33  "the subapps before transfering to the main app.");
34  return params;
35 }
36 
38  : StochasticToolsTransfer(parameters),
39  _variable_names(getParam<std::vector<VariableName>>("variables")),
40  _serialize_on_root(getParam<bool>("serialize_on_root"))
41 {
42  if (hasToMultiApp())
43  paramError("to_multi_app", "To and between multiapp directions are not implemented");
44 }
45 
46 void
48 {
49  // Check if we have the storage space to receive the serialized solution fields
51  getParam<std::string>("parallel_storage"));
52 }
53 
54 void
56 {
57  _solution_container.clear();
58  const auto n = getFromMultiApp()->numGlobalApps();
59  const auto & serialized_solution_reporter = getParam<std::string>("solution_container");
60 
61  for (MooseIndex(n) i = 0; i < n; i++)
62  if (getFromMultiApp()->hasLocalApp(i))
63  {
64  FEProblemBase & app_problem = getFromMultiApp()->appProblemBase(i);
65  _solution_container.push_back(
66  &app_problem.getUserObject<SolutionContainer>(serialized_solution_reporter));
67  }
68 }
69 
70 void
72 {
73  // First we fetch the solution containers from the subapps. This function is used
74  // in batch mode only so we will have one solution container on each rank
75  _solution_container.clear();
76 
77  FEProblemBase & app_problem = getFromMultiApp()->appProblemBase(_app_index);
78 
79  _solution_container.push_back(
80  &app_problem.getUserObject<SolutionContainer>(getParam<std::string>("solution_container")));
81 }
82 
83 void
85 {
87 
88  const auto n = getFromMultiApp()->numGlobalApps();
89 
90  for (MooseIndex(n) i = 0; i < n; i++)
91  {
92  if (getFromMultiApp()->hasLocalApp(i))
93  {
94  FEProblemBase & app_problem = getFromMultiApp()->appProblemBase(i);
95 
96  // Converting the local indexing to global sample indices
97  const unsigned int local_i = i - _sampler_ptr->getLocalRowBegin();
98 
99  // Here we have to branch out based on if only the root processors
100  // need to participate in the transfer or if we would like to distribute the
101  // data among every processor of the subapplication
102  if (_serialize_on_root)
103  transferToSubAppRoot(app_problem, *_solution_container[local_i], i);
104  else
105  transferInParallel(app_problem, *_solution_container[local_i], i);
106  }
107  }
108 }
109 
110 void
112 {
114 
115  if (getFromMultiApp()->hasLocalApp(_app_index))
116  {
117  FEProblemBase & app_problem = getFromMultiApp()->appProblemBase(_app_index);
118 
119  // Here we have to branch out based on if only the root processors
120  // need to participate in the transfer or if we would like to distribute the
121  // data among every processor of the subapplication
122  if (_serialize_on_root)
124  else
126  }
127 }
128 
129 void
131  SolutionContainer & solution_container,
132  const dof_id_type global_i)
133 {
134  unsigned int local_app_index = global_i - _sampler_ptr->getLocalRowBegin();
135 
136  // Looping over the variables to extract the corresponding solution values
137  // and copy them into the container.
138  for (unsigned int var_i = 0; var_i < _variable_names.size(); ++var_i)
139  {
140  SystemBase & system = getSystem(app_problem, _variable_names[var_i]);
141 
142  // We need to go through this communicator because the multiapp's
143  // communicator is not necessarily the communicator of the underlying MooseObject.
144  const auto & comm = system.comm();
146  comm.sum(num_entries);
147 
148  // We shall distribute the samples on the given application between its processors.
149  // Only using a linear partitioning here for the sake of simplicity.
150  dof_id_type new_local_entries_begin;
151  dof_id_type new_local_entries_end;
152  dof_id_type num_new_local_entries;
153 
155  comm.size(),
156  comm.rank(),
157  num_new_local_entries,
158  new_local_entries_begin,
159  new_local_entries_end);
160 
161  // Getting the corresponding DoF indices for the variable.
162  system.setVariableGlobalDoFs(_variable_names[var_i]);
163 
164  for (const auto & snapshot : solution_container.getSnapshots())
165  {
166  DenseVector<Real> serialized_solution;
167 
168  // Localize the solution and add it to the local container on the rank
169  // which is supposed to own it
170  snapshot.localize(
171  serialized_solution.get_values(),
172  (local_app_index >= new_local_entries_begin && local_app_index < new_local_entries_end)
173  ? system.getVariableGlobalDoFs()
174  : std::vector<dof_id_type>());
175 
176  if (local_app_index >= new_local_entries_begin && local_app_index < new_local_entries_end)
177  _parallel_storage->addEntry(_variable_names[var_i], global_i, serialized_solution);
178  }
179  }
180 }
181 
182 void
184  SolutionContainer & solution_container,
185  const dof_id_type global_i)
186 {
187  // Looping over the variables to extract the corresponding solution values
188  for (unsigned int var_i = 0; var_i < _variable_names.size(); ++var_i)
189  {
190  SystemBase & system = getSystem(app_problem, _variable_names[var_i]);
191 
192  // Getting the corresponding DoF indices for the variable.
193  system.setVariableGlobalDoFs(_variable_names[var_i]);
194 
195  for (const auto & snapshot : solution_container.getSnapshots())
196  {
197  DenseVector<Real> serialized_solution;
198 
199  // In this case we always serialize on the root processor of the application.
200  snapshot.localize(serialized_solution.get_values(),
201  getFromMultiApp()->isRootProcessor() ? system.getVariableGlobalDoFs()
202  : std::vector<dof_id_type>());
203 
204  if (getFromMultiApp()->isRootProcessor())
205  _parallel_storage->addEntry(_variable_names[var_i], global_i, serialized_solution);
206  }
207  }
208 }
209 
210 SystemBase &
211 SerializedSolutionTransfer::getSystem(FEProblemBase & app_problem, const VariableName & vname)
212 {
213  auto & variable = app_problem.getVariable(_tid, vname);
214  return variable.sys();
215 }
dof_id_type _global_index
Index for tracking the row index when using batch mode operation.
Sampler * _sampler_ptr
Pointer to the Sampler object used by the SamplerTransientMultiApp or SamplerFullSolveMultiApp.
registerMooseObject("StochasticToolsApp", SerializedSolutionTransfer)
T & getUserObject(const std::string &name, unsigned int tid=0) const
const std::shared_ptr< MultiApp > getFromMultiApp() const
const Snapshots & getSnapshots() const
Return the whole snapshot container.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void initializeInNormalMode()
Initializes the solution container if the multiapp is run in normal mode.
void addEntry(const VariableName &vname, unsigned int global_i, const DenseVector< Real > &solution)
Add a new solution entry to the container.
SerializedSolutionTransfer(const InputParameters &parameters)
void initializeInBatchMode()
This routine queries the solution container addresses from the subapps.
processor_id_type rank() const
dof_id_type getLocalRowBegin() const
const Parallel::Communicator & comm() const
FEProblemBase & _fe_problem
void linearPartitionItems(dof_id_type num_items, dof_id_type num_chunks, dof_id_type chunk_id, dof_id_type &num_local_items, dof_id_type &local_items_begin, dof_id_type &local_items_end)
dof_id_type getNumberOfLocalRows() const
const bool _serialize_on_root
User-selected switch that determines if we want to serialize on the root of the subapp only or distri...
void transferInParallel(FEProblemBase &app_problem, SolutionContainer &solution_container, const dof_id_type global_i)
Serialize on methodically determined rank of the subapp and transfer to the main application.
void addRequiredParam(const std::string &name, const std::string &doc_string)
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
The class creates an additional API to allow Transfers to work when running the StochasticTools<FullS...
processor_id_type size() const
dof_id_type _app_index
Index for the sub-app that the batch-mode multiapp is working on.
static InputParameters validParams()
const std::vector< dof_id_type > & getVariableGlobalDoFs()
void paramError(const std::string &param, Args... args) const
static InputParameters validParams()
void transferToSubAppRoot(FEProblemBase &app_problem, SolutionContainer &solution_container, const dof_id_type global_i)
Serialize on the root processor of the subapplication and transfer the result to the main application...
SystemBase & getSystem(FEProblemBase &app_problem, const VariableName &vname)
Return the system which contains the given variable.
bool hasToMultiApp() const
virtual void initialSetup() override
void addClassDescription(const std::string &doc_string)
ParallelSolutionStorage * _parallel_storage
The storage on the main application where the serialized solutions should be transferred.
void setVariableGlobalDoFs(const std::string &var_name)
This class is responsible for collecting solution vectors in one place.
SystemBase & sys()
std::vector< VariableName > _variable_names
The names of the variables which should be extracted from the solution vector.
This class is responsible for serializing solutions coming from subapps on specific processors...
A Reporter which stores serialized solution fields for given variables in a distributed fashion...
std::vector< SolutionContainer * > _solution_container
Link to the storage spaces on the subapplications (will only hold one in batch mode) ...
uint8_t dof_id_type