LCOV - code coverage report
Current view: top level - src/transfers - MultiAppPostprocessorTransfer.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 96 112 85.7 %
Date: 2025-07-17 01:28:37 Functions: 4 4 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 "MultiAppPostprocessorTransfer.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "MooseTypes.h"
      14             : #include "FEProblem.h"
      15             : #include "MultiApp.h"
      16             : 
      17             : // libMesh
      18             : #include "libmesh/meshfree_interpolation.h"
      19             : #include "libmesh/system.h"
      20             : 
      21             : registerMooseObject("MooseApp", MultiAppPostprocessorTransfer);
      22             : 
      23             : InputParameters
      24       16641 : MultiAppPostprocessorTransfer::validParams()
      25             : {
      26       16641 :   InputParameters params = MultiAppTransfer::validParams();
      27       16641 :   params.addClassDescription(
      28             :       "Transfers postprocessor data between the master application and sub-application(s).");
      29       16641 :   params.addRequiredParam<PostprocessorName>(
      30             :       "from_postprocessor",
      31             :       "The name of the Postprocessor in the Master to transfer the value from.");
      32       16641 :   params.addRequiredParam<PostprocessorName>(
      33             :       "to_postprocessor",
      34             :       "The name of the Postprocessor in the MultiApp to transfer the value to. "
      35             :       " This should most likely be a Reporter Postprocessor.");
      36       16641 :   MooseEnum reduction_type("average sum maximum minimum");
      37       16641 :   params.addParam<MooseEnum>("reduction_type",
      38             :                              reduction_type,
      39             :                              "The type of reduction to perform to reduce postprocessor "
      40             :                              "values from multiple SubApps to a single value");
      41       33282 :   return params;
      42       16641 : }
      43             : 
      44        1188 : MultiAppPostprocessorTransfer::MultiAppPostprocessorTransfer(const InputParameters & parameters)
      45             :   : MultiAppTransfer(parameters),
      46        1188 :     _from_pp_name(getParam<PostprocessorName>("from_postprocessor")),
      47        1188 :     _to_pp_name(getParam<PostprocessorName>("to_postprocessor")),
      48        2376 :     _reduction_type(getParam<MooseEnum>("reduction_type"))
      49             : {
      50        1188 :   if (_directions.size() != 1)
      51           0 :     paramError("direction", "This transfer is only unidirectional");
      52             : 
      53        1188 :   if (_current_direction == FROM_MULTIAPP)
      54         588 :     if (!_reduction_type.isValid())
      55           0 :       mooseError("In MultiAppPostprocessorTransfer, must specify 'reduction_type' if direction = "
      56             :                  "from_multiapp");
      57             : 
      58        2400 :   if (isParamValid("to_multi_app") && isParamValid("from_multi_app") &&
      59        1212 :       isParamValid("reduction_type"))
      60           0 :     mooseError("Reductions are not supported for multiapp sibling transfers");
      61        1188 : }
      62             : 
      63             : void
      64       51080 : MultiAppPostprocessorTransfer::execute()
      65             : {
      66       51080 :   TIME_SECTION("MultiAppPostprocessorTransfer::execute()", 5, "Transferring a postprocessor");
      67             : 
      68             :   // Execute the postprocessor if it was specified to execute on TRANSFER
      69       51080 :   switch (_current_direction)
      70             :   {
      71       24777 :     case TO_MULTIAPP:
      72             :     {
      73       24777 :       _fe_problem.computeUserObjectByName(EXEC_TRANSFER, Moose::PRE_AUX, _from_pp_name);
      74       24777 :       _fe_problem.computeUserObjectByName(EXEC_TRANSFER, Moose::POST_AUX, _from_pp_name);
      75       24777 :       break;
      76             :     }
      77       26303 :     case FROM_MULTIAPP:
      78             :     case BETWEEN_MULTIAPP:
      79       26303 :       errorIfObjectExecutesOnTransferInSourceApp(_from_pp_name);
      80             :   }
      81             : 
      82       51080 :   switch (_current_direction)
      83             :   {
      84        2274 :     case BETWEEN_MULTIAPP:
      85        6822 :       for (unsigned int i = 0; i < getFromMultiApp()->numGlobalApps(); i++)
      86             :       {
      87             :         // Get source postprocessor value
      88        4548 :         Real pp_value = std::numeric_limits<Real>::max();
      89        4548 :         if (getFromMultiApp()->hasLocalApp(i))
      90             :         {
      91        3192 :           FEProblemBase & from_problem = getFromMultiApp()->appProblemBase(i);
      92        3192 :           pp_value = from_problem.getPostprocessorValueByName(_from_pp_name);
      93             :         }
      94             : 
      95             :         // Find the postprocessor value from another process
      96        4548 :         if (getFromMultiApp()->numGlobalApps() == 1)
      97           0 :           _communicator.min(pp_value);
      98             :         else
      99             :           mooseAssert(pp_value != std::numeric_limits<Real>::max() ||
     100             :                           !getToMultiApp()->hasLocalApp(i),
     101             :                       "Source and target app parallel distribution must be the same");
     102             : 
     103             :         // Case 1: a single source app, multiple target apps
     104             :         // All target apps must be local
     105        4548 :         if (getFromMultiApp()->numGlobalApps() == 1)
     106           0 :           for (const auto j : make_range(getToMultiApp()->numGlobalApps()))
     107             :           {
     108           0 :             if (getToMultiApp()->hasLocalApp(j))
     109           0 :               getToMultiApp()->appProblemBase(j).setPostprocessorValueByName(_to_pp_name, pp_value);
     110             :           }
     111             : 
     112             :         // Case 2: same number of source and target apps
     113             :         // The allocation of the child apps on the processors must be the same
     114        4548 :         else if (getToMultiApp()->hasLocalApp(i))
     115        3192 :           getToMultiApp()->appProblemBase(i).setPostprocessorValueByName(_to_pp_name, pp_value);
     116             :       }
     117        2274 :       break;
     118       24777 :     case TO_MULTIAPP:
     119             :     {
     120       24777 :       FEProblemBase & from_problem = getToMultiApp()->problemBase();
     121             : 
     122       24777 :       const Real & pp_value = from_problem.getPostprocessorValueByName(_from_pp_name);
     123             : 
     124       49609 :       for (unsigned int i = 0; i < getToMultiApp()->numGlobalApps(); i++)
     125       24832 :         if (getToMultiApp()->hasLocalApp(i))
     126       24802 :           getToMultiApp()->appProblemBase(i).setPostprocessorValueByName(_to_pp_name, pp_value);
     127       24777 :       break;
     128             :     }
     129       24029 :     case FROM_MULTIAPP:
     130             :     {
     131       24029 :       FEProblemBase & to_problem = getFromMultiApp()->problemBase();
     132             : 
     133             :       Real reduced_pp_value;
     134       24029 :       switch (_reduction_type)
     135             :       {
     136       23985 :         case AVERAGE:
     137             :         case SUM:
     138       23985 :           reduced_pp_value = 0;
     139       23985 :           break;
     140          22 :         case MAXIMUM:
     141          22 :           reduced_pp_value = -std::numeric_limits<Real>::max();
     142          22 :           break;
     143          22 :         case MINIMUM:
     144          22 :           reduced_pp_value = std::numeric_limits<Real>::max();
     145          22 :           break;
     146           0 :         default:
     147           0 :           mooseError(
     148             :               "Can't get here unless someone adds a new enum and fails to add it to this switch");
     149             :       }
     150             : 
     151       24029 :       const auto multi_app = hasFromMultiApp() ? getFromMultiApp() : getToMultiApp();
     152             : 
     153       48102 :       for (unsigned int i = 0; i < multi_app->numGlobalApps(); i++)
     154             :       {
     155       24073 :         if (multi_app->hasLocalApp(i) && multi_app->isRootProcessor())
     156             :         {
     157             :           const Real & curr_pp_value =
     158       17326 :               multi_app->appProblemBase(i).getPostprocessorValueByName(_from_pp_name);
     159       17326 :           switch (_reduction_type)
     160             :           {
     161       17278 :             case AVERAGE:
     162             :             case SUM:
     163       17278 :               reduced_pp_value += curr_pp_value;
     164       17278 :               break;
     165          24 :             case MAXIMUM:
     166          24 :               reduced_pp_value = std::max(curr_pp_value, reduced_pp_value);
     167          24 :               break;
     168          24 :             case MINIMUM:
     169          24 :               reduced_pp_value = std::min(curr_pp_value, reduced_pp_value);
     170          24 :               break;
     171           0 :             default:
     172           0 :               mooseError("Can't get here unless someone adds a new enum and fails to add it to "
     173             :                          "this switch");
     174             :           }
     175             :         }
     176             :       }
     177             : 
     178       24029 :       switch (_reduction_type)
     179             :       {
     180       23787 :         case AVERAGE:
     181       23787 :           _communicator.sum(reduced_pp_value);
     182       23787 :           reduced_pp_value /= static_cast<Real>(multi_app->numGlobalApps());
     183       23787 :           break;
     184         198 :         case SUM:
     185         198 :           _communicator.sum(reduced_pp_value);
     186         198 :           break;
     187          22 :         case MAXIMUM:
     188          22 :           _communicator.max(reduced_pp_value);
     189          22 :           break;
     190          22 :         case MINIMUM:
     191          22 :           _communicator.min(reduced_pp_value);
     192          22 :           break;
     193           0 :         default:
     194           0 :           mooseError(
     195             :               "Can't get here unless someone adds a new enum and fails to add it to this switch");
     196             :       }
     197             : 
     198       24029 :       to_problem.setPostprocessorValueByName(_to_pp_name, reduced_pp_value);
     199       24029 :       break;
     200       24029 :     }
     201             :   }
     202       51080 : }
     203             : 
     204             : void
     205          24 : MultiAppPostprocessorTransfer::checkSiblingsTransferSupported() const
     206             : {
     207             :   // Check that we are in one of the supported configurations
     208             :   // Case 2: same number of source and target apps
     209             :   // The allocation of the child apps on the processors must be the same
     210          24 :   if (getFromMultiApp()->numGlobalApps() == getToMultiApp()->numGlobalApps())
     211             :   {
     212          72 :     for (const auto i : make_range(getToMultiApp()->numGlobalApps()))
     213          48 :       if (getFromMultiApp()->hasLocalApp(i) + getToMultiApp()->hasLocalApp(i) == 1)
     214           0 :         mooseError("Child application allocation on parallel processes must be the same to support "
     215             :                    "siblings postprocessor transfer");
     216             :   }
     217             :   // Unsupported, we dont know how to choose a postprocessor value
     218             :   // We could default to 'any' value is good enough in the future, but it would not be reproducible
     219             :   // in parallel. Also every process will not necessarily have a 'source' value
     220           0 :   else if (getFromMultiApp()->numGlobalApps() != 1)
     221           0 :     mooseError("Number of source and target child apps must either match or only a single source "
     222             :                "app may be used");
     223          24 : }

Generated by: LCOV version 1.14