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