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