LCOV - code coverage report
Current view: top level - src/multiapps - SamplerTransientMultiApp.C (source / functions) Hit Total Coverage
Test: idaholab/moose stochastic_tools: #32971 (54bef8) with base c6cf66 Lines: 112 116 96.6 %
Date: 2026-05-29 20:40:35 Functions: 8 8 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             : // StochasticTools includes
      11             : #include "SamplerTransientMultiApp.h"
      12             : #include "Sampler.h"
      13             : #include "StochasticToolsTransfer.h"
      14             : #include "SamplerFullSolveMultiApp.h"
      15             : 
      16             : registerMooseObject("StochasticToolsApp", SamplerTransientMultiApp);
      17             : 
      18             : InputParameters
      19         604 : SamplerTransientMultiApp::validParams()
      20             : {
      21         604 :   InputParameters params = TransientMultiApp::validParams();
      22         604 :   params += SamplerInterface::validParams();
      23         604 :   params.addClassDescription("Creates a sub-application for each row of each Sampler matrix.");
      24        1208 :   params.addRequiredParam<SamplerName>("sampler",
      25             :                                        "The Sampler object to utilize for creating MultiApps.");
      26         604 :   params.suppressParameter<std::vector<Point>>("positions");
      27         604 :   params.suppressParameter<bool>("output_in_position");
      28         604 :   params.suppressParameter<std::vector<FileName>>("positions_file");
      29         604 :   params.suppressParameter<Real>("move_time");
      30         604 :   params.suppressParameter<std::vector<Point>>("move_positions");
      31         604 :   params.suppressParameter<std::vector<unsigned int>>("move_apps");
      32         604 :   params.set<bool>("use_positions") = false;
      33             : 
      34             :   // use "batch-restore=2" to be consistent with SamplerFullSolveMultiApp and use the
      35             :   // allow_out_of_range flag to allow the StochasticToolsTransfer object to inspect the MultiApp
      36             :   // object parameters without triggering an assert.
      37        1208 :   MooseEnum modes("normal=0 batch-reset=1 batch-restore=2", "normal");
      38        1208 :   params.addParam<MooseEnum>(
      39             :       "mode",
      40             :       modes,
      41             :       "The operation mode, 'normal' creates one sub-application for each row in the Sampler and "
      42             :       "'batch-reset' and 'batch-restore' creates N sub-applications, where N is the minimum of "
      43             :       "'num_rows' in the Sampler and floor(number of processes / min_procs_per_app). To run "
      44             :       "the rows in the Sampler, 'batch-reset' will destroy and re-create sub-apps as needed, "
      45             :       "whereas the 'batch-restore' will backup and restore sub-apps to the initial state prior "
      46             :       "to execution, without destruction.");
      47             : 
      48         604 :   return params;
      49         604 : }
      50             : 
      51         303 : SamplerTransientMultiApp::SamplerTransientMultiApp(const InputParameters & parameters)
      52             :   : TransientMultiApp(parameters),
      53             :     SamplerInterface(this),
      54         303 :     _sampler(getSampler("sampler")),
      55         606 :     _mode(getParam<MooseEnum>("mode").getEnum<StochasticTools::MultiAppMode>()),
      56         303 :     _local_batch_app_index(0),
      57         606 :     _number_of_sampler_rows(_sampler.getNumberOfRows())
      58             : {
      59         303 :   if (_mode == StochasticTools::MultiAppMode::BATCH_RESET)
      60           4 :     paramError("mode",
      61             :                "The supplied mode, '",
      62             :                getParam<MooseEnum>("mode"),
      63             :                "', currently is not implemented for the SamplerTransientMultiApp, the available "
      64             :                "options are 'normal' or 'batch-restore'.");
      65             : 
      66         602 :   if (getParam<unsigned int>("min_procs_per_app") !=
      67         903 :           _sampler.getParam<unsigned int>("min_procs_per_row") ||
      68         602 :       getParam<unsigned int>("max_procs_per_app") !=
      69         903 :           _sampler.getParam<unsigned int>("max_procs_per_row"))
      70           0 :     paramError("sampler",
      71             :                "Sampler and multiapp communicator configuration inconsistent. Please ensure that "
      72             :                "'MultiApps/",
      73             :                name(),
      74             :                "/min(max)_procs_per_app' and 'Samplers/",
      75           0 :                _sampler.name(),
      76             :                "/min(max)_procs_per_row' are the same.");
      77             : 
      78         301 :   init(_sampler.getNumberOfRows(),
      79         301 :        _sampler.getRankConfig(_mode == StochasticTools::MultiAppMode::BATCH_RESET ||
      80             :                               _mode == StochasticTools::MultiAppMode::BATCH_RESTORE));
      81         301 : }
      82             : 
      83             : void
      84         297 : SamplerTransientMultiApp::initialSetup()
      85             : {
      86         594 :   TIME_SECTION("initialSetup", 2, "Setting Up SamplerTransientMultiApp");
      87             : 
      88         297 :   TransientMultiApp::initialSetup();
      89             : 
      90             :   // Perform initial backup for the batch sub-applications
      91         297 :   if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
      92             :   {
      93          85 :     dof_id_type n = _rank_config.num_local_sims;
      94          85 :     _batch_backup.resize(n);
      95         335 :     for (MooseIndex(n) i = 0; i < n; ++i)
      96         500 :       for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
      97         250 :         _batch_backup[i].emplace_back(_apps[j]->backup());
      98             :   }
      99         297 : }
     100             : 
     101             : bool
     102         906 : SamplerTransientMultiApp::solveStep(Real dt, Real target_time, bool auto_advance)
     103             : {
     104        1812 :   TIME_SECTION("solveStep", 3, "Solving SamplerTransientMultiApp");
     105             : 
     106         906 :   if (_sampler.getNumberOfRows() != _number_of_sampler_rows)
     107           2 :     mooseError("The size of the sampler has changed; SamplerTransientMultiApp object do not "
     108             :                "support dynamic Sampler output.");
     109             : 
     110             :   bool last_solve_converged = true;
     111         904 :   if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
     112         276 :     last_solve_converged = solveStepBatch(dt, target_time, auto_advance);
     113             :   else
     114         628 :     last_solve_converged = TransientMultiApp::solveStep(dt, target_time, auto_advance);
     115         900 :   return last_solve_converged;
     116         900 : }
     117             : 
     118             : bool
     119         276 : SamplerTransientMultiApp::solveStepBatch(Real dt, Real target_time, bool auto_advance)
     120             : {
     121             :   // Value to return
     122             :   bool last_solve_converged = true;
     123             : 
     124             :   // List of active relevant Transfer objects
     125             :   std::vector<std::shared_ptr<StochasticToolsTransfer>> to_transfers =
     126         276 :       getActiveStochasticToolsTransfers(MultiAppTransfer::TO_MULTIAPP);
     127             :   std::vector<std::shared_ptr<StochasticToolsTransfer>> from_transfers =
     128         276 :       getActiveStochasticToolsTransfers(MultiAppTransfer::FROM_MULTIAPP);
     129             : 
     130             :   // Initialize to/from transfers
     131         552 :   for (auto transfer : to_transfers)
     132             :   {
     133         276 :     transfer->setGlobalMultiAppIndex(_rank_config.first_local_app_index);
     134         276 :     transfer->initializeToMultiapp();
     135             :   }
     136         552 :   for (auto transfer : from_transfers)
     137             :   {
     138         276 :     transfer->setGlobalMultiAppIndex(_rank_config.first_local_app_index);
     139         276 :     transfer->initializeFromMultiapp();
     140             :   }
     141             : 
     142             :   // Perform batch MultiApp solves
     143         276 :   _local_batch_app_index = 0;
     144         276 :   for (dof_id_type i = _rank_config.first_local_sim_index;
     145        1126 :        i < _rank_config.first_local_sim_index + _rank_config.num_local_sims;
     146             :        ++i)
     147             :   {
     148         850 :     updateRowData(_local_batch_app_index);
     149             : 
     150         850 :     if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
     151        1700 :       for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
     152             :       {
     153         850 :         _apps[j]->restore(std::move(_batch_backup[_local_batch_app_index][j]), false);
     154         850 :         _apps[j]->finalizeRestore();
     155             :       }
     156             : 
     157         850 :     SamplerFullSolveMultiApp::execBatchTransfers(to_transfers,
     158             :                                                  i,
     159         850 :                                                  _row_data,
     160             :                                                  MultiAppTransfer::TO_MULTIAPP,
     161         850 :                                                  _fe_problem.verboseMultiApps(),
     162         850 :                                                  _console);
     163             : 
     164             :     // Set the file base based on the current row
     165        1700 :     for (unsigned int ai = 0; ai < _my_num_apps; ++ai)
     166             :     {
     167         850 :       const std::string mname = getMultiAppName(name(), i, _number_of_sampler_rows);
     168        2550 :       _apps[ai]->setOutputFileBase(_app.getOutputFileBase() + "_" + mname);
     169             :     }
     170             : 
     171             :     const bool curr_last_solve_converged =
     172         850 :         TransientMultiApp::solveStep(dt, target_time, auto_advance);
     173         850 :     last_solve_converged = last_solve_converged && curr_last_solve_converged;
     174             : 
     175         850 :     SamplerFullSolveMultiApp::execBatchTransfers(from_transfers,
     176             :                                                  i,
     177             :                                                  _row_data,
     178             :                                                  MultiAppTransfer::FROM_MULTIAPP,
     179         850 :                                                  _fe_problem.verboseMultiApps(),
     180             :                                                  _console);
     181             : 
     182         850 :     incrementTStep(target_time);
     183             : 
     184         850 :     if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
     185        1700 :       for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
     186         850 :         _batch_backup[_local_batch_app_index][j] = _apps[j]->backup();
     187             : 
     188         850 :     _local_batch_app_index++;
     189             :   }
     190         276 :   _local_batch_app_index = 0;
     191             : 
     192             :   // Finalize to/from transfers
     193         552 :   for (auto transfer : to_transfers)
     194         276 :     transfer->finalizeToMultiapp();
     195         552 :   for (auto transfer : from_transfers)
     196         276 :     transfer->finalizeFromMultiapp();
     197             : 
     198         276 :   return last_solve_converged;
     199         276 : }
     200             : 
     201             : std::vector<std::shared_ptr<StochasticToolsTransfer>>
     202         552 : SamplerTransientMultiApp::getActiveStochasticToolsTransfers(Transfer::DIRECTION direction)
     203             : {
     204             :   std::vector<std::shared_ptr<StochasticToolsTransfer>> output;
     205             :   const ExecuteMooseObjectWarehouse<Transfer> & warehouse =
     206         552 :       _fe_problem.getMultiAppTransferWarehouse(direction);
     207        1132 :   for (std::shared_ptr<Transfer> transfer : warehouse.getActiveObjects())
     208             :   {
     209             :     std::shared_ptr<StochasticToolsTransfer> ptr =
     210         580 :         std::dynamic_pointer_cast<StochasticToolsTransfer>(transfer);
     211        1132 :     if (ptr && ptr->getMultiApp().get() == this)
     212         552 :       output.push_back(ptr);
     213             :   }
     214         552 :   return output;
     215           0 : }
     216             : 
     217             : std::vector<std::string>
     218         227 : SamplerTransientMultiApp::getCommandLineArgs(const unsigned int local_app)
     219             : {
     220             :   std::vector<std::string> args;
     221             : 
     222             :   // With multiple processors per app, there are no local rows for non-root processors
     223         227 :   if (isRootProcessor())
     224             :   {
     225             :     // Since we only store param_names in cli_args, we need to find the values for each param from
     226             :     // sampler data and combine them to get full command line option strings.
     227         197 :     updateRowData(_mode == StochasticTools::MultiAppMode::NORMAL ? local_app
     228             :                                                                  : _local_batch_app_index);
     229         197 :     args = SamplerFullSolveMultiApp::sampledCommandLineArgs(
     230         394 :         _row_data, TransientMultiApp::getCommandLineArgs(local_app));
     231             :   }
     232             : 
     233         227 :   _my_communicator.broadcast(args);
     234         227 :   return args;
     235           0 : }
     236             : 
     237             : void
     238        1047 : SamplerTransientMultiApp::updateRowData(dof_id_type local_index)
     239             : {
     240        1047 :   if (!isRootProcessor())
     241             :     return;
     242             : 
     243             :   mooseAssert(local_index < _sampler.getNumberOfLocalRows(),
     244             :               "Local index must be less than number of local rows.");
     245             : 
     246         957 :   if (_row_data.empty() ||
     247         824 :       (_local_row_index == _sampler.getNumberOfLocalRows() - 1 && local_index == 0))
     248             :   {
     249             :     mooseAssert(local_index == 0,
     250             :                 "The first time calling updateRowData must have a local index of 0.");
     251         294 :     _local_row_index = 0;
     252         294 :     _row_data = _sampler.getNextLocalRow();
     253             :   }
     254         663 :   else if (local_index - _local_row_index == 1)
     255             :   {
     256         656 :     _local_row_index++;
     257         656 :     _row_data = _sampler.getNextLocalRow();
     258             :   }
     259             : 
     260             :   mooseAssert(local_index == _local_row_index,
     261             :               "Local index must be equal or one greater than the index previously called.");
     262             : }

Generated by: LCOV version 1.14