LCOV - code coverage report
Current view: top level - src/transfers - MultiAppReporterTransfer.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 131 141 92.9 %
Date: 2025-08-08 20:01:16 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             : #include "MooseError.h"
      11             : #include "MultiAppReporterTransfer.h"
      12             : #include "MultiApp.h"
      13             : 
      14             : registerMooseObject("MooseApp", MultiAppReporterTransfer);
      15             : 
      16             : InputParameters
      17       14995 : MultiAppReporterTransfer::validParams()
      18             : {
      19       14995 :   InputParameters params = MultiAppTransfer::validParams();
      20       14995 :   params += ReporterTransferInterface::validParams();
      21       14995 :   params.addClassDescription("Transfers reporter data between two applications.");
      22       14995 :   params.addRequiredParam<std::vector<ReporterName>>(
      23             :       "from_reporters",
      24             :       "List of the reporter names (object_name/value_name) to transfer the value from.");
      25       14995 :   params.addRequiredParam<std::vector<ReporterName>>(
      26             :       "to_reporters",
      27             :       "List of the reporter names (object_name/value_name) to transfer the value to.");
      28       44985 :   params.addParam<unsigned int>(
      29             :       "subapp_index",
      30       29990 :       std::numeric_limits<unsigned int>::max(),
      31             :       "The MultiApp object sub-application index to use when transferring to/from the "
      32             :       "sub-application. If unset and transferring to the sub-applications then all "
      33             :       "sub-applications will receive data. The value must be set when transferring from a "
      34             :       "sub-application.");
      35       44985 :   params.addParam<bool>(
      36             :       "distribute_reporter_vector",
      37       29990 :       false,
      38             :       "Transfer to/from a vector reporter from/to reporters on child applications. N "
      39             :       "to 1 or 1 to N type of transfer. The number of child applications must "
      40             :       "match the size of the vector reporter");
      41       14995 :   return params;
      42           0 : }
      43             : 
      44         337 : MultiAppReporterTransfer::MultiAppReporterTransfer(const InputParameters & parameters)
      45             :   : MultiAppTransfer(parameters),
      46             :     ReporterTransferInterface(this),
      47         337 :     _from_reporter_names(getParam<std::vector<ReporterName>>("from_reporters")),
      48         337 :     _to_reporter_names(getParam<std::vector<ReporterName>>("to_reporters")),
      49         337 :     _subapp_index(getParam<unsigned int>("subapp_index")),
      50         674 :     _distribute_reporter_vector(getParam<bool>("distribute_reporter_vector"))
      51             : {
      52         337 :   if (_from_reporter_names.size() != _to_reporter_names.size())
      53           0 :     paramError("to_reporters", "from_reporters and to_reporters must be the same size.");
      54             : 
      55         337 :   if (_directions.size() > 1)
      56           0 :     paramError("direction", "This transfer only supports a single direction.");
      57             : 
      58         363 :   if (isParamValid("to_multi_app") && isParamValid("from_multi_app") &&
      59          26 :       _subapp_index != std::numeric_limits<unsigned int>::max())
      60           0 :     paramError("subapp_index",
      61             :                "The subapp_index parameter is not supported for transfers between two multiapps");
      62             : 
      63         337 :   if (hasFromMultiApp())
      64             :   {
      65         175 :     const auto multi_app = getFromMultiApp();
      66             :     // Errors for sub app index.
      67         277 :     if (_subapp_index != std::numeric_limits<unsigned int>::max() &&
      68         102 :         _subapp_index >= multi_app->numGlobalApps())
      69           4 :       paramError(
      70             :           "subapp_index",
      71             :           "The supplied sub-application index is greater than the number of sub-applications.");
      72         316 :     else if (_directions.isValueSet(FROM_MULTIAPP) &&
      73         192 :              _subapp_index == std::numeric_limits<unsigned int>::max() &&
      74         363 :              multi_app->numGlobalApps() > 1 && !_distribute_reporter_vector)
      75           4 :       paramError("from_multi_app",
      76             :                  "subapp_index must be provided when more than one subapp is present.");
      77         167 :   }
      78         162 :   else if (hasToMultiApp())
      79             :   {
      80             :     // Errors for sub app index.
      81         247 :     if (_subapp_index != std::numeric_limits<unsigned int>::max() &&
      82         247 :         _subapp_index >= getToMultiApp()->numGlobalApps())
      83           4 :       paramError(
      84             :           "subapp_index",
      85             :           "The supplied sub-application index is greater than the number of sub-applications.");
      86             :   }
      87         325 : }
      88             : 
      89             : void
      90         281 : MultiAppReporterTransfer::initialSetup()
      91             : {
      92         281 :   MultiAppTransfer::initialSetup();
      93             : 
      94             :   // We need to get a reference to the data now so we can tell ReporterData
      95             :   // that we consume a replicated version.
      96             :   // Find proper FEProblem
      97         281 :   FEProblemBase * problem_ptr = nullptr;
      98         281 :   if (_directions.isValueSet(TO_MULTIAPP))
      99         134 :     problem_ptr = &getToMultiApp()->problemBase();
     100         216 :   else if (_subapp_index == std::numeric_limits<unsigned int>::max() &&
     101         216 :            getFromMultiApp()->hasLocalApp(0))
     102          54 :     problem_ptr = &getFromMultiApp()->appProblemBase(0);
     103          93 :   else if (getFromMultiApp()->hasLocalApp(_subapp_index))
     104          60 :     problem_ptr = &getFromMultiApp()->appProblemBase(_subapp_index);
     105             : 
     106             :   // Tell ReporterData to consume with replicated
     107         281 :   if (problem_ptr && !_distribute_reporter_vector)
     108         421 :     for (const auto & fn : _from_reporter_names)
     109         250 :       addReporterTransferMode(fn, REPORTER_MODE_REPLICATED, *problem_ptr);
     110             : 
     111             :   // Check that we have the correct reporter modes setup.
     112         281 :   if (_distribute_reporter_vector)
     113             :   {
     114          86 :     if (hasFromMultiApp())
     115          43 :       setVectorReporterTransferModes(getFromMultiApp(), _to_reporter_names, _from_reporter_names);
     116          43 :     else if (hasToMultiApp())
     117          43 :       setVectorReporterTransferModes(getToMultiApp(), _from_reporter_names, _to_reporter_names);
     118             :   }
     119         281 : }
     120             : 
     121             : void
     122        1126 : MultiAppReporterTransfer::executeToMultiapp()
     123             : {
     124        1126 :   if (!hasToMultiApp())
     125           0 :     return;
     126             : 
     127        1126 :   std::vector<unsigned int> indices;
     128        1126 :   if (_subapp_index == std::numeric_limits<unsigned int>::max())
     129             :   {
     130        1066 :     indices.resize(getToMultiApp()->numGlobalApps());
     131        1066 :     std::iota(indices.begin(), indices.end(), 0);
     132             :   }
     133             :   else
     134          60 :     indices = {_subapp_index};
     135             : 
     136        3390 :   for (const auto & ind : indices)
     137        6201 :     if (getToMultiApp()->hasLocalApp(ind) &&
     138        3937 :         (!hasFromMultiApp() || getFromMultiApp()->hasLocalApp(ind)))
     139        4983 :       for (unsigned int n = 0; n < _from_reporter_names.size(); ++n)
     140             :       {
     141        3310 :         if (_distribute_reporter_vector)
     142         432 :           transferFromVectorReporter(_from_reporter_names[n],
     143         216 :                                      _to_reporter_names[n],
     144         432 :                                      getToMultiApp()->problemBase(),
     145         216 :                                      getToMultiApp()->appProblemBase(ind),
     146         216 :                                      ind);
     147             :         else
     148        9282 :           transferReporter(_from_reporter_names[n],
     149        3094 :                            _to_reporter_names[n],
     150        9030 :                            hasFromMultiApp() ? getFromMultiApp()->appProblemBase(ind)
     151        3220 :                                              : getToMultiApp()->problemBase(),
     152        6188 :                            getToMultiApp()->appProblemBase(ind));
     153             :       }
     154        1126 : }
     155             : 
     156             : void
     157         108 : MultiAppReporterTransfer::executeFromMultiapp()
     158             : {
     159         108 :   if (!hasFromMultiApp())
     160           0 :     return;
     161             : 
     162             :   // subapp indices to perform transfers on
     163         108 :   std::vector<unsigned int> indices;
     164         108 :   if (_distribute_reporter_vector)
     165             :   {
     166             :     // If distributing, resize the indices vector to the number of global apps
     167          36 :     indices.resize(getFromMultiApp()->numGlobalApps());
     168          36 :     std::iota(indices.begin(), indices.end(), 0);
     169             :   }
     170          72 :   else if (_subapp_index == std::numeric_limits<unsigned int>::max())
     171             :   {
     172             :     // if _subapp_index not set indices is set to 0
     173           0 :     indices = {0};
     174             :   }
     175             :   else
     176             :     // set indices to specific _subapp_index
     177          72 :     indices = {_subapp_index};
     178             : 
     179         108 :   if (_distribute_reporter_vector)
     180         108 :     for (const auto n : index_range(_to_reporter_names))
     181             :     {
     182             :       // Clear all vector reporters and resize to the number of subapps.
     183             :       // The summing process later will make sure the reporter values are
     184             :       // consistent across the processors.
     185          72 :       auto size = getFromMultiApp()->numGlobalApps();
     186          72 :       clearVectorReporter(_to_reporter_names[n], getFromMultiApp()->problemBase());
     187          72 :       resizeReporter(_to_reporter_names[n], getFromMultiApp()->problemBase(), size);
     188             :     }
     189             : 
     190         324 :   for (const auto ind : indices)
     191         594 :     if (getFromMultiApp()->hasLocalApp(ind) &&
     192         378 :         (!hasToMultiApp() || getToMultiApp()->hasLocalApp(ind)))
     193         450 :       for (const auto n : index_range(_from_reporter_names))
     194             :       {
     195         288 :         if (_distribute_reporter_vector)
     196             :         {
     197         216 :           if (getFromMultiApp()->appProblemBase(ind).processor_id() == 0) // Subapp Root Rank only
     198         432 :             transferToVectorReporter(_from_reporter_names[n],
     199         216 :                                      _to_reporter_names[n],
     200         432 :                                      getFromMultiApp()->appProblemBase(ind),
     201         432 :                                      getFromMultiApp()->problemBase(),
     202             :                                      ind);
     203             :         }
     204             :         else
     205         144 :           transferReporter(_from_reporter_names[n],
     206          72 :                            _to_reporter_names[n],
     207         144 :                            getFromMultiApp()->appProblemBase(ind),
     208         144 :                            hasToMultiApp() ? getToMultiApp()->appProblemBase(ind) // !
     209         144 :                                            : getFromMultiApp()->problemBase());
     210             :       }
     211             : 
     212         108 :   if (_distribute_reporter_vector)
     213         108 :     for (const auto n : index_range(_to_reporter_names))
     214             :     {
     215             :       // Perform summing operation that makes sure all procs have the correct
     216             :       // Reporter values.
     217          72 :       sumVectorReporter(_to_reporter_names[n], getFromMultiApp()->problemBase());
     218             :     }
     219         108 : }
     220             : 
     221             : void
     222        1234 : MultiAppReporterTransfer::execute()
     223             : {
     224        1234 :   TIME_SECTION("MultiAppReporterTransfer::execute()", 5, "Transferring reporters");
     225             : 
     226        1234 :   if (_current_direction == FROM_MULTIAPP)
     227         108 :     executeFromMultiapp();
     228             :   else
     229        1126 :     executeToMultiapp();
     230        1234 : }
     231             : 
     232             : void
     233          26 : MultiAppReporterTransfer::checkSiblingsTransferSupported() const
     234             : {
     235             : 
     236          26 :   if (_distribute_reporter_vector)
     237           0 :     paramError("distribute_reporter_vector",
     238             :                "Distributing reporter vectors is not implemented with sibling transfers.");
     239             : 
     240             :   // Check that we are in the supported configuration: same number of source and target apps
     241             :   // The allocation of the child apps on the processors must be the same
     242          26 :   if (getFromMultiApp()->numGlobalApps() == getToMultiApp()->numGlobalApps())
     243             :   {
     244          78 :     for (const auto i : make_range(getToMultiApp()->numGlobalApps()))
     245          52 :       if (getFromMultiApp()->hasLocalApp(i) + getToMultiApp()->hasLocalApp(i) == 1)
     246           0 :         mooseError("Child application allocation on parallel processes must be the same to support "
     247             :                    "siblings reporter transfer");
     248             :   }
     249             :   else
     250           0 :     mooseError("Number of source and target child apps must match for siblings transfer");
     251          26 : }
     252             : 
     253             : // Helper function to check reporter modes
     254             : void
     255          86 : MultiAppReporterTransfer::setVectorReporterTransferModes(
     256             :     const std::shared_ptr<MultiApp> & main_app,
     257             :     const std::vector<ReporterName> & main_app_rep_names,
     258             :     const std::vector<ReporterName> & sub_app_rep_names)
     259             : {
     260             :   // Set reporter transfer modes for the main app.
     261         250 :   for (const auto & rn : main_app_rep_names)
     262         164 :     addReporterTransferMode(rn, REPORTER_MODE_REPLICATED, main_app->problemBase());
     263             : 
     264          86 :   std::vector<unsigned int> indices(main_app->numGlobalApps());
     265          86 :   std::iota(indices.begin(), indices.end(), 0);
     266             : 
     267             :   // Set reporter transfer modes for sub app.
     268             :   // Setting to ROOT means this works for ROOT and REPLICATED reports with no
     269             :   // change to users.
     270         406 :   for (const auto & ind : indices)
     271         320 :     if (main_app->hasLocalApp(ind))
     272         736 :       for (const auto & rn : sub_app_rep_names)
     273         488 :         addReporterTransferMode(rn, REPORTER_MODE_ROOT, main_app->appProblemBase(ind));
     274          86 : }

Generated by: LCOV version 1.14