https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SCMMixingKimAndChung.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
13#include "TriSubChannelMesh.h"
14#include "QuadSubChannelMesh.h"
15
17
20{
23 "Class that models the turbulent mixing coefficient using the Kim and Chung correlations.");
24 return params;
25}
26
28 : SCMMixingClosureBase(parameters),
29 _is_tri_lattice(dynamic_cast<const TriSubChannelMesh *>(&_subchannel_mesh) != nullptr),
30 _sch_mesh(_subchannel_mesh),
31 _S_soln(_subproblem.getVariable(0, "S")),
32 _mdot_soln(_subproblem.getVariable(0, "mdot")),
33 _w_perim_soln(_subproblem.getVariable(0, "w_perim")),
34 _mu_soln(_subproblem.getVariable(0, "mu")),
35 _P_soln(_subproblem.getVariable(0, "P")),
36 _T_soln(_subproblem.getVariable(0, "T"))
37{
39 {
40 const auto & tri_mesh = cast_ref<const TriSubChannelMesh &>(_subchannel_mesh);
41 if (tri_mesh.getWireDiameter() != 0.0 || tri_mesh.getWireLeadLength() != 0.0)
42 mooseError("SCMMixingKimAndChung applies only to bare-pin assemblies and cannot be used "
43 "with wire-wrapped triangular bundles.");
44 }
45}
46
47Real
48SCMMixingKimAndChung::computeMixingParameter(const unsigned int i_gap, const unsigned int iz) const
49{
51 return computeTriLatticeMixingParameter(i_gap, iz);
52 else
53 return computeQuadLatticeMixingParameter(i_gap, iz);
54}
55
60Real
62 const unsigned int iz,
63 const Real delta,
64 const Real sf) const
65{
66 const Real P_out = _scm_problem.getOutletPressure();
68 const Real pin_diameter = _sch_mesh.getPinDiameter();
69
70 const auto chans = _sch_mesh.getGapChannels(i_gap);
71 const unsigned int i_ch = chans.first;
72 const unsigned int j_ch = chans.second;
73
74 const Node * const node_in_i = _sch_mesh.getChannelNode(i_ch, iz - 1);
75 const Node * const node_out_i = _sch_mesh.getChannelNode(i_ch, iz);
76 const Node * const node_in_j = _sch_mesh.getChannelNode(j_ch, iz - 1);
77 const Node * const node_out_j = _sch_mesh.getChannelNode(j_ch, iz);
78
79 const Real Si_in = _S_soln(node_in_i);
80 const Real Sj_in = _S_soln(node_in_j);
81 const Real Si_out = _S_soln(node_out_i);
82 const Real Sj_out = _S_soln(node_out_j);
83
84 const Real Si = 0.5 * (Si_in + Si_out);
85 const Real Sj = 0.5 * (Sj_in + Sj_out);
86 const Real S_total = Si_in + Sj_in + Si_out + Sj_out;
87
88 // crossflow area between channels i,j (dz*gap_width)
89 const Real gap = _sch_mesh.getGapWidth(iz, i_gap);
90
91 const Real massflux_i = 0.5 * (_mdot_soln(node_in_i) + _mdot_soln(node_out_i)) / Si;
92 const Real massflux_j = 0.5 * (_mdot_soln(node_in_j) + _mdot_soln(node_out_j)) / Sj;
93
94 // average massflux definition
95 const Real avg_massflux =
96 0.5 * ((_mdot_soln(node_in_i) + _mdot_soln(node_in_j)) / (Si_in + Sj_in) +
97 (_mdot_soln(node_out_i) + _mdot_soln(node_out_j)) / (Si_out + Sj_out));
98
99 const Real w_perim_i = 0.5 * (_w_perim_soln(node_in_i) + _w_perim_soln(node_out_i));
100 const Real w_perim_j = 0.5 * (_w_perim_soln(node_in_j) + _w_perim_soln(node_out_j));
101
102 const Real mu_i = 0.5 * (_mu_soln(node_in_i) + _mu_soln(node_out_i));
103 const Real mu_j = 0.5 * (_mu_soln(node_in_j) + _mu_soln(node_out_j));
104 const Real avg_mu = 0.5 * (mu_i + mu_j);
105
106 const Real avg_hD = 4.0 * (Si + Sj) / (w_perim_i + w_perim_j);
107 const Real hD_i = 4.0 * Si / w_perim_i;
108 const Real hD_j = 4.0 * Sj / w_perim_j;
109
110 const Real Re_i = massflux_i * hD_i / mu_i;
111 const Real Re_j = massflux_j * hD_j / mu_j;
112 const Real Re = avg_massflux * avg_hD / avg_mu;
113
114 constexpr Real gamma = 20.0; // empirical constant
115 constexpr Real a = 0.18;
116 constexpr Real b = 0.2;
117
118 const auto friction_args_i = FrictionStruct(i_ch, Re_i, Si, w_perim_i);
119 const auto friction_args_j = FrictionStruct(j_ch, Re_j, Sj, w_perim_j);
120
121 const Real fi = _scm_problem.getFrictionClosure()->computeFrictionFactor(friction_args_i);
122 const Real fj = _scm_problem.getFrictionClosure()->computeFrictionFactor(friction_args_j);
123 const Real f = 0.5 * (fi + fj);
124
125 // average heat conduction
126 const Real avg_k =
127 (1.0 / S_total) * (fp->k_from_p_T(_P_soln(node_out_i) + P_out, _T_soln(node_out_i)) * Si_out +
128 fp->k_from_p_T(_P_soln(node_in_i) + P_out, _T_soln(node_in_i)) * Si_in +
129 fp->k_from_p_T(_P_soln(node_out_j) + P_out, _T_soln(node_out_j)) * Sj_out +
130 fp->k_from_p_T(_P_soln(node_in_j) + P_out, _T_soln(node_in_j)) * Sj_in);
131
132 // average specific heat capacity
133 const Real avg_cp = (1.0 / S_total) *
134 (fp->cp_from_p_T(_P_soln(node_out_i) + P_out, _T_soln(node_out_i)) * Si_out +
135 fp->cp_from_p_T(_P_soln(node_in_i) + P_out, _T_soln(node_in_i)) * Si_in +
136 fp->cp_from_p_T(_P_soln(node_out_j) + P_out, _T_soln(node_out_j)) * Sj_out +
137 fp->cp_from_p_T(_P_soln(node_in_j) + P_out, _T_soln(node_in_j)) * Sj_in);
138
139 const Real Pr = avg_mu * avg_cp / avg_k; // Prandtl number
140 const Real Pr_t = Pr * (Re / gamma) * std::sqrt(f / 8.0); // Turbulent Prandtl number
141
142 // This form is intended for liquid-metal applications; warn when the local average Prandtl
143 // number is outside the usual low-Pr liquid-metal regime.
144 if (Pr >= 0.1)
145 flagSolutionWarning("Prandtl number (Pr) outside the low-Prandtl-number liquid-metal range "
146 "expected by the Kim-Chung turbulent mixing closure.");
147
148 const Real L_x = sf * delta; // axial length scale (gap is the lateral length scale)
149 const Real lamda = gap / L_x; // aspect ratio
150 const Real a_x = 1.0 - 2.0 * lamda * lamda / libMesh::pi; // velocity coefficient
151
152 const Real z_FP_over_D =
153 (2.0 * L_x / pin_diameter) *
154 (1.0 + (-0.5 * std::log(lamda) + 0.5 * std::log(4.0) - 0.25) * lamda * lamda);
155
156 const Real Str =
157 1.0 / (0.822 * (gap / pin_diameter) + 0.144); // Strouhal number (Wu & Trupp 1994)
158
159 const Real freq_factor = 2.0 / Utility::pow<2>(gamma) * std::sqrt(a / 8.0) * (avg_hD / gap);
160
161 const Real rod_mixing = (1.0 / Pr_t) * lamda;
162 const Real axial_mixing = a_x * z_FP_over_D * Str;
163
164 // Mixing Stanton number following Kim and Chung (2001), Eq. 25, as used by
165 // Jeong et al. (2005), Eq. 19:
166 //
167 // St_g = 2/gamma^2 * sqrt(a/8) * (D_h/g)
168 // * [lambda/Pr_t + a_x * (z_FP/D) * Str] * Re^(-b/2).
169 //
170 // The subchannel problem converts St_g to the turbulent interchange flow through
171 // w'_ij = beta * S_ij * G_bar (St_g = beta). This correlation doesn't include the
172 // molecular diffusion term which represents the conductive heat transfer,
173 // which is separately modeled in the subchannel energy equation.
174 return freq_factor * (rod_mixing + axial_mixing) * std::pow(Re, -b / 2.0);
175}
176
177Real
179 const unsigned int iz) const
180{
181 // main differences for tri lattice: delta and sf
182 const Real pitch = _sch_mesh.getPitch();
183 const Real delta = pitch / std::sqrt(3.0); // centroid to centroid distance
184 constexpr Real sf = 2.0 / 3.0; // shape factor
185 return computeLatticeMixingParameter(i_gap, iz, delta, sf);
186}
187
188Real
190 const unsigned int iz) const
191{
192 // main differences for quad lattice: delta and sf
193 const Real pitch = _sch_mesh.getPitch();
194 const Real delta = pitch; // centroid to centroid distance
195 constexpr Real sf = 1.0; // shape factor
196 return computeLatticeMixingParameter(i_gap, iz, delta, sf);
197}
Real f(Real x)
Test function for Brents method.
const double Re
registerMooseObject("SubChannelApp", SCMMixingKimAndChung)
void addClassDescription(const std::string &doc_string)
void mooseError(Args &&... args) const
const SubChannel1PhaseProblem & _scm_problem
Reference to the subchannel problem.
const SubChannelMesh & _subchannel_mesh
Reference to the subchannel mesh.
virtual Real computeFrictionFactor(const FrictionStruct &friction_info) const =0
Computes the friction factor for the local conditions.
Base class for turbulent mixing closures used in SCM.
static InputParameters validParams()
SubChannel1PhaseProblem::FrictionStruct FrictionStruct
Class that calculates the turbulent mixing coefficient based on the Kim and Chung (2001) correllation...
static InputParameters validParams()
bool _is_tri_lattice
Keep track of the lattice type.
Real computeLatticeMixingParameter(const unsigned int i_gap, const unsigned int iz, const Real delta, const Real sf) const
Common implementation for both tri and quad lattices.
Real computeTriLatticeMixingParameter(const unsigned int i_gap, const unsigned int iz) const
virtual Real computeMixingParameter(const unsigned int i_gap, const unsigned int iz) const override
Computes the turbulent mixing coefficient for the local conditions around gap(i_gap) and axial level(...
SCMMixingKimAndChung(const InputParameters &parameters)
Real computeQuadLatticeMixingParameter(const unsigned int i_gap, const unsigned int iz) const
const SubChannelMesh & _sch_mesh
Pointer to the base subchannel mesh.
const PostprocessorValue & getOutletPressure() const
Get outlet pressure.
const SCMFrictionClosureBase * getFrictionClosure() const
const SinglePhaseFluidProperties * getSinglePhaseFluidProperties() const
Get fluid properties object.
virtual Real getGapWidth(unsigned int axial_index, unsigned int gap_index) const =0
Return gap width for a given gap index.
virtual const Real & getPitch() const
Return the undeformed pitch between 2 subchannels.
virtual const std::pair< unsigned int, unsigned int > & getGapChannels(unsigned int i_gap) const =0
Return a pair of subchannel indices for a given gap index.
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 const Real & getPinDiameter() const
Return undeformed Pin diameter.
Mesh class for triangular, edge and corner subchannels for hexagonal lattice fuel assemblies.
const Real pi