LCOV - code coverage report
Current view: top level - src/multiapps - SamplerTransientMultiApp.C (source / functions) Hit Total Coverage
Test: idaholab/moose stochastic_tools: f45d79 Lines: 111 115 96.5 %
Date: 2025-07-25 05:00:46 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        1304 : SamplerTransientMultiApp::validParams()
      20             : {
      21        1304 :   InputParameters params = TransientMultiApp::validParams();
      22        1304 :   params += SamplerInterface::validParams();
      23        1304 :   params.addClassDescription("Creates a sub-application for each row of each Sampler matrix.");
      24        2608 :   params.addRequiredParam<SamplerName>("sampler",
      25             :                                        "The Sampler object to utilize for creating MultiApps.");
      26        1304 :   params.suppressParameter<std::vector<Point>>("positions");
      27        1304 :   params.suppressParameter<bool>("output_in_position");
      28        1304 :   params.suppressParameter<std::vector<FileName>>("positions_file");
      29        1304 :   params.suppressParameter<Real>("move_time");
      30        1304 :   params.suppressParameter<std::vector<Point>>("move_positions");
      31        1304 :   params.suppressParameter<std::vector<unsigned int>>("move_apps");
      32        1304 :   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        2608 :   MooseEnum modes("normal=0 batch-reset=1 batch-restore=2", "normal");
      38        2608 :   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        1304 :   return params;
      49        1304 : }
      50             : 
      51         654 : SamplerTransientMultiApp::SamplerTransientMultiApp(const InputParameters & parameters)
      52             :   : TransientMultiApp(parameters),
      53             :     SamplerInterface(this),
      54         654 :     _sampler(getSampler("sampler")),
      55        1308 :     _mode(getParam<MooseEnum>("mode").getEnum<StochasticTools::MultiAppMode>()),
      56         654 :     _local_batch_app_index(0),
      57        1308 :     _number_of_sampler_rows(_sampler.getNumberOfRows())
      58             : {
      59         654 :   if (_mode == StochasticTools::MultiAppMode::BATCH_RESET)
      60           8 :     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        1300 :   if (getParam<unsigned int>("min_procs_per_app") !=
      67        1950 :           _sampler.getParam<unsigned int>("min_procs_per_row") ||
      68        1300 :       getParam<unsigned int>("max_procs_per_app") !=
      69        1950 :           _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         650 :   init(_sampler.getNumberOfRows(),
      79         650 :        _sampler.getRankConfig(_mode == StochasticTools::MultiAppMode::BATCH_RESET ||
      80             :                               _mode == StochasticTools::MultiAppMode::BATCH_RESTORE));
      81         650 : }
      82             : 
      83             : void
      84         642 : SamplerTransientMultiApp::initialSetup()
      85             : {
      86        1284 :   TIME_SECTION("initialSetup", 2, "Setting Up SamplerTransientMultiApp");
      87             : 
      88         642 :   TransientMultiApp::initialSetup();
      89             : 
      90             :   // Perform initial backup for the batch sub-applications
      91         642 :   if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
      92             :   {
      93         180 :     dof_id_type n = _rank_config.num_local_sims;
      94         180 :     _batch_backup.resize(n);
      95         680 :     for (MooseIndex(n) i = 0; i < n; ++i)
      96        1000 :       for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
      97         500 :         _batch_backup[i].emplace_back(_apps[j]->backup());
      98             :   }
      99         642 : }
     100             : 
     101             : bool
     102        1978 : SamplerTransientMultiApp::solveStep(Real dt, Real target_time, bool auto_advance)
     103             : {
     104        3956 :   TIME_SECTION("solveStep", 3, "Solving SamplerTransientMultiApp");
     105             : 
     106        1978 :   if (_sampler.getNumberOfRows() != _number_of_sampler_rows)
     107           4 :     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        1974 :   if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
     112         588 :     last_solve_converged = solveStepBatch(dt, target_time, auto_advance);
     113             :   else
     114        1386 :     last_solve_converged = TransientMultiApp::solveStep(dt, target_time, auto_advance);
     115        1966 :   return last_solve_converged;
     116             : }
     117             : 
     118             : bool
     119         588 : 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         588 :       getActiveStochasticToolsTransfers(MultiAppTransfer::TO_MULTIAPP);
     127             :   std::vector<std::shared_ptr<StochasticToolsTransfer>> from_transfers =
     128         588 :       getActiveStochasticToolsTransfers(MultiAppTransfer::FROM_MULTIAPP);
     129             : 
     130             :   // Initialize to/from transfers
     131        1176 :   for (auto transfer : to_transfers)
     132             :   {
     133         588 :     transfer->setGlobalMultiAppIndex(_rank_config.first_local_app_index);
     134         588 :     transfer->initializeToMultiapp();
     135             :   }
     136        1176 :   for (auto transfer : from_transfers)
     137             :   {
     138         588 :     transfer->setGlobalMultiAppIndex(_rank_config.first_local_app_index);
     139         588 :     transfer->initializeFromMultiapp();
     140             :   }
     141             : 
     142             :   // Perform batch MultiApp solves
     143         588 :   _local_batch_app_index = 0;
     144         588 :   for (dof_id_type i = _rank_config.first_local_sim_index;
     145        2288 :        i < _rank_config.first_local_sim_index + _rank_config.num_local_sims;
     146             :        ++i)
     147             :   {
     148        1700 :     updateRowData(_local_batch_app_index);
     149             : 
     150        1700 :     if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
     151        3400 :       for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
     152             :       {
     153        1700 :         _apps[j]->restore(std::move(_batch_backup[_local_batch_app_index][j]), false);
     154        1700 :         _apps[j]->finalizeRestore();
     155             :       }
     156             : 
     157        1700 :     SamplerFullSolveMultiApp::execBatchTransfers(to_transfers,
     158             :                                                  i,
     159        1700 :                                                  _row_data,
     160             :                                                  MultiAppTransfer::TO_MULTIAPP,
     161        1700 :                                                  _fe_problem.verboseMultiApps(),
     162        1700 :                                                  _console);
     163             : 
     164             :     // Set the file base based on the current row
     165        3400 :     for (unsigned int ai = 0; ai < _my_num_apps; ++ai)
     166             :     {
     167        1700 :       const std::string mname = getMultiAppName(name(), i, _number_of_sampler_rows);
     168        5100 :       _apps[ai]->setOutputFileBase(_app.getOutputFileBase() + "_" + mname);
     169             :     }
     170             : 
     171             :     const bool curr_last_solve_converged =
     172        1700 :         TransientMultiApp::solveStep(dt, target_time, auto_advance);
     173        1700 :     last_solve_converged = last_solve_converged && curr_last_solve_converged;
     174             : 
     175        1700 :     SamplerFullSolveMultiApp::execBatchTransfers(from_transfers,
     176             :                                                  i,
     177             :                                                  _row_data,
     178             :                                                  MultiAppTransfer::FROM_MULTIAPP,
     179        1700 :                                                  _fe_problem.verboseMultiApps(),
     180             :                                                  _console);
     181             : 
     182        1700 :     incrementTStep(target_time);
     183             : 
     184        1700 :     if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
     185        3400 :       for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
     186        1700 :         _batch_backup[_local_batch_app_index][j] = _apps[j]->backup();
     187             : 
     188        1700 :     _local_batch_app_index++;
     189             :   }
     190         588 :   _local_batch_app_index = 0;
     191             : 
     192             :   // Finalize to/from transfers
     193        1176 :   for (auto transfer : to_transfers)
     194         588 :     transfer->finalizeToMultiapp();
     195        1176 :   for (auto transfer : from_transfers)
     196         588 :     transfer->finalizeFromMultiapp();
     197             : 
     198         588 :   return last_solve_converged;
     199         588 : }
     200             : 
     201             : std::vector<std::shared_ptr<StochasticToolsTransfer>>
     202        1176 : SamplerTransientMultiApp::getActiveStochasticToolsTransfers(Transfer::DIRECTION direction)
     203             : {
     204             :   std::vector<std::shared_ptr<StochasticToolsTransfer>> output;
     205             :   const ExecuteMooseObjectWarehouse<Transfer> & warehouse =
     206        1176 :       _fe_problem.getMultiAppTransferWarehouse(direction);
     207        2416 :   for (std::shared_ptr<Transfer> transfer : warehouse.getActiveObjects())
     208             :   {
     209             :     std::shared_ptr<StochasticToolsTransfer> ptr =
     210        1240 :         std::dynamic_pointer_cast<StochasticToolsTransfer>(transfer);
     211        2416 :     if (ptr && ptr->getMultiApp().get() == this)
     212        1176 :       output.push_back(ptr);
     213             :   }
     214        1176 :   return output;
     215           0 : }
     216             : 
     217             : std::vector<std::string>
     218         456 : 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         456 :   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         396 :     updateRowData(_mode == StochasticTools::MultiAppMode::NORMAL ? local_app
     228             :                                                                  : _local_batch_app_index);
     229         396 :     args = SamplerFullSolveMultiApp::sampledCommandLineArgs(
     230         792 :         _row_data, TransientMultiApp::getCommandLineArgs(local_app));
     231             :   }
     232             : 
     233         456 :   _my_communicator.broadcast(args);
     234         456 :   return args;
     235           0 : }
     236             : 
     237             : void
     238        2096 : SamplerTransientMultiApp::updateRowData(dof_id_type local_index)
     239             : {
     240        2096 :   if (!isRootProcessor())
     241             :     return;
     242             : 
     243             :   mooseAssert(local_index < _sampler.getNumberOfLocalRows(),
     244             :               "Local index must be less than number of local rows.");
     245             : 
     246        1916 :   if (_row_data.empty() ||
     247        1632 :       (_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         632 :     _local_row_index = 0;
     252        1264 :     _row_data = _sampler.getNextLocalRow();
     253             :   }
     254        1284 :   else if (local_index - _local_row_index == 1)
     255             :   {
     256        1268 :     _local_row_index++;
     257        2536 :     _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