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