LCOV - code coverage report
Current view: top level - src/multiapps - PODFullSolveMultiApp.C (source / functions) Hit Total Coverage
Test: idaholab/moose stochastic_tools: f45d79 Lines: 41 92 44.6 %
Date: 2025-07-25 05:00:46 Functions: 5 8 62.5 %
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 "PODFullSolveMultiApp.h"
      12             : #include "NonlinearSystemBase.h"
      13             : #include "Sampler.h"
      14             : #include "Executioner.h"
      15             : #include "PODSamplerSolutionTransfer.h"
      16             : #include "PODResidualTransfer.h"
      17             : 
      18             : registerMooseObject("StochasticToolsApp", PODFullSolveMultiApp);
      19             : 
      20             : InputParameters
      21         208 : PODFullSolveMultiApp::validParams()
      22             : {
      23         208 :   InputParameters params = SamplerFullSolveMultiApp::validParams();
      24         208 :   params.addClassDescription(
      25             :       "Creates a full-solve type sub-application for each row of a Sampler matrix. "
      26             :       "On second call, this object creates residuals for a PODReducedBasisTrainer with given basis "
      27             :       "functions.");
      28         416 :   params.addRequiredParam<UserObjectName>(
      29             :       "trainer_name", "Trainer object that contains the solutions for different samples.");
      30             : 
      31         208 :   return params;
      32           0 : }
      33             : 
      34         100 : PODFullSolveMultiApp::PODFullSolveMultiApp(const InputParameters & parameters)
      35             :   : SamplerFullSolveMultiApp(parameters),
      36             :     SurrogateModelInterface(this),
      37         100 :     _trainer(getSurrogateTrainer<PODReducedBasisTrainer>("trainer_name")),
      38         100 :     _snapshot_generation(true)
      39             : {
      40         192 :   if (getParam<unsigned int>("max_procs_per_app") != 1)
      41           4 :     paramError("max_procs_per_app", " does not support more than one processors per subapp!");
      42             : 
      43          92 :   if (n_processors() > _sampler.getNumberOfRows())
      44           0 :     mooseError(type(),
      45             :                " needs to be run with fewer processors (detected ",
      46           0 :                n_processors(),
      47             :                ") than samples (detected ",
      48           0 :                _sampler.getNumberOfRows(),
      49             :                ")!");
      50          92 : }
      51             : 
      52             : void
      53         168 : PODFullSolveMultiApp::preTransfer(Real dt, Real target_time)
      54             : {
      55             :   // Reinitialize the problem only if the snapshot generation part is done.
      56         168 :   if (!_snapshot_generation)
      57             :   {
      58          84 :     dof_id_type base_size = _trainer.getSumBaseSize();
      59          84 :     if (base_size < 1)
      60           4 :       mooseError(
      61             :           "There are no basis vectors available for residual generation."
      62             :           " This indicates that the bases have not been created yet."
      63             :           " The most common cause of this error is the wrong setting"
      64             :           " of the 'execute_on' flags in the PODFullSolveMultiApp and/or PODReducedBasisTrainer.");
      65             : 
      66          80 :     init(base_size,
      67          80 :          _sampler.getRankConfig(_mode == StochasticTools::MultiAppMode::BATCH_RESET ||
      68             :                                 _mode == StochasticTools::MultiAppMode::BATCH_RESTORE));
      69             : 
      70          80 :     initialSetup();
      71             :   }
      72         164 :   SamplerFullSolveMultiApp::preTransfer(dt, target_time);
      73         164 : }
      74             : 
      75             : bool
      76         164 : PODFullSolveMultiApp::solveStep(Real dt, Real target_time, bool auto_advance)
      77             : {
      78             : 
      79             :   bool last_solve_converged = true;
      80             : 
      81             :   // If snapshot generation phase, solve the subapplications in a regular manner.
      82             :   // Otherwise, compute the residuals only.
      83         164 :   if (_snapshot_generation)
      84             :   {
      85          84 :     last_solve_converged = SamplerFullSolveMultiApp::solveStep(dt, target_time, auto_advance);
      86          84 :     _snapshot_generation = false;
      87             :   }
      88             :   else
      89             :   {
      90          80 :     if (_mode == StochasticTools::MultiAppMode::BATCH_RESET ||
      91             :         _mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
      92           0 :       computeResidualBatch(target_time);
      93             :     else
      94          80 :       computeResidual();
      95             :   }
      96             : 
      97         164 :   return last_solve_converged;
      98             : }
      99             : 
     100             : void
     101          80 : PODFullSolveMultiApp::computeResidual()
     102             : {
     103             :   // Doing the regular computation but instead of solving the subapplication,
     104             :   // the residuals for different tags are evaluated.
     105          80 :   if (!_has_an_app)
     106           0 :     return;
     107             : 
     108          80 :   Moose::ScopedCommSwapper swapper(_my_comm);
     109             : 
     110             :   int rank;
     111             :   int ierr;
     112          80 :   ierr = MPI_Comm_rank(_communicator.get(), &rank);
     113          80 :   mooseCheckMPIErr(ierr);
     114             : 
     115             :   // Getting the necessary tag names.
     116          80 :   const std::vector<std::string> & trainer_tags = _trainer.getTagNames();
     117             : 
     118             :   // Looping over the subapplications and computing residuals.
     119         240 :   for (unsigned int i = 0; i < _my_num_apps; i++)
     120             :   {
     121             :     // Getting the local problem
     122         160 :     FEProblemBase & problem = _apps[i]->getExecutioner()->feProblem();
     123             : 
     124             :     // Extracting the TagIDs based on tag names from the current subapp.
     125             :     std::set<TagID> tags_to_compute;
     126         900 :     for (auto & tag_name : trainer_tags)
     127        1480 :       tags_to_compute.insert(problem.getVectorTagID(tag_name));
     128             : 
     129         160 :     problem.setCurrentNonlinearSystem(0);
     130         160 :     problem.computeResidualTags(tags_to_compute);
     131             :   }
     132             : }
     133             : 
     134             : void
     135           0 : PODFullSolveMultiApp::computeResidualBatch(Real target_time)
     136             : {
     137             :   // Getting the overall base size from the trainer.
     138           0 :   dof_id_type base_size = _trainer.getSumBaseSize();
     139             : 
     140             :   // Distributing the residual evaluation among processes.
     141             :   dof_id_type local_base_begin;
     142             :   dof_id_type local_base_end;
     143             :   dof_id_type n_local_bases;
     144           0 :   MooseUtils::linearPartitionItems(
     145             :       base_size, n_processors(), processor_id(), n_local_bases, local_base_begin, local_base_end);
     146             : 
     147             :   // List of active relevant Transfer objects
     148             :   std::vector<std::shared_ptr<PODSamplerSolutionTransfer>> to_transfers =
     149           0 :       getActiveSolutionTransfers(MultiAppTransfer::TO_MULTIAPP);
     150             :   std::vector<std::shared_ptr<PODResidualTransfer>> from_transfers =
     151           0 :       getActiveResidualTransfers(MultiAppTransfer::FROM_MULTIAPP);
     152             : 
     153             :   // Initialize to/from transfers
     154           0 :   for (auto transfer : to_transfers)
     155           0 :     transfer->initializeToMultiapp();
     156             : 
     157           0 :   for (auto transfer : from_transfers)
     158           0 :     transfer->initializeFromMultiapp();
     159             : 
     160           0 :   if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
     161           0 :     backup();
     162             : 
     163             :   // Perform batch MultiApp solves
     164           0 :   _local_batch_app_index = 0;
     165           0 :   for (dof_id_type i = local_base_begin; i < local_base_end; ++i)
     166             :   {
     167           0 :     for (auto & transfer : to_transfers)
     168             :     {
     169             :       transfer->setGlobalMultiAppIndex(i);
     170           0 :       transfer->executeToMultiapp();
     171             :     }
     172             : 
     173           0 :     computeResidual();
     174             : 
     175           0 :     for (auto & transfer : from_transfers)
     176             :     {
     177             :       transfer->setGlobalMultiAppIndex(i);
     178           0 :       transfer->executeFromMultiapp();
     179             :     }
     180             : 
     181           0 :     if (i < _sampler.getLocalRowEnd() - 1)
     182             :     {
     183           0 :       if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
     184           0 :         restore();
     185             :       else
     186             :       {
     187             :         // The app is being reset for the next loop, thus the batch index must be indexed as such
     188           0 :         _local_batch_app_index++;
     189           0 :         resetApp(_local_batch_app_index + i, target_time);
     190           0 :         initialSetup();
     191             :       }
     192             :     }
     193             :   }
     194             : 
     195             :   // Finalize to/from transfers
     196           0 :   for (auto transfer : to_transfers)
     197           0 :     transfer->finalizeToMultiapp();
     198           0 :   for (auto transfer : from_transfers)
     199           0 :     transfer->finalizeFromMultiapp();
     200           0 : }
     201             : 
     202             : std::vector<std::shared_ptr<PODSamplerSolutionTransfer>>
     203           0 : PODFullSolveMultiApp::getActiveSolutionTransfers(Transfer::DIRECTION direction)
     204             : {
     205             :   std::vector<std::shared_ptr<PODSamplerSolutionTransfer>> output;
     206             :   const ExecuteMooseObjectWarehouse<Transfer> & warehouse =
     207           0 :       _fe_problem.getMultiAppTransferWarehouse(direction);
     208           0 :   for (std::shared_ptr<Transfer> transfer : warehouse.getActiveObjects())
     209             :   {
     210           0 :     auto ptr = std::dynamic_pointer_cast<PODSamplerSolutionTransfer>(transfer);
     211           0 :     if (ptr)
     212           0 :       output.push_back(ptr);
     213             :   }
     214           0 :   return output;
     215           0 : }
     216             : 
     217             : std::vector<std::shared_ptr<PODResidualTransfer>>
     218           0 : PODFullSolveMultiApp::getActiveResidualTransfers(Transfer::DIRECTION direction)
     219             : {
     220             :   std::vector<std::shared_ptr<PODResidualTransfer>> output;
     221             :   const ExecuteMooseObjectWarehouse<Transfer> & warehouse =
     222           0 :       _fe_problem.getMultiAppTransferWarehouse(direction);
     223           0 :   for (std::shared_ptr<Transfer> transfer : warehouse.getActiveObjects())
     224             :   {
     225           0 :     auto ptr = std::dynamic_pointer_cast<PODResidualTransfer>(transfer);
     226           0 :     if (ptr)
     227           0 :       output.push_back(ptr);
     228             :   }
     229           0 :   return output;
     230           0 : }

Generated by: LCOV version 1.14