LCOV - code coverage report
Current view: top level - src/transfers - MultiAppReporterTransfer.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 131 141 92.9 %
Date: 2025-07-17 01:28:37 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       14953 : MultiAppReporterTransfer::validParams()
      18             : {
      19       14953 :   InputParameters params = MultiAppTransfer::validParams();
      20       14953 :   params += ReporterTransferInterface::validParams();
      21       14953 :   params.addClassDescription("Transfers reporter data between two applications.");
      22       14953 :   params.addRequiredParam<std::vector<ReporterName>>(
      23             :       "from_reporters",
      24             :       "List of the reporter names (object_name/value_name) to transfer the value from.");
      25       14953 :   params.addRequiredParam<std::vector<ReporterName>>(
      26             :       "to_reporters",
      27             :       "List of the reporter names (object_name/value_name) to transfer the value to.");
      28       44859 :   params.addParam<unsigned int>(
      29             :       "subapp_index",
      30       29906 :       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       44859 :   params.addParam<bool>(
      36             :       "distribute_reporter_vector",
      37       29906 :       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       14953 :   return params;
      42           0 : }
      43             : 
      44         316 : MultiAppReporterTransfer::MultiAppReporterTransfer(const InputParameters & parameters)
      45             :   : MultiAppTransfer(parameters),
      46             :     ReporterTransferInterface(this),
      47         316 :     _from_reporter_names(getParam<std::vector<ReporterName>>("from_reporters")),
      48         316 :     _to_reporter_names(getParam<std::vector<ReporterName>>("to_reporters")),
      49         316 :     _subapp_index(getParam<unsigned int>("subapp_index")),
      50         632 :     _distribute_reporter_vector(getParam<bool>("distribute_reporter_vector"))
      51             : {
      52         316 :   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         316 :   if (_directions.size() > 1)
      56           0 :     paramError("direction", "This transfer only supports a single direction.");
      57             : 
      58         340 :   if (isParamValid("to_multi_app") && isParamValid("from_multi_app") &&
      59          24 :       _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         316 :   if (hasFromMultiApp())
      64             :   {
      65         164 :     const auto multi_app = getFromMultiApp();
      66             :     // Errors for sub app index.
      67         260 :     if (_subapp_index != std::numeric_limits<unsigned int>::max() &&
      68          96 :         _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         296 :     else if (_directions.isValueSet(FROM_MULTIAPP) &&
      73         180 :              _subapp_index == std::numeric_limits<unsigned int>::max() &&
      74         340 :              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         156 :   }
      78         152 :   else if (hasToMultiApp())
      79             :   {
      80             :     // Errors for sub app index.
      81         232 :     if (_subapp_index != std::numeric_limits<unsigned int>::max() &&
      82         232 :         _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         304 : }
      88             : 
      89             : void
      90         260 : MultiAppReporterTransfer::initialSetup()
      91             : {
      92         260 :   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         260 :   FEProblemBase * problem_ptr = nullptr;
      98         260 :   if (_directions.isValueSet(TO_MULTIAPP))
      99         124 :     problem_ptr = &getToMultiApp()->problemBase();
     100         200 :   else if (_subapp_index == std::numeric_limits<unsigned int>::max() &&
     101         200 :            getFromMultiApp()->hasLocalApp(0))
     102          49 :     problem_ptr = &getFromMultiApp()->appProblemBase(0);
     103          87 :   else if (getFromMultiApp()->hasLocalApp(_subapp_index))
     104          54 :     problem_ptr = &getFromMultiApp()->appProblemBase(_subapp_index);
     105             : 
     106             :   // Tell ReporterData to consume with replicated
     107         260 :   if (problem_ptr && !_distribute_reporter_vector)
     108         384 :     for (const auto & fn : _from_reporter_names)
     109         228 :       addReporterTransferMode(fn, REPORTER_MODE_REPLICATED, *problem_ptr);
     110             : 
     111             :   // Check that we have the correct reporter modes setup.
     112         260 :   if (_distribute_reporter_vector)
     113             :   {
     114          80 :     if (hasFromMultiApp())
     115          40 :       setVectorReporterTransferModes(getFromMultiApp(), _to_reporter_names, _from_reporter_names);
     116          40 :     else if (hasToMultiApp())
     117          40 :       setVectorReporterTransferModes(getToMultiApp(), _from_reporter_names, _to_reporter_names);
     118             :   }
     119         260 : }
     120             : 
     121             : void
     122        1010 : MultiAppReporterTransfer::executeToMultiapp()
     123             : {
     124        1010 :   if (!hasToMultiApp())
     125           0 :     return;
     126             : 
     127        1010 :   std::vector<unsigned int> indices;
     128        1010 :   if (_subapp_index == std::numeric_limits<unsigned int>::max())
     129             :   {
     130         955 :     indices.resize(getToMultiApp()->numGlobalApps());
     131         955 :     std::iota(indices.begin(), indices.end(), 0);
     132             :   }
     133             :   else
     134          55 :     indices = {_subapp_index};
     135             : 
     136        3041 :   for (const auto & ind : indices)
     137        5502 :     if (getToMultiApp()->hasLocalApp(ind) &&
     138        3471 :         (!hasFromMultiApp() || getFromMultiApp()->hasLocalApp(ind)))
     139        4288 :       for (unsigned int n = 0; n < _from_reporter_names.size(); ++n)
     140             :       {
     141        2848 :         if (_distribute_reporter_vector)
     142         384 :           transferFromVectorReporter(_from_reporter_names[n],
     143         192 :                                      _to_reporter_names[n],
     144         384 :                                      getToMultiApp()->problemBase(),
     145         192 :                                      getToMultiApp()->appProblemBase(ind),
     146         192 :                                      ind);
     147             :         else
     148        7968 :           transferReporter(_from_reporter_names[n],
     149        2656 :                            _to_reporter_names[n],
     150        7744 :                            hasFromMultiApp() ? getFromMultiApp()->appProblemBase(ind)
     151        2768 :                                              : getToMultiApp()->problemBase(),
     152        5312 :                            getToMultiApp()->appProblemBase(ind));
     153             :       }
     154        1010 : }
     155             : 
     156             : void
     157          99 : MultiAppReporterTransfer::executeFromMultiapp()
     158             : {
     159          99 :   if (!hasFromMultiApp())
     160           0 :     return;
     161             : 
     162             :   // subapp indices to perform transfers on
     163          99 :   std::vector<unsigned int> indices;
     164          99 :   if (_distribute_reporter_vector)
     165             :   {
     166             :     // If distributing, resize the indices vector to the number of global apps
     167          33 :     indices.resize(getFromMultiApp()->numGlobalApps());
     168          33 :     std::iota(indices.begin(), indices.end(), 0);
     169             :   }
     170          66 :   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          66 :     indices = {_subapp_index};
     178             : 
     179          99 :   if (_distribute_reporter_vector)
     180          99 :     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          66 :       auto size = getFromMultiApp()->numGlobalApps();
     186          66 :       clearVectorReporter(_to_reporter_names[n], getFromMultiApp()->problemBase());
     187          66 :       resizeReporter(_to_reporter_names[n], getFromMultiApp()->problemBase(), size);
     188             :     }
     189             : 
     190         297 :   for (const auto ind : indices)
     191         540 :     if (getFromMultiApp()->hasLocalApp(ind) &&
     192         342 :         (!hasToMultiApp() || getToMultiApp()->hasLocalApp(ind)))
     193         400 :       for (const auto n : index_range(_from_reporter_names))
     194             :       {
     195         256 :         if (_distribute_reporter_vector)
     196             :         {
     197         192 :           if (getFromMultiApp()->appProblemBase(ind).processor_id() == 0) // Subapp Root Rank only
     198         384 :             transferToVectorReporter(_from_reporter_names[n],
     199         192 :                                      _to_reporter_names[n],
     200         384 :                                      getFromMultiApp()->appProblemBase(ind),
     201         384 :                                      getFromMultiApp()->problemBase(),
     202             :                                      ind);
     203             :         }
     204             :         else
     205         128 :           transferReporter(_from_reporter_names[n],
     206          64 :                            _to_reporter_names[n],
     207         128 :                            getFromMultiApp()->appProblemBase(ind),
     208         128 :                            hasToMultiApp() ? getToMultiApp()->appProblemBase(ind) // !
     209         128 :                                            : getFromMultiApp()->problemBase());
     210             :       }
     211             : 
     212          99 :   if (_distribute_reporter_vector)
     213          99 :     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          66 :       sumVectorReporter(_to_reporter_names[n], getFromMultiApp()->problemBase());
     218             :     }
     219          99 : }
     220             : 
     221             : void
     222        1109 : MultiAppReporterTransfer::execute()
     223             : {
     224        1109 :   TIME_SECTION("MultiAppReporterTransfer::execute()", 5, "Transferring reporters");
     225             : 
     226        1109 :   if (_current_direction == FROM_MULTIAPP)
     227          99 :     executeFromMultiapp();
     228             :   else
     229        1010 :     executeToMultiapp();
     230        1109 : }
     231             : 
     232             : void
     233          24 : MultiAppReporterTransfer::checkSiblingsTransferSupported() const
     234             : {
     235             : 
     236          24 :   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          24 :   if (getFromMultiApp()->numGlobalApps() == getToMultiApp()->numGlobalApps())
     243             :   {
     244          72 :     for (const auto i : make_range(getToMultiApp()->numGlobalApps()))
     245          48 :       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          24 : }
     252             : 
     253             : // Helper function to check reporter modes
     254             : void
     255          80 : 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         232 :   for (const auto & rn : main_app_rep_names)
     262         152 :     addReporterTransferMode(rn, REPORTER_MODE_REPLICATED, main_app->problemBase());
     263             : 
     264          80 :   std::vector<unsigned int> indices(main_app->numGlobalApps());
     265          80 :   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         376 :   for (const auto & ind : indices)
     271         296 :     if (main_app->hasLocalApp(ind))
     272         664 :       for (const auto & rn : sub_app_rep_names)
     273         440 :         addReporterTransferMode(rn, REPORTER_MODE_ROOT, main_app->appProblemBase(ind));
     274          80 : }

Generated by: LCOV version 1.14