https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SamplerParameterTransfer.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// MOOSE includes
14#include "SamplerReceiver.h"
15#include "Sampler.h"
16#include "MooseUtils.h"
17#include "pcrecpp.h"
18
19registerMooseObjectRenamed("StochasticToolsApp",
20 SamplerTransfer,
21 "01/01/2020 00:00",
24
27{
29 params.addClassDescription("Copies Sampler data to a SamplerReceiver object.");
30 params.suppressParameter<MultiMooseEnum>("direction");
31 params.suppressParameter<MultiAppName>("multi_app");
32 params.addParam<std::vector<std::string>>(
33 "parameters",
34 "A list of parameters (on the sub application) to control "
35 "with the Sampler data. The order of the parameters listed "
36 "here should match the order of the items in the Sampler.");
37 params.addDeprecatedParam<std::string>(
38 "to_control",
39 "Unused parameter.",
40 "This parameter is no longer used as the SamplerReceiver will automatically be detected.");
41 return params;
42}
43
45 : StochasticToolsTransfer(parameters),
46 _parameter_names(getParam<std::vector<std::string>>("parameters"))
47{
48 if (hasFromMultiApp())
49 paramError("from_multi_app", "From and between multiapp directions are not implemented");
50}
51
52void
54{
55 mooseAssert((_sampler_ptr->getNumberOfLocalRows() == 0) ||
56 (_sampler_ptr->getNumberOfLocalRows() == getToMultiApp()->numLocalApps()),
57 "The number of MultiApps and the number of sample rows must be the same.");
58
59 if (!getToMultiApp()->hasApp())
60 return;
61
62 // Loop over the MultiApp's own local app range rather than the sampler's local row
63 // range: the latter is only nonempty on a slot's root rank.
65 const dof_id_type first = getToMultiApp()->firstLocalApp();
66 const dof_id_type end = first + getToMultiApp()->numLocalApps();
67 for (dof_id_type row_index = first; row_index < end; ++row_index)
68 {
69 // Only the slot root has this row locally; share it with the rest of the slot.
70 std::vector<Real> row;
71 if (getToMultiApp()->isRootProcessor())
72 {
73 mooseAssert(row_index >= _sampler_ptr->getLocalRowBegin() &&
74 row_index < _sampler_ptr->getLocalRowEnd(),
75 "The current sample row index is not a valid local sampler row.");
76 row = _sampler_ptr->getSampleRow(row_index);
77 }
78 slot_comm.broadcast(row, 0);
79
80 // Get the command line arguments
82
83 // Get the sub-app SamplerReceiver objects and transfer param-values map
84 for (auto & ptr : getReceivers(row_index, args))
85 ptr.first->transfer(ptr.second);
86 }
87}
88
89void
91{
92 if (!getToMultiApp()->hasApp())
93 return;
94
95 // _row_data is only populated on the slot root; share it with the rest of the slot.
97 std::vector<Real> row = _row_data;
98 slot_comm.broadcast(row, 0);
99
100 // Get the command line arguments
102
103 // Get the sub-app SamplerReceiver objects and transfer param-values map
104 for (auto & ptr : getReceivers(_app_index, args))
105 ptr.first->transfer(ptr.second);
106}
107
108std::map<SamplerReceiver *, std::map<std::string, std::vector<Real>>>
110 const std::vector<std::string> & args)
111{
112 // These are the receivers we are returning
113 std::map<SamplerReceiver *, std::map<std::string, std::vector<Real>>> ptrs;
114
115 // Split all the input parameters to retrieve receivers and set param-values pairs
116 // Cache the multiapp-reciever mapping
117 std::unordered_map<std::string, std::vector<SamplerReceiver *>> multiapp_receivers;
118 for (const auto & param : args)
119 {
120 // Get MultiApp Name
121 std::string multiapp_name = getToMultiApp()->name();
122 const auto pos = param.rfind(":");
123 if (pos != std::string::npos)
124 multiapp_name += ":" + param.substr(0, pos);
125 // Get parameter name
126 const auto pos2 = param.rfind("=");
127 if (pos2 == std::string::npos)
128 mooseError("Internal error: Improper command-line format\n ", param, ".");
129 const std::string param_name = param.substr(pos + 1, pos2 - pos - 1);
130
131 // Get values
132 const std::string vstr = param.substr(pos2 + 1);
133 const auto vpos1 = vstr.find("'");
134 const auto vpos2 = vstr.rfind("'");
135 std::vector<Real> value;
136 if (!MooseUtils::tokenizeAndConvert(vstr.substr(vpos1 + 1, vpos2 - vpos1 - 1), value, " "))
137 mooseError("Internal error: Improper command-line format\n ", param, ".");
138
139 // Find receivers if we haven't already found them
140 if (multiapp_receivers.find(multiapp_name) == multiapp_receivers.end())
141 {
142 auto & recvs = multiapp_receivers[multiapp_name]; // Convenience
143 // Split the <sub>:<subsub>:<subsubsub> syntax
144 const std::vector<std::string> nested_names = MooseUtils::split(multiapp_name, ":");
145 // Find all the appropriate FEProblemBases based on the parameter syntax and get a
146 // SamplerReceiver
147 for (const auto & problem : getMultiAppProblemsHelper(
148 getToMultiApp()->appProblemBase(app_index),
149 std::vector<std::string>(nested_names.begin() + 1, nested_names.end())))
150 {
151 // Loop through all the active controls and find one that is a SamplerReciever
152 SamplerReceiver * recv_ptr = nullptr;
153 for (const auto & control_ptr : problem->getControlWarehouse().getActiveObjects())
154 {
155 recv_ptr = dynamic_cast<SamplerReceiver *>(control_ptr.get());
156 if (recv_ptr)
157 break;
158 }
159 if (!recv_ptr)
160 paramError("parameters",
161 "The sub-application (",
162 multiapp_name,
163 ") does not contain a SamplerReceiver control object.");
164
165 // Insert the found receiver
166 recvs.push_back(recv_ptr);
167 }
168 }
169
170 // Add the parameter and value to the reciever map
171 for (const auto & recv_ptr : multiapp_receivers[multiapp_name])
172 ptrs[recv_ptr][param_name] = value;
173 }
174
175 return ptrs;
176}
177
178std::vector<FEProblemBase *>
180 const std::vector<std::string> & multiapp_names)
181{
182 // This is what we'll return
183 std::vector<FEProblemBase *> problems;
184
185 if (multiapp_names.empty()) // Stop recursion if no nested apps provided
186 problems.push_back(&base_problem);
187 else
188 {
189 // Get the name of highest level app provided and the index if provided
190 std::string sub_name;
191 int sub_num = -1;
192 pcrecpp::RE("(\\S*?)(\\d*)").FullMatch(multiapp_names[0], &sub_name, &sub_num);
193 MultiApp & multiapp = *base_problem.getMultiApp(sub_name);
194
195 // Get the app indices (either the requested one or all of them)
196 std::pair<unsigned int, unsigned int> app_ind;
197 if (sub_num == -1) // There was no number provided, so get all the local sub apps
198 app_ind = std::make_pair(multiapp.firstLocalApp(),
199 multiapp.firstLocalApp() + multiapp.numLocalApps());
200 else if (multiapp.hasLocalApp(sub_num)) // Number provided, get that app if owned
201 app_ind = std::make_pair(sub_num, sub_num + 1);
202 else // This processor doesn't own the app index provided
203 return {};
204
205 // Get all the nested subapps with recursion
206 std::vector<std::string> nested_names(multiapp_names.begin() + 1, multiapp_names.end());
207 for (unsigned int i = app_ind.first; i < app_ind.second; ++i)
208 for (auto & prob : getMultiAppProblemsHelper(multiapp.appProblemBase(i), nested_names))
209 problems.push_back(prob);
210 }
211
212 return problems;
213}
registerMooseObject("StochasticToolsApp", SamplerParameterTransfer)
registerMooseObjectRenamed("StochasticToolsApp", SamplerTransfer, "01/01/2020 00:00", SamplerParameterTransfer)
std::shared_ptr< MultiApp > getMultiApp(const std::string &multi_app_name) const
void suppressParameter(const std::string &name)
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
const std::shared_ptr< MultiApp > getToMultiApp() const
bool hasFromMultiApp() const
unsigned int numLocalApps()
FEProblemBase & appProblemBase(unsigned int app)
bool hasLocalApp(unsigned int global_app) const
unsigned int firstLocalApp()
static std::vector< std::string > sampledCommandLineArgs(const std::vector< Real > &row, const std::vector< std::string > &full_args_name)
Helper for inserting row data into commandline arguments Used here and in SamplerTransientMultiApp.
Copy each row from each DenseMatrix to the sub-applications SamplerReceiver object.
static InputParameters validParams()
virtual void executeToMultiapp() override
Methods used when running in batch mode (see SamplerFullSolveMultiApp)
const std::vector< std::string > & _parameter_names
Storage for the list of parameters to control.
SamplerParameterTransfer(const InputParameters &parameters)
std::map< SamplerReceiver *, std::map< std::string, std::vector< Real > > > getReceivers(unsigned int app_index, const std::vector< std::string > &args)
Based on command line args, return a map between SamplerReceiver objects and the parameter-value pair...
virtual void execute() override
Traditional Transfer callback.
static std::vector< FEProblemBase * > getMultiAppProblemsHelper(FEProblemBase &base_problem, const std::vector< std::string > &multiapp_names)
Helper function that recursively finds feproblem pointers from nested multiapps.
A Control object for receiving data from a master application Sampler object.
dof_id_type getNumberOfLocalRows() const
dof_id_type getLocalRowBegin() const
std::vector< Real > getSampleRow(dof_id_type row_index) const
The class creates an additional API to allow Transfers to work when running the StochasticTools<FullS...
static InputParameters validParams()
std::vector< Real > _row_data
The current row of data (comes from multiapp)
dof_id_type _app_index
Index for the sub-app that the batch-mode multiapp is working on.
Sampler * _sampler_ptr
Pointer to the Sampler object used by the SamplerTransientMultiApp or SamplerFullSolveMultiApp.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
const Parallel::Communicator & comm() const
std::vector< std::string > split(const std::string &str, const std::string &delimiter, std::size_t max_count)
bool tokenizeAndConvert(const std::string &str, std::vector< T > &tokenized_vector, const std::string &delimiter=" \t\n\v\f\r", bool throw_on_unreadable=false)