LCOV - code coverage report
Current view: top level - src/transfers - MultiAppPostprocessorTransfer.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33416 (b10b36) with base 9fbd27 Lines: 100 117 85.5 %
Date: 2026-07-23 16:15:30 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        5853 : MultiAppPostprocessorTransfer::validParams()
      25             : {
      26        5853 :   InputParameters params = MultiAppTransfer::validParams();
      27       11706 :   params.addClassDescription(
      28             :       "Transfers postprocessor data between the master application and sub-application(s).");
      29       23412 :   params.addRequiredParam<PostprocessorName>(
      30             :       "from_postprocessor",
      31             :       "The name of the Postprocessor in the Master to transfer the value from.");
      32       23412 :   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       23412 :   MooseEnum reduction_type("average sum maximum minimum");
      37       17559 :   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        5853 :   MultiAppTransfer::addUserObjectExecutionCheckParam(params);
      42             : 
      43       11706 :   return params;
      44        5853 : }
      45             : 
      46        1382 : MultiAppPostprocessorTransfer::MultiAppPostprocessorTransfer(const InputParameters & parameters)
      47             :   : MultiAppTransfer(parameters),
      48        1382 :     _from_pp_name(getParam<PostprocessorName>("from_postprocessor")),
      49        2764 :     _to_pp_name(getParam<PostprocessorName>("to_postprocessor")),
      50        4146 :     _reduction_type(getParam<MooseEnum>("reduction_type"))
      51             : {
      52        1382 :   if (_directions.size() != 1)
      53           0 :     paramError("direction", "This transfer is only unidirectional");
      54             : 
      55        7622 :   if (isParamValid("from_multi_app") && !isParamValid("to_multi_app") &&
      56        3428 :       !isParamValid("reduction_type"))
      57           0 :     paramError("reduction_type",
      58             :                "In MultiAppPostprocessorTransfer, must specify 'reduction_type' if "
      59             :                "'from_multi_app' is set");
      60             : 
      61        7604 :   if (isParamValid("to_multi_app") && !isParamValid("from_multi_app") &&
      62        3410 :       isParamValid("reduction_type"))
      63           0 :     paramError("reduction_type", "Reduction is not supported for transfer from parent application");
      64             : 
      65        6952 :   if (isParamValid("to_multi_app") && isParamValid("from_multi_app") &&
      66        1454 :       isParamValid("reduction_type"))
      67           0 :     paramError("reduction_type", "Reductions are not supported for multiapp sibling transfers");
      68        1382 : }
      69             : 
      70             : void
      71       53834 : MultiAppPostprocessorTransfer::execute()
      72             : {
      73      269170 :   TIME_SECTION("MultiAppPostprocessorTransfer::execute()", 5, "Transferring a postprocessor");
      74             : 
      75             :   // Execute the postprocessor if it was specified to execute on TRANSFER
      76       53834 :   switch (_current_direction)
      77             :   {
      78       27178 :     case TO_MULTIAPP:
      79             :     {
      80       27178 :       checkParentAppUserObjectExecuteOn(_from_pp_name);
      81       27178 :       _fe_problem.computeUserObjectByName(EXEC_TRANSFER, Moose::PRE_AUX, _from_pp_name);
      82       27178 :       _fe_problem.computeUserObjectByName(EXEC_TRANSFER, Moose::POST_AUX, _from_pp_name);
      83       27178 :       break;
      84             :     }
      85       26656 :     case FROM_MULTIAPP:
      86             :     case BETWEEN_MULTIAPP:
      87       26656 :       errorIfObjectExecutesOnTransferInSourceApp(_from_pp_name);
      88             :   }
      89             : 
      90       53834 :   switch (_current_direction)
      91             :   {
      92         112 :     case BETWEEN_MULTIAPP:
      93         336 :       for (unsigned int i = 0; i < getFromMultiApp()->numGlobalApps(); i++)
      94             :       {
      95             :         // Get source postprocessor value
      96         224 :         Real pp_value = std::numeric_limits<Real>::max();
      97         224 :         if (getFromMultiApp()->hasLocalApp(i))
      98             :         {
      99         164 :           FEProblemBase & from_problem = getFromMultiApp()->appProblemBase(i);
     100         164 :           pp_value = from_problem.getPostprocessorValueByName(_from_pp_name);
     101             :         }
     102             : 
     103             :         // Find the postprocessor value from another process
     104         224 :         if (getFromMultiApp()->numGlobalApps() == 1)
     105           0 :           _communicator.min(pp_value);
     106             :         else
     107             :           mooseAssert(pp_value != std::numeric_limits<Real>::max() ||
     108             :                           !getToMultiApp()->hasLocalApp(i),
     109             :                       "Source and target app parallel distribution must be the same");
     110             : 
     111             :         // Case 1: a single source app, multiple target apps
     112             :         // All target apps must be local
     113         224 :         if (getFromMultiApp()->numGlobalApps() == 1)
     114           0 :           for (const auto j : make_range(getToMultiApp()->numGlobalApps()))
     115             :           {
     116           0 :             if (getToMultiApp()->hasLocalApp(j))
     117           0 :               getToMultiApp()->appProblemBase(j).setPostprocessorValueByName(_to_pp_name, pp_value);
     118             :           }
     119             : 
     120             :         // Case 2: same number of source and target apps
     121             :         // The allocation of the child apps on the processors must be the same
     122         224 :         else if (getToMultiApp()->hasLocalApp(i))
     123         164 :           getToMultiApp()->appProblemBase(i).setPostprocessorValueByName(_to_pp_name, pp_value);
     124             :       }
     125         112 :       break;
     126       27178 :     case TO_MULTIAPP:
     127             :     {
     128       27178 :       FEProblemBase & from_problem = getToMultiApp()->problemBase();
     129             : 
     130       27178 :       const Real & pp_value = from_problem.getPostprocessorValueByName(_from_pp_name);
     131             : 
     132       54412 :       for (unsigned int i = 0; i < getToMultiApp()->numGlobalApps(); i++)
     133       27234 :         if (getToMultiApp()->hasLocalApp(i))
     134       27204 :           getToMultiApp()->appProblemBase(i).setPostprocessorValueByName(_to_pp_name, pp_value);
     135       27178 :       break;
     136             :     }
     137       26544 :     case FROM_MULTIAPP:
     138             :     {
     139       26544 :       FEProblemBase & to_problem = getFromMultiApp()->problemBase();
     140             : 
     141             :       Real reduced_pp_value;
     142       26544 :       switch (_reduction_type)
     143             :       {
     144       26496 :         case AVERAGE:
     145             :         case SUM:
     146       26496 :           reduced_pp_value = 0;
     147       26496 :           break;
     148          24 :         case MAXIMUM:
     149          24 :           reduced_pp_value = -std::numeric_limits<Real>::max();
     150          24 :           break;
     151          24 :         case MINIMUM:
     152          24 :           reduced_pp_value = std::numeric_limits<Real>::max();
     153          24 :           break;
     154           0 :         default:
     155           0 :           mooseError(
     156             :               "Can't get here unless someone adds a new enum and fails to add it to this switch");
     157             :       }
     158             : 
     159       26544 :       const auto multi_app = hasFromMultiApp() ? getFromMultiApp() : getToMultiApp();
     160             : 
     161       53136 :       for (unsigned int i = 0; i < multi_app->numGlobalApps(); i++)
     162             :       {
     163       26592 :         if (multi_app->hasLocalApp(i) && multi_app->isRootProcessor())
     164             :         {
     165             :           const Real & curr_pp_value =
     166       19182 :               multi_app->appProblemBase(i).getPostprocessorValueByName(_from_pp_name);
     167       19182 :           switch (_reduction_type)
     168             :           {
     169       19128 :             case AVERAGE:
     170             :             case SUM:
     171       19128 :               reduced_pp_value += curr_pp_value;
     172       19128 :               break;
     173          27 :             case MAXIMUM:
     174          27 :               reduced_pp_value = std::max(curr_pp_value, reduced_pp_value);
     175          27 :               break;
     176          27 :             case MINIMUM:
     177          27 :               reduced_pp_value = std::min(curr_pp_value, reduced_pp_value);
     178          27 :               break;
     179           0 :             default:
     180           0 :               mooseError("Can't get here unless someone adds a new enum and fails to add it to "
     181             :                          "this switch");
     182             :           }
     183             :         }
     184             :       }
     185             : 
     186       26544 :       switch (_reduction_type)
     187             :       {
     188       25416 :         case AVERAGE:
     189       25416 :           _communicator.sum(reduced_pp_value);
     190       25416 :           reduced_pp_value /= static_cast<Real>(multi_app->numGlobalApps());
     191       25416 :           break;
     192        1080 :         case SUM:
     193        1080 :           _communicator.sum(reduced_pp_value);
     194        1080 :           break;
     195          24 :         case MAXIMUM:
     196          24 :           _communicator.max(reduced_pp_value);
     197          24 :           break;
     198          24 :         case MINIMUM:
     199          24 :           _communicator.min(reduced_pp_value);
     200          24 :           break;
     201           0 :         default:
     202           0 :           mooseError(
     203             :               "Can't get here unless someone adds a new enum and fails to add it to this switch");
     204             :       }
     205             : 
     206       26544 :       to_problem.setPostprocessorValueByName(_to_pp_name, reduced_pp_value);
     207       26544 :       break;
     208       26544 :     }
     209             :   }
     210       53834 : }
     211             : 
     212             : void
     213          24 : MultiAppPostprocessorTransfer::checkSiblingsTransferSupported() const
     214             : {
     215             :   // Check that we are in one of the supported configurations
     216             :   // Case 2: same number of source and target apps
     217             :   // The allocation of the child apps on the processors must be the same
     218          24 :   if (getFromMultiApp()->numGlobalApps() == getToMultiApp()->numGlobalApps())
     219             :   {
     220          72 :     for (const auto i : make_range(getToMultiApp()->numGlobalApps()))
     221          48 :       if (getFromMultiApp()->hasLocalApp(i) + getToMultiApp()->hasLocalApp(i) == 1)
     222           0 :         mooseError("Child application allocation on parallel processes must be the same to support "
     223             :                    "siblings postprocessor transfer");
     224             :   }
     225             :   // Unsupported, we dont know how to choose a postprocessor value
     226             :   // We could default to 'any' value is good enough in the future, but it would not be reproducible
     227             :   // in parallel. Also every process will not necessarily have a 'source' value
     228           0 :   else if (getFromMultiApp()->numGlobalApps() != 1)
     229           0 :     mooseError("Number of source and target child apps must either match or only a single source "
     230             :                "app may be used");
     231          24 : }

Generated by: LCOV version 1.14