https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SCMSolutionTransfer.C
Go to the documentation of this file.
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
16namespace
17{
18bool
19isDeprecatedPinTransferType(const InputParameters & parameters)
20{
21 const auto & type = parameters.getObjectType();
22 return type == "SCMPinSolutionTransfer" || type == "PinSolutionTransfer";
23}
24}
25
28 SolutionTransfer,
29 "06/30/2027 24:00",
32 SCMPinSolutionTransfer,
33 "06/30/2027 24:00",
36 PinSolutionTransfer,
37 "06/30/2027 24:00",
39
42{
44 params.addRequiredParam<std::vector<AuxVariableName>>("variable",
45 "The auxiliary variables to transfer.");
46 MooseEnum transfer_type("subchannel pin", "subchannel");
47 params.addParam<MooseEnum>("transfer_type",
48 transfer_type,
49 "Whether to transfer subchannel-centered or pin-centered fields.");
51 "Transfers subchannel or pin solutions from a SubChannel mesh onto a visualization mesh.");
52 return params;
53}
54
56 : MultiAppTransfer(parameters),
57 _var_names(getParam<std::vector<AuxVariableName>>("variable")),
58 _pin_transfer(
59 getParam<MooseEnum>("transfer_type") == "pin" ||
60 (!parameters.isParamSetByUser("transfer_type") && isDeprecatedPinTransferType(parameters)))
61{
63 paramError("from_multiapp", "This transfer works only into multi-app.");
64}
65
66void
68{
70 for (std::size_t var_index = 0; var_index < _var_names.size(); ++var_index)
71 {
72 if (_to_problems.empty())
73 continue;
74
76 0, _var_names[var_index], Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
77 const auto & fe_type = from_var.feType();
78
79 if (fe_type.family != LAGRANGE || fe_type.order != FIRST)
80 paramError("variable",
81 "This transfer requires a first order Lagrange variable for the source variable");
82
83 MooseVariableFieldBase & to_var = _to_problems[0]->getVariable(
84 0, _var_names[var_index], Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
85 const auto & fe_type_target = to_var.feType();
86
87 if (fe_type_target.family != LAGRANGE || fe_type_target.order != FIRST)
88 paramError("variable",
89 "This transfer requires a first order Lagrange variable for the source variable");
90 }
91}
92
93void
95{
96 TIME_SECTION(
97 "MultiAppDetailedSolutionBaseTransfer::execute()", 5, "Transferring subchannel solutions");
98 getAppInfo();
99
100 switch (_current_direction)
101 {
102 case TO_MULTIAPP:
103 case BETWEEN_MULTIAPP:
105 break;
106
107 default:
108 break;
109 }
110}
111
112void
114{
115 mooseAssert(_from_meshes.size() == 1, "Only one source mesh can be active in this transfer.");
116 auto * from_mesh = dynamic_cast<SubChannelMesh *>(_from_meshes[0]);
117 if (from_mesh == nullptr)
118 mooseError("This transfer works only with SubChannelMesh classes.");
119 if (_pin_transfer && !from_mesh->pinMeshExist())
121 "This transfer was configured for pin variables, but the source mesh has no pin mesh.");
122
123 for (unsigned int i = 0; i < getToMultiApp()->numGlobalApps(); i++)
124 if (getToMultiApp()->hasLocalApp(i))
126}
127
128void
130{
131 transferNodalVars(app_idx);
132}
133
134void
136{
138
139 FEProblemBase & to_problem = getToMultiApp()->appProblemBase(app_idx);
140 MooseMesh * mesh = NULL;
142 mesh = &to_problem.getDisplacedProblem()->mesh();
143 else
144 mesh = &to_problem.mesh();
145
146 const SubChannelMesh & from_mesh = dynamic_cast<SubChannelMesh &>(*_from_meshes[0]);
147 FEProblemBase & from_problem = *_from_problems[0];
148 validateVariableLocations(from_mesh, to_problem);
149
150 for (auto & node : mesh->getMesh().local_node_ptr_range())
151 {
152 if (processor_id() != 0)
153 continue;
154 Node * from_node = getFromNode(from_mesh, *node);
155
156 for (auto & var_name : _var_names)
157 {
158 System * to_sys = find_sys(to_problem.es(), var_name);
159 unsigned int to_sys_num = to_sys->number();
160 unsigned int to_var_num = to_sys->variable_number(var_name);
161
162 if (node->n_dofs(to_sys_num, to_var_num) > 0)
163 {
164 System * from_sys = find_sys(from_problem.es(), var_name);
165 unsigned int from_sys_num = from_sys->number();
166 unsigned int from_var_num = from_sys->variable_number(var_name);
167
168 // Return to parent app MPI communicator to get solution dof
169 swapper.forceSwap();
170 NumericVector<Real> * from_solution = from_sys->solution.get();
171 dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0);
172 Real from_value = (*from_solution)(from_dof);
173 swapper.forceSwap();
174
175 NumericVector<Real> & to_solution = getToMultiApp()->appTransferVector(app_idx, var_name);
176 dof_id_type to_dof = node->dof_number(to_sys_num, to_var_num, 0);
177 to_solution.set(to_dof, from_value);
178 }
179 }
180 }
181
182 for (auto & var_name : _var_names)
183 {
184 getToMultiApp()->appTransferVector(app_idx, var_name).close();
185 find_sys(to_problem.es(), var_name)->update();
186 }
187}
188
189void
191 FEProblemBase & to_problem)
192{
193 if (processor_id() != 0)
194 return;
195
196 Node * from_node = _pin_transfer ? from_mesh.getPinNode(0, 0) : from_mesh.getChannelNode(0, 0);
197 mooseAssert(from_node, "The representative source node must be non-null.");
198
199 FEProblemBase & from_problem = *_from_problems[0];
200 const auto transfer_type = _pin_transfer ? "pin" : "subchannel";
201 const auto other_transfer_type = _pin_transfer ? "subchannel" : "pin";
202 const auto expected_block = _pin_transfer ? "fuel_pins" : "subchannel";
203 const auto source_block_id = from_mesh.getSubdomainID(expected_block);
204 const auto target_block_id = to_problem.mesh().getSubdomainID(expected_block);
205
206 for (const auto & var_name : _var_names)
207 {
208 MooseVariableFieldBase & from_var = from_problem.getVariable(
209 0, var_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
210 MooseVariableFieldBase & to_var = to_problem.getVariable(
211 0, var_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
212 System * from_sys = find_sys(from_problem.es(), var_name);
213 const auto from_sys_num = from_sys->number();
214 const auto from_var_num = from_sys->variable_number(var_name);
215
216 if (!from_var.activeOnSubdomain(source_block_id) ||
217 !to_var.activeOnSubdomain(target_block_id) ||
218 from_node->n_dofs(from_sys_num, from_var_num) == 0)
219 paramError("variable",
220 "The variable '",
221 var_name,
222 "' does not have DOFs on ",
223 transfer_type,
224 " nodes. Use a separate SCMSolutionTransfer with transfer_type = '",
225 other_transfer_type,
226 "' for variables centered on ",
227 other_transfer_type,
228 " nodes.");
229 }
230}
231
232Node *
233SCMSolutionTransfer::getFromNode(const SubChannelMesh & from_mesh, const Point & src_node)
234{
235 unsigned int sch_idx =
236 _pin_transfer ? from_mesh.pinIndex(src_node) : from_mesh.channelIndex(src_node);
237 unsigned iz = from_mesh.getZIndex(src_node);
238 return _pin_transfer ? from_mesh.getPinNode(sch_idx, iz) : from_mesh.getChannelNode(sch_idx, iz);
239}
registerMooseObjectRenamed("SubChannelApp", SolutionTransfer, "06/30/2027 24:00", SCMSolutionTransfer)
registerMooseObject("SubChannelApp", SCMSolutionTransfer)
virtual libMesh::EquationSystems & es() override
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
virtual MooseMesh & mesh() override
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const std::string & getObjectType() const
void addClassDescription(const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
SubdomainID getSubdomainID(const SubdomainName &subdomain_name) const
const libMesh::FEType & feType() const
bool activeOnSubdomain(SubdomainID subdomain) const
void initialSetup() override
std::vector< MooseMesh * > _from_meshes
std::vector< FEProblemBase * > _from_problems
virtual void getAppInfo()
bool _displaced_target_mesh
std::vector< FEProblemBase * > _to_problems
const std::shared_ptr< MultiApp > getToMultiApp() const
static InputParameters validParams()
bool contains(const std::string &value) const
Transfers subchannel and pin solutions from a SubChannel mesh onto a visualization mesh.
const bool _pin_transfer
Whether pin fields should be transferred instead of subchannel fields.
virtual void execute() override
void transferVarsToApp(unsigned int app_idx)
Node * getFromNode(const SubChannelMesh &from_mesh, const Point &src_node)
void transferNodalVars(unsigned int app_idx)
const std::vector< AuxVariableName > & _var_names
Variable names to transfer.
SCMSolutionTransfer(const InputParameters &parameters)
static InputParameters validParams()
void validateVariableLocations(const SubChannelMesh &from_mesh, FEProblemBase &to_problem)
void initialSetup() override
Base class for subchannel meshes.
virtual unsigned int channelIndex(const Point &point) const =0
virtual unsigned int pinIndex(const Point &p) const =0
virtual unsigned int getZIndex(const Point &point) const
Get axial index of point.
virtual Node * getChannelNode(unsigned int i_chan, unsigned int iz) const =0
Get the subchannel mesh node for a given channel index and elevation index.
virtual Node * getPinNode(unsigned int i_pin, unsigned int iz) const =0
Get the pin mesh node for a given pin index and elevation index.
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const=0
MultiMooseEnum _directions
MooseEnum _current_direction
SubProblem & _subproblem
static libMesh::System * find_sys(libMesh::EquationSystems &es, const std::string &var_name)
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
virtual void update()
MeshBase & mesh