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