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 "SCMSolutionTransfer.h" 11 : #include "MultiApp.h" 12 : #include "FEProblemBase.h" 13 : #include "DisplacedProblem.h" 14 : #include "SubChannelMesh.h" 15 : 16 : registerMooseObject("SubChannelApp", SCMSolutionTransfer); 17 : registerMooseObjectRenamed("SubChannelApp", 18 : SolutionTransfer, 19 : "06/30/2027 24:00", 20 : SCMSolutionTransfer); 21 : registerMooseObjectRenamed("SubChannelApp", 22 : SCMPinSolutionTransfer, 23 : "06/30/2027 24:00", 24 : SCMSolutionTransfer); 25 : registerMooseObjectRenamed("SubChannelApp", 26 : PinSolutionTransfer, 27 : "06/30/2027 24:00", 28 : SCMSolutionTransfer); 29 : 30 : InputParameters 31 250 : SCMSolutionTransfer::validParams() 32 : { 33 250 : InputParameters params = MultiAppTransfer::validParams(); 34 500 : params.addRequiredParam<std::vector<AuxVariableName>>("variable", 35 : "The auxiliary variables to transfer."); 36 500 : MooseEnum transfer_type("subchannel pin", "subchannel"); 37 500 : params.addParam<MooseEnum>("transfer_type", 38 : transfer_type, 39 : "Whether to transfer subchannel-centered or pin-centered fields."); 40 250 : params.addClassDescription( 41 : "Transfers subchannel or pin solutions from a SubChannel mesh onto a visualization mesh."); 42 250 : return params; 43 250 : } 44 : 45 125 : SCMSolutionTransfer::SCMSolutionTransfer(const InputParameters & parameters) 46 : : MultiAppTransfer(parameters), 47 125 : _var_names(getParam<std::vector<AuxVariableName>>("variable")), 48 375 : _pin_transfer(getParam<MooseEnum>("transfer_type") == "pin") 49 : { 50 125 : if (_directions.contains(Transfer::FROM_MULTIAPP)) 51 0 : paramError("from_multiapp", "This transfer works only into multi-app."); 52 125 : } 53 : 54 : void 55 112 : SCMSolutionTransfer::initialSetup() 56 : { 57 112 : MultiAppTransfer::initialSetup(); 58 699 : for (std::size_t var_index = 0; var_index < _var_names.size(); ++var_index) 59 : { 60 587 : if (_to_problems.empty()) 61 16 : continue; 62 : 63 571 : MooseVariableFieldBase & from_var = _subproblem.getVariable( 64 : 0, _var_names[var_index], Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY); 65 : const auto & fe_type = from_var.feType(); 66 : 67 571 : if (fe_type.family != LAGRANGE || fe_type.order != FIRST) 68 0 : paramError("variable", 69 : "This transfer requires a first order Lagrange variable for the source variable"); 70 : 71 571 : MooseVariableFieldBase & to_var = _to_problems[0]->getVariable( 72 571 : 0, _var_names[var_index], Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY); 73 : const auto & fe_type_target = to_var.feType(); 74 : 75 571 : if (fe_type_target.family != LAGRANGE || fe_type_target.order != FIRST) 76 0 : paramError("variable", 77 : "This transfer requires a first order Lagrange variable for the source variable"); 78 : } 79 112 : } 80 : 81 : void 82 234 : SCMSolutionTransfer::execute() 83 : { 84 468 : TIME_SECTION( 85 : "MultiAppDetailedSolutionBaseTransfer::execute()", 5, "Transferring subchannel solutions"); 86 234 : getAppInfo(); 87 : 88 234 : switch (_current_direction) 89 : { 90 234 : case TO_MULTIAPP: 91 : case BETWEEN_MULTIAPP: 92 234 : transferToMultiApps(); 93 : break; 94 : 95 : default: 96 : break; 97 : } 98 234 : } 99 : 100 : void 101 234 : SCMSolutionTransfer::transferToMultiApps() 102 : { 103 : mooseAssert(_from_meshes.size() == 1, "Only one source mesh can be active in this transfer."); 104 234 : auto * from_mesh = dynamic_cast<SubChannelMesh *>(_from_meshes[0]); 105 234 : if (from_mesh == nullptr) 106 0 : mooseError("This transfer works only with SubChannelMesh classes."); 107 234 : if (_pin_transfer && !from_mesh->pinMeshExist()) 108 0 : mooseError( 109 : "This transfer was configured for pin variables, but the source mesh has no pin mesh."); 110 : 111 936 : for (unsigned int i = 0; i < getToMultiApp()->numGlobalApps(); i++) 112 468 : if (getToMultiApp()->hasLocalApp(i)) 113 226 : transferVarsToApp(i); 114 234 : } 115 : 116 : void 117 226 : SCMSolutionTransfer::transferVarsToApp(unsigned int app_idx) 118 : { 119 226 : transferNodalVars(app_idx); 120 226 : } 121 : 122 : void 123 226 : SCMSolutionTransfer::transferNodalVars(unsigned int app_idx) 124 : { 125 226 : Moose::ScopedCommSwapper swapper(getToMultiApp()->comm()); 126 : 127 226 : FEProblemBase & to_problem = getToMultiApp()->appProblemBase(app_idx); 128 : MooseMesh * mesh = NULL; 129 226 : if (_displaced_target_mesh && to_problem.getDisplacedProblem()) 130 0 : mesh = &to_problem.getDisplacedProblem()->mesh(); 131 : else 132 226 : mesh = &to_problem.mesh(); 133 : 134 226 : const SubChannelMesh & from_mesh = dynamic_cast<SubChannelMesh &>(*_from_meshes[0]); 135 226 : FEProblemBase & from_problem = *_from_problems[0]; 136 : 137 7755284 : for (auto & node : mesh->getMesh().local_node_ptr_range()) 138 : { 139 3877416 : if (processor_id() != 0) 140 881254 : continue; 141 2996162 : Node * from_node = getFromNode(from_mesh, *node); 142 : 143 19022473 : for (auto & var_name : _var_names) 144 : { 145 16026311 : System * to_sys = find_sys(to_problem.es(), var_name); 146 : unsigned int to_sys_num = to_sys->number(); 147 16026311 : unsigned int to_var_num = to_sys->variable_number(var_name); 148 : 149 16026311 : if (node->n_dofs(to_sys_num, to_var_num) > 0) 150 : { 151 13744207 : System * from_sys = find_sys(from_problem.es(), var_name); 152 : unsigned int from_sys_num = from_sys->number(); 153 13744207 : unsigned int from_var_num = from_sys->variable_number(var_name); 154 : 155 : // Return to parent app MPI communicator to get solution dof 156 : swapper.forceSwap(); 157 : NumericVector<Real> * from_solution = from_sys->solution.get(); 158 13744207 : dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0); 159 13744207 : Real from_value = (*from_solution)(from_dof); 160 : swapper.forceSwap(); 161 : 162 27488414 : NumericVector<Real> & to_solution = getToMultiApp()->appTransferVector(app_idx, var_name); 163 13744207 : dof_id_type to_dof = node->dof_number(to_sys_num, to_var_num, 0); 164 13744207 : to_solution.set(to_dof, from_value); 165 : } 166 : } 167 226 : } 168 : 169 1397 : for (auto & var_name : _var_names) 170 : { 171 2342 : getToMultiApp()->appTransferVector(app_idx, var_name).close(); 172 1171 : find_sys(to_problem.es(), var_name)->update(); 173 : } 174 226 : } 175 : 176 : Node * 177 2996162 : SCMSolutionTransfer::getFromNode(const SubChannelMesh & from_mesh, const Point & src_node) 178 : { 179 : unsigned int sch_idx = 180 2996162 : _pin_transfer ? from_mesh.pinIndex(src_node) : from_mesh.channelIndex(src_node); 181 2996162 : unsigned iz = from_mesh.getZIndex(src_node); 182 2996162 : return _pin_transfer ? from_mesh.getPinNode(sch_idx, iz) : from_mesh.getChannelNode(sch_idx, iz); 183 : }