LCOV - code coverage report
Current view: top level - src/transfers - SamplerParameterTransfer.C (source / functions) Hit Total Coverage
Test: idaholab/moose stochastic_tools: f45d79 Lines: 72 77 93.5 %
Date: 2025-07-25 05:00:46 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.14