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 5776 : SamplerParameterTransfer::validParams() 27 : { 28 5776 : InputParameters params = StochasticToolsTransfer::validParams(); 29 5776 : params.addClassDescription("Copies Sampler data to a SamplerReceiver object."); 30 5776 : params.suppressParameter<MultiMooseEnum>("direction"); 31 5776 : params.suppressParameter<MultiAppName>("multi_app"); 32 11552 : 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 11552 : 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 5776 : return params; 42 0 : } 43 : 44 2878 : SamplerParameterTransfer::SamplerParameterTransfer(const InputParameters & parameters) 45 : : StochasticToolsTransfer(parameters), 46 5744 : _parameter_names(getParam<std::vector<std::string>>("parameters")) 47 : { 48 2866 : if (hasFromMultiApp()) 49 0 : paramError("from_multi_app", "From and between multiapp directions are not implemented"); 50 2866 : } 51 : 52 : void 53 3236 : 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 9788 : for (dof_id_type row_index = _sampler_ptr->getLocalRowBegin(); 61 9788 : 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 6564 : std::vector<Real> row = _sampler_ptr->getNextLocalRow(); 69 : 70 : // Get the command line arguments 71 6564 : const auto args = SamplerFullSolveMultiApp::sampledCommandLineArgs(row, _parameter_names); 72 : 73 : // Get the sub-app SamplerReceiver objects and transfer param-values map 74 14188 : for (auto & ptr : getReceivers(row_index, args)) 75 7632 : ptr.first->transfer(ptr.second); 76 6552 : } 77 3224 : } 78 : 79 : void 80 15780 : SamplerParameterTransfer::executeToMultiapp() 81 : { 82 31560 : if (getToMultiApp()->isRootProcessor()) 83 : { 84 : // Get the command line arguments 85 14780 : const auto args = SamplerFullSolveMultiApp::sampledCommandLineArgs(_row_data, _parameter_names); 86 : 87 : // Get the sub-app SamplerReceiver objects and transfer param-values map 88 31720 : for (auto & ptr : getReceivers(_app_index, args)) 89 16940 : ptr.first->transfer(ptr.second); 90 14780 : } 91 15780 : } 92 : 93 : std::map<SamplerReceiver *, std::map<std::string, std::vector<Real>>> 94 21336 : 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 70812 : for (const auto & param : args) 104 : { 105 : // Get MultiApp Name 106 49480 : std::string multiapp_name = getToMultiApp()->name(); 107 49480 : const auto pos = param.rfind(":"); 108 49480 : if (pos != std::string::npos) 109 8640 : multiapp_name += ":" + param.substr(0, pos); 110 : // Get parameter name 111 49480 : const auto pos2 = param.rfind("="); 112 49480 : if (pos2 == std::string::npos) 113 0 : mooseError("Internal error: Improper command-line format\n ", param, "."); 114 49480 : const std::string param_name = param.substr(pos + 1, pos2 - pos - 1); 115 : 116 : // Get values 117 49480 : const std::string vstr = param.substr(pos2 + 1); 118 49480 : const auto vpos1 = vstr.find("'"); 119 49480 : const auto vpos2 = vstr.rfind("'"); 120 : std::vector<Real> value; 121 98960 : 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 49480 : 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 51312 : 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 25656 : for (const auto & problem : getMultiAppProblemsHelper( 133 25656 : getToMultiApp()->appProblemBase(app_index), 134 103700 : 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 26736 : SamplerReceiver * recv_ptr = nullptr; 138 26736 : for (const auto & control_ptr : problem->getControlWarehouse().getActiveObjects()) 139 : { 140 26732 : recv_ptr = dynamic_cast<SamplerReceiver *>(control_ptr.get()); 141 26732 : if (recv_ptr) 142 : break; 143 : } 144 26736 : 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 26732 : recvs.push_back(recv_ptr); 152 : } 153 25652 : } 154 : 155 : // Add the parameter and value to the reciever map 156 100032 : for (const auto & recv_ptr : multiapp_receivers[multiapp_name]) 157 50556 : ptrs[recv_ptr][param_name] = value; 158 : } 159 : 160 21332 : return ptrs; 161 : } 162 : 163 : std::vector<FEProblemBase *> 164 34296 : 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 34296 : if (multiapp_names.empty()) // Stop recursion if no nested apps provided 171 26736 : 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 7560 : int sub_num = -1; 177 7560 : pcrecpp::RE("(\\S*?)(\\d*)").FullMatch(multiapp_names[0], &sub_name, &sub_num); 178 7560 : 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 7560 : 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 5400 : multiapp.firstLocalApp() + multiapp.numLocalApps()); 185 2160 : else if (multiapp.hasLocalApp(sub_num)) // Number provided, get that app if owned 186 2160 : 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 7560 : std::vector<std::string> nested_names(multiapp_names.begin() + 1, multiapp_names.end()); 192 16200 : for (unsigned int i = app_ind.first; i < app_ind.second; ++i) 193 18360 : for (auto & prob : getMultiAppProblemsHelper(multiapp.appProblemBase(i), nested_names)) 194 9720 : problems.push_back(prob); 195 7560 : } 196 : 197 : return problems; 198 : }