Line data Source code
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 11 : #include "SamplerParameterTransfer.h" 12 : #include "SamplerTransientMultiApp.h" 13 : #include "SamplerFullSolveMultiApp.h" 14 : #include "SamplerReceiver.h" 15 : #include "Sampler.h" 16 : #include "MooseUtils.h" 17 : #include "pcrecpp.h" 18 : 19 : registerMooseObjectRenamed("StochasticToolsApp", 20 : SamplerTransfer, 21 : "01/01/2020 00:00", 22 : SamplerParameterTransfer); 23 : registerMooseObject("StochasticToolsApp", SamplerParameterTransfer); 24 : 25 : InputParameters 26 6198 : SamplerParameterTransfer::validParams() 27 : { 28 6198 : InputParameters params = StochasticToolsTransfer::validParams(); 29 6198 : params.addClassDescription("Copies Sampler data to a SamplerReceiver object."); 30 6198 : params.suppressParameter<MultiMooseEnum>("direction"); 31 6198 : params.suppressParameter<MultiAppName>("multi_app"); 32 12396 : 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 12396 : 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 6198 : return params; 42 0 : } 43 : 44 3089 : SamplerParameterTransfer::SamplerParameterTransfer(const InputParameters & parameters) 45 : : StochasticToolsTransfer(parameters), 46 6166 : _parameter_names(getParam<std::vector<std::string>>("parameters")) 47 : { 48 3077 : if (hasFromMultiApp()) 49 0 : paramError("from_multi_app", "From and between multiapp directions are not implemented"); 50 3077 : } 51 : 52 : void 53 3483 : SamplerParameterTransfer::execute() 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 : // Loop over all sub-apps 60 10683 : for (dof_id_type row_index = _sampler_ptr->getLocalRowBegin(); 61 10683 : row_index < _sampler_ptr->getLocalRowEnd(); 62 : row_index++) 63 : { 64 : mooseAssert(getToMultiApp()->hasLocalApp(row_index), 65 : "The current sample row index is not a valid global MultiApp index."); 66 : 67 : // Populate the row of data to transfer 68 7212 : std::vector<Real> row = _sampler_ptr->getNextLocalRow(); 69 : 70 : // Get the command line arguments 71 7212 : const auto args = SamplerFullSolveMultiApp::sampledCommandLineArgs(row, _parameter_names); 72 : 73 : // Get the sub-app SamplerReceiver objects and transfer param-values map 74 15592 : for (auto & ptr : getReceivers(row_index, args)) 75 8388 : ptr.first->transfer(ptr.second); 76 7200 : } 77 3471 : } 78 : 79 : void 80 17194 : SamplerParameterTransfer::executeToMultiapp() 81 : { 82 34388 : if (getToMultiApp()->isRootProcessor()) 83 : { 84 : // Get the command line arguments 85 16112 : const auto args = SamplerFullSolveMultiApp::sampledCommandLineArgs(_row_data, _parameter_names); 86 : 87 : // Get the sub-app SamplerReceiver objects and transfer param-values map 88 34600 : for (auto & ptr : getReceivers(_app_index, args)) 89 18488 : ptr.first->transfer(ptr.second); 90 16112 : } 91 17194 : } 92 : 93 : std::map<SamplerReceiver *, std::map<std::string, std::vector<Real>>> 94 23316 : SamplerParameterTransfer::getReceivers(unsigned int app_index, 95 : const std::vector<std::string> & args) 96 : { 97 : // These are the receivers we are returning 98 : std::map<SamplerReceiver *, std::map<std::string, std::vector<Real>>> ptrs; 99 : 100 : // Split all the input parameters to retrieve receivers and set param-values pairs 101 : // Cache the multiapp-reciever mapping 102 : std::unordered_map<std::string, std::vector<SamplerReceiver *>> multiapp_receivers; 103 77424 : for (const auto & param : args) 104 : { 105 : // Get MultiApp Name 106 54112 : std::string multiapp_name = getToMultiApp()->name(); 107 54112 : const auto pos = param.rfind(":"); 108 54112 : if (pos != std::string::npos) 109 9504 : multiapp_name += ":" + param.substr(0, pos); 110 : // Get parameter name 111 54112 : const auto pos2 = param.rfind("="); 112 54112 : if (pos2 == std::string::npos) 113 0 : mooseError("Internal error: Improper command-line format\n ", param, "."); 114 54112 : const std::string param_name = param.substr(pos + 1, pos2 - pos - 1); 115 : 116 : // Get values 117 54112 : const std::string vstr = param.substr(pos2 + 1); 118 54112 : const auto vpos1 = vstr.find("'"); 119 54112 : const auto vpos2 = vstr.rfind("'"); 120 : std::vector<Real> value; 121 108224 : if (!MooseUtils::tokenizeAndConvert(vstr.substr(vpos1 + 1, vpos2 - vpos1 - 1), value, " ")) 122 0 : mooseError("Internal error: Improper command-line format\n ", param, "."); 123 : 124 : // Find receivers if we haven't already found them 125 54112 : if (multiapp_receivers.find(multiapp_name) == multiapp_receivers.end()) 126 : { 127 : auto & recvs = multiapp_receivers[multiapp_name]; // Convenience 128 : // Split the <sub>:<subsub>:<subsubsub> syntax 129 56136 : const std::vector<std::string> nested_names = MooseUtils::split(multiapp_name, ":"); 130 : // Find all the appropriate FEProblemBases based on the parameter syntax and get a 131 : // SamplerReceiver 132 28068 : for (const auto & problem : getMultiAppProblemsHelper( 133 28068 : getToMultiApp()->appProblemBase(app_index), 134 113456 : std::vector<std::string>(nested_names.begin() + 1, nested_names.end()))) 135 : { 136 : // Loop through all the active controls and find one that is a SamplerReciever 137 29256 : SamplerReceiver * recv_ptr = nullptr; 138 29256 : for (const auto & control_ptr : problem->getControlWarehouse().getActiveObjects()) 139 : { 140 29252 : recv_ptr = dynamic_cast<SamplerReceiver *>(control_ptr.get()); 141 29252 : if (recv_ptr) 142 : break; 143 : } 144 29256 : if (!recv_ptr) 145 4 : paramError("parameters", 146 : "The sub-application (", 147 : multiapp_name, 148 : ") does not contain a SamplerReceiver control object."); 149 : 150 : // Insert the found receiver 151 29252 : recvs.push_back(recv_ptr); 152 28064 : } 153 28064 : } 154 : 155 : // Add the parameter and value to the reciever map 156 109404 : for (const auto & recv_ptr : multiapp_receivers[multiapp_name]) 157 55296 : ptrs[recv_ptr][param_name] = value; 158 54108 : } 159 : 160 23312 : return ptrs; 161 : } 162 : 163 : std::vector<FEProblemBase *> 164 37572 : SamplerParameterTransfer::getMultiAppProblemsHelper(FEProblemBase & base_problem, 165 : const std::vector<std::string> & multiapp_names) 166 : { 167 : // This is what we'll return 168 : std::vector<FEProblemBase *> problems; 169 : 170 37572 : if (multiapp_names.empty()) // Stop recursion if no nested apps provided 171 29256 : problems.push_back(&base_problem); 172 : else 173 : { 174 : // Get the name of highest level app provided and the index if provided 175 : std::string sub_name; 176 8316 : int sub_num = -1; 177 8316 : pcrecpp::RE("(\\S*?)(\\d*)").FullMatch(multiapp_names[0], &sub_name, &sub_num); 178 8316 : MultiApp & multiapp = *base_problem.getMultiApp(sub_name); 179 : 180 : // Get the app indices (either the requested one or all of them) 181 : std::pair<unsigned int, unsigned int> app_ind; 182 8316 : if (sub_num == -1) // There was no number provided, so get all the local sub apps 183 : app_ind = std::make_pair(multiapp.firstLocalApp(), 184 5940 : multiapp.firstLocalApp() + multiapp.numLocalApps()); 185 2376 : else if (multiapp.hasLocalApp(sub_num)) // Number provided, get that app if owned 186 2376 : app_ind = std::make_pair(sub_num, sub_num + 1); 187 : else // This processor doesn't own the app index provided 188 0 : return {}; 189 : 190 : // Get all the nested subapps with recursion 191 8316 : std::vector<std::string> nested_names(multiapp_names.begin() + 1, multiapp_names.end()); 192 17820 : for (unsigned int i = app_ind.first; i < app_ind.second; ++i) 193 20196 : for (auto & prob : getMultiAppProblemsHelper(multiapp.appProblemBase(i), nested_names)) 194 20196 : problems.push_back(prob); 195 8316 : } 196 : 197 : return problems; 198 37572 : }