https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SCMFrictionChenTodreas.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
11
14 SCMFrictionUpgradedChengTodreas,
15 "09/30/2027 24:00",
18 SCMFrictionUpdatedChengTodreas,
19 "09/30/2027 24:00",
21
24{
26
28 "Class that computes the axial friction factor using the Chen-Todreas correlations.");
29
30 MooseEnum friction_model("Upgraded Pacio", "Upgraded");
31
32 params.addParam<MooseEnum>(
33 "friction_model",
34 friction_model,
35 "Friction-factor parameterization for triangular wire-wrapped Chen-Todreas correlations.");
36
37 return params;
38}
39
41 : SCMFrictionClosureBase(parameters),
42 _is_tri_lattice(dynamic_cast<const TriSubChannelMesh *>(&_subchannel_mesh) != nullptr),
43 _tri_sch_mesh(dynamic_cast<const TriSubChannelMesh *>(&_subchannel_mesh)),
44 _quad_sch_mesh(dynamic_cast<const QuadSubChannelMesh *>(&_subchannel_mesh)),
45 _has_wire_wrap(_is_tri_lattice && _tri_sch_mesh->getWireDiameter() != 0.0 &&
46 _tri_sch_mesh->getWireLeadLength() != 0.0),
47 _friction_model(getParam<MooseEnum>("friction_model"))
48{
49 if (_is_tri_lattice &&
51 mooseError("Wire-wrapped bundle friction requires both wire diameter and wire lead length. "
52 "Set both to zero for a bare pin bundle.");
53
55 paramError("friction_model",
56 "The Pacio-Chen-Todreas friction correlation applies only to wire-wrapped "
57 "triangular assemblies.");
58
60 {
61 const auto pitch = _subchannel_mesh.getPitch();
62 const auto pin_diameter = _subchannel_mesh.getPinDiameter();
63 const auto p_over_d = pitch / pin_diameter;
64 const auto wire_lead_to_diameter = _tri_sch_mesh->getWireLeadLength() / pin_diameter;
65 const unsigned int Nr = _tri_sch_mesh->getNumOfRings();
66 const unsigned int num_pins = 1 + 3 * Nr * (Nr - 1);
67
68 // Reported ranges of validity from Table 1 of Pacio et al. (2022):
69 // UCTD: 7 <= Npin <= 217, 1.00 <= P/D <= 1.42, 8 <= H/D <= 52, 50 <= Reb <= 1.0e6
70 // PCTD: 19 <= Npin <= 217, 1.02 <= P/D <= 1.42, 7.5 <= H/D <= 54, 10 <= Reb <= 3.0e5
71 if (_friction_model == "Upgraded")
72 {
73 if (p_over_d < 1.0 || p_over_d > 1.42)
74 flagSolutionWarning("Pitch-over-pin diameter ratio (P/D) outside the Upgraded "
75 "Chen-Todreas friction correlation data range.");
76 if (_has_wire_wrap && (wire_lead_to_diameter < 8.0 || wire_lead_to_diameter > 52.0))
77 flagSolutionWarning("Wire lead length-over-pin diameter ratio (H/D) outside the Upgraded "
78 "Chen-Todreas friction correlation data range.");
79 if (num_pins < 7 || num_pins > 217)
80 flagSolutionWarning("Number of pins outside the Upgraded Chen-Todreas friction correlation "
81 "data range.");
82 }
83 else
84 {
85 if (p_over_d < 1.02 || p_over_d > 1.42)
86 flagSolutionWarning("Pitch-over-pin diameter ratio (P/D) outside the "
87 "Pacio-Chen-Todreas friction correlation data range.");
88 if (_has_wire_wrap && (wire_lead_to_diameter < 7.5 || wire_lead_to_diameter > 54.0))
89 flagSolutionWarning("Wire lead length-over-pin diameter ratio (H/D) outside the "
90 "Pacio-Chen-Todreas friction correlation data range.");
91 if (num_pins < 19 || num_pins > 217)
92 flagSolutionWarning("Number of pins outside the Pacio-Chen-Todreas friction correlation "
93 "data range.");
94 }
95 }
96}
97
98Real
100{
101 if (_is_tri_lattice)
102 return computeTriLatticeFrictionFactor(friction_args);
103 else
104 return computeQuadLatticeFrictionFactor(friction_args);
105}
106
107Real
109{
110 const auto Re = friction_args.Re;
111 // Limit the Reynolds number used in the friction-factor correlation to avoid
112 // singular behavior at zero flow.
113 const Real Re_eff = std::max(Re, 1.0);
114 const auto i_ch = friction_args.i_ch;
115 const auto S = friction_args.S;
116 const auto w_perim = friction_args.w_perim;
117 const auto Dh_i = 4.0 * S / w_perim;
118 // Bare fuel Pins coefficients, and friction factor
119 Real k1L, k2L, k3L, CfL;
120 Real k1T, k2T, k3T, CfT;
121 // Transient range parameters
122 Real CbL1, CbL2, CbT1, CbT2;
123 // wire sweep coefficient parameters
124 Real a, b;
125 // wire Drag coefficient parameters
126 Real CwT1, CwT2, CwT3, CwT4;
127 // Ratio of laminar over turbulent drag and sweep coefficients
128 Real CwL1, CwL2;
129 // interpolation exponent
130 Real lambda;
131 // transition smoothing coefficient
132 Real gamma;
133 if (_friction_model == "Upgraded")
134 {
135 CbL1 = 320.0;
136 CbL2 = 1.0;
137 CbT1 = 10000.0;
138 CbT2 = 0.7;
139
140 a = -11.0;
141 b = 19.0;
142
143 CwT1 = 19.56;
144 CwT2 = -98.71;
145 CwT3 = 303.47;
146 CwT4 = -0.541;
147
148 CwL1 = 1.4;
149 CwL2 = 1.0;
150
151 lambda = 7.0;
152 gamma = 1.0 / 3.0;
153 }
154 else
155 {
156 CbL1 = 700.0;
157 CbL2 = 0.0;
158 CbT1 = 10000.0;
159 CbT2 = 0.0;
160
161 a = -6.9;
162 b = 12.0;
163
164 CwT1 = 15.2;
165 CwT2 = -48.0;
166 CwT3 = 148.6;
167 CwT4 = -0.547;
168
169 CwL1 = 0.8;
170 CwL2 = 1.2;
171
172 lambda = 6.7;
173 gamma = 0.362;
174 }
175
176 const Real & pitch = _subchannel_mesh.getPitch();
177 const Real & pin_diameter = _subchannel_mesh.getPinDiameter();
178 const Real & wire_lead_length = _tri_sch_mesh->getWireLeadLength();
179 const Real & wire_diameter = _tri_sch_mesh->getWireDiameter();
180 const auto gap = _tri_sch_mesh->getDuctToPinGap();
181 const auto p_over_d = pitch / pin_diameter;
182 const auto w_over_d = (pin_diameter + gap) / pin_diameter;
183 const auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
184 const auto ReL = std::pow(10, CbL2 * (p_over_d - 1)) * CbL1;
185 const auto ReT = std::pow(10, CbT2 * (p_over_d - 1)) * CbT1;
186 const auto Reb = _scm_problem.getBulkReynoldsNumber();
187 const auto psi = std::log(Reb / ReL) / std::log(ReT / ReL);
188
189 // The bulk Reynolds number is computed from the solution during the solve, so its
190 // applicability range (see constructor) can only be checked here rather than at construction
191 if (_friction_model == "Upgraded")
192 {
193 if (Reb < 50.0 || Reb > 1.0e6)
194 flagSolutionWarning("Bulk Reynolds number (Reb) outside the Upgraded Chen-Todreas friction "
195 "correlation data range.");
196 }
197 else if (Reb < 10.0 || Reb > 3.0e5)
198 flagSolutionWarning("Bulk Reynolds number (Reb) outside the Pacio-Chen-Todreas friction "
199 "correlation data range.");
200
201 // Find the coefficients of bare Pin bundle friction factor
202 // correlations for turbulent and laminar flow regimes. Todreas & Kazimi, Nuclear Systems
203 // second edition, Volume 1, Chapter 9.6
204 if (subch_type == EChannelType::CENTER)
205 {
206 if (p_over_d < 1.1)
207 {
208 k1L = 26.0;
209 k2L = 888.2;
210 k3L = -3334.0;
211 k1T = 0.09378;
212 k2T = 1.398;
213 k3T = -8.664;
214 }
215 else
216 {
217 k1L = 62.97;
218 k2L = 216.9;
219 k3L = -190.2;
220 k1T = 0.1458;
221 k2T = 0.03632;
222 k3T = -0.03333;
223 }
224 // laminar flow friction factor for bare Pin bundle - Center subchannel
225 CfL = k1L + k2L * (p_over_d - 1) + k3L * Utility::pow<2>((p_over_d - 1));
226 // turbulent flow friction factor for bare Pin bundle - Center subchannel
227 CfT = k1T + k2T * (p_over_d - 1) + k3T * Utility::pow<2>((p_over_d - 1));
228 }
229 else if (subch_type == EChannelType::EDGE)
230 {
231 if (w_over_d < 1.1)
232 {
233 k1L = 26.18;
234 k2L = 554.5;
235 k3L = -1480.0;
236 k1T = 0.09377;
237 k2T = 0.8732;
238 k3T = -3.341;
239 }
240 else
241 {
242 k1L = 44.4;
243 k2L = 256.7;
244 k3L = -267.6;
245 k1T = 0.1430;
246 k2T = 0.04199;
247 k3T = -0.04428;
248 }
249 // laminar flow friction factor for bare Pin bundle - Edge subchannel
250 CfL = k1L + k2L * (w_over_d - 1) + k3L * Utility::pow<2>((w_over_d - 1));
251 // turbulent flow friction factor for bare Pin bundle - Edge subchannel
252 CfT = k1T + k2T * (w_over_d - 1) + k3T * Utility::pow<2>((w_over_d - 1));
253 }
254 else
255 {
256 if (w_over_d < 1.1)
257 {
258 k1L = 26.98;
259 k2L = 1636.0;
260 k3L = -10050.0;
261 k1T = 0.1004;
262 k2T = 1.625;
263 k3T = -11.85;
264 }
265 else
266 {
267 k1L = 87.26;
268 k2L = 38.59;
269 k3L = -55.12;
270 k1T = 0.1499;
271 k2T = 0.006706;
272 k3T = -0.009567;
273 }
274 // laminar flow friction factor for bare Pin bundle - Corner subchannel
275 CfL = k1L + k2L * (w_over_d - 1) + k3L * Utility::pow<2>((w_over_d - 1));
276 // turbulent flow friction factor for bare Pin bundle - Corner subchannel
277 CfT = k1T + k2T * (w_over_d - 1) + k3T * Utility::pow<2>((w_over_d - 1));
278 }
279
280 // Find the coefficients of wire-wrapped Pin bundle friction factor
281 // correlations for turbulent and laminar flow regimes. Todreas & Kazimi, Nuclear Systems
282 // Volume 1 Chapter 9-6 also Chen and Todreas (2018).
283 if (_has_wire_wrap)
284 {
285 const auto theta =
286 std::acos(wire_lead_length /
287 std::sqrt(Utility::pow<2>(wire_lead_length) +
288 Utility::pow<2>(libMesh::pi * (pin_diameter + wire_diameter))));
289 // Drag coefficient
290 const auto WdT = (CwT1 + CwT2 * (wire_diameter / pin_diameter) +
291 CwT3 * Utility::pow<2>((wire_diameter / pin_diameter))) *
292 std::pow((wire_lead_length / pin_diameter), CwT4);
293 const auto WdL = CwL1 * WdT;
294 // Sweep coefficient
295 const auto WsT = a * std::log10(wire_lead_length / pin_diameter) + b;
296 const auto WsL = CwL2 * WsT;
297 Real ar = 0.0;
298 Real a_p = 0.0;
299
300 if (subch_type == EChannelType::CENTER)
301 {
302 // wetted perimeter for center subchannel and bare Pin bundle
303 const Real pw_p = libMesh::pi * pin_diameter / 2.0;
304 // wire projected area - center subchannel wire-wrapped bundle
305 ar = libMesh::pi * (pin_diameter + wire_diameter) * wire_diameter / 6.0;
306 // bare Pin bundle center subchannel flow area (normal area + wire area)
307 a_p = S + libMesh::pi * Utility::pow<2>(wire_diameter) / 8.0 / std::cos(theta);
308 // turbulent friction factor equation constant - Center subchannel
309 CfT *= (pw_p / w_perim);
310 CfT += WdT * (3.0 * ar / a_p) * (Dh_i / wire_lead_length) *
311 std::pow((Dh_i / wire_diameter), 0.18);
312 // laminar friction factor equation constant - Center subchannel
313 CfL *= (pw_p / w_perim);
314 CfL += WdL * (3.0 * ar / a_p) * (Dh_i / wire_lead_length) * (Dh_i / wire_diameter);
315 }
316 else if (subch_type == EChannelType::EDGE)
317 {
318 // wire projected area - edge subchannel wire-wrapped bundle
319 ar = libMesh::pi * (pin_diameter + wire_diameter) * wire_diameter / 4.0;
320 // bare Pin bundle edge subchannel flow area (normal area + wire area)
321 a_p = S + libMesh::pi * Utility::pow<2>(wire_diameter) / 8.0 / std::cos(theta);
322 // turbulent friction factor equation constant - Edge subchannel
323 const Real turbulent_wire_correction =
324 1 + WsT * (ar / a_p) * Utility::pow<2>(std::tan(theta));
325 if (!std::isfinite(turbulent_wire_correction) || turbulent_wire_correction < 0.0)
326 mooseError("The exponentiated term in the Chen-Todreas turbulent wire correction must be "
327 "non-negative and finite for an edge subchannel. Computed ",
328 turbulent_wire_correction,
329 ".");
330 CfT *= std::pow(turbulent_wire_correction, 1.41);
331 // laminar friction factor equation constant - Edge subchannel
332 CfL *= (1 + WsL * (ar / a_p) * Utility::pow<2>(std::tan(theta)));
333 }
334 else
335 {
336 // wire projected area - corner subchannel wire-wrapped bundle
337 ar = libMesh::pi * (pin_diameter + wire_diameter) * wire_diameter / 6.0;
338 // bare Pin bundle corner subchannel flow area (normal area + wire area)
339 a_p = S + libMesh::pi * Utility::pow<2>(wire_diameter) / 24.0 / std::cos(theta);
340 // turbulent friction factor equation constant - Corner subchannel
341 const Real turbulent_wire_correction =
342 1 + WsT * (ar / a_p) * Utility::pow<2>(std::tan(theta));
343 if (!std::isfinite(turbulent_wire_correction) || turbulent_wire_correction < 0.0)
344 mooseError("The exponentiated term in the Chen-Todreas turbulent wire correction must be "
345 "non-negative and finite for a corner subchannel. Computed ",
346 turbulent_wire_correction,
347 ".");
348 CfT *= std::pow(turbulent_wire_correction, 1.41);
349 // laminar friction factor equation constant - Corner subchannel
350 CfL *= (1 + WsL * (ar / a_p) * Utility::pow<2>(std::tan(theta)));
351 }
352 }
353 // laminar friction factor and turbulent friction factor coefficients
354 const Real mL = -1.0;
355 const Real mT = -0.18;
356 auto fL = CfL * std::pow(Re_eff, mL);
357 auto fT = CfT * std::pow(Re_eff, mT);
358 if (Reb < ReL)
359 {
360 // laminar flow
361 return fL;
362 }
363 else if (Reb > ReT)
364 {
365 // turbulent flow
366 return fT;
367 }
368 else
369 {
370 // Transition regime is selected by bulk Reynolds number, same for all channels.
371 // fL and fT are evaluated at the local Reynolds number of the subchannel, as Eq. (35) of
372 // Pacio et al. (2022) is written. The example calculation of that paper, Section 6.1.3,
373 // evaluates fL with the laminar and fT with the turbulent flow split of the subchannel type
374 // instead, which gives a different transition flow split.
375 return fL * std::pow((1 - psi), gamma) * (1 - std::pow(psi, lambda)) +
376 fT * std::pow(psi, gamma);
377 }
378}
379
380Real
382{
383 const auto Re = friction_args.Re;
384 // Limit the Reynolds number used in the friction-factor correlation to avoid
385 // singular behavior k1T zero flow.
386 const Real Re_eff = std::max(Re, 1.0);
387 const auto i_ch = friction_args.i_ch;
389 Real k1L, k2L, k3L, CfL;
390 Real k1T, k2T, k3T, CfT;
391 const auto pitch = _subchannel_mesh.getPitch();
392 const auto pin_diameter = _subchannel_mesh.getPinDiameter();
393 // This gap is a constant value for the whole assembly. Might want to make it
394 // subchannel specific in the future if we have duct deformation.
395 const auto side_gap = _quad_sch_mesh->getSideGap();
396 const auto w = (pin_diameter / 2.0) + (pitch / 2.0) + side_gap;
397 const auto p_over_d = pitch / pin_diameter;
398 const auto w_over_d = w / pin_diameter;
399 const auto ReL = std::pow(10, (p_over_d - 1)) * 320.0;
400 const auto ReT = std::pow(10, 0.7 * (p_over_d - 1)) * 1.0E+4;
401 const auto Reb = _scm_problem.getBulkReynoldsNumber();
402 const auto psi = std::log(Reb / ReL) / std::log(ReT / ReL);
403 const auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
404 // interpolation exponent
405 Real lambda;
406 // transition smoothing coefficient
407 Real gamma;
408
409 // Find the coefficients of bare Pin bundle friction factor
410 // correlations for turbulent and laminar flow regimes. Todreas & Kazimi, Nuclear Systems Volume
411 // 1
412 if (subch_type == EChannelType::CENTER)
413 {
414 if (p_over_d < 1.1)
415 {
416 k1L = 26.37;
417 k2L = 374.2;
418 k3L = -493.9;
419 k1T = 0.09423;
420 k2T = 0.5806;
421 k3T = -1.239;
422 }
423 else
424 {
425 k1L = 35.55;
426 k2L = 263.7;
427 k3L = -190.2;
428 k1T = 0.1339;
429 k2T = 0.09059;
430 k3T = -0.09926;
431 }
432 // laminar flow friction factor for bare Pin bundle - Center subchannel
433 CfL = k1L + k2L * (p_over_d - 1) + k3L * Utility::pow<2>((p_over_d - 1));
434 // turbulent flow friction factor for bare Pin bundle - Center subchannel
435 CfT = k1T + k2T * (p_over_d - 1) + k3T * Utility::pow<2>((p_over_d - 1));
436 }
437 else if (subch_type == EChannelType::EDGE)
438 {
439 if (p_over_d < 1.1)
440 {
441 k1L = 26.18;
442 k2L = 554.5;
443 k3L = -1480;
444 k1T = 0.09377;
445 k2T = 0.8732;
446 k3T = -3.341;
447 }
448 else
449 {
450 k1L = 44.40;
451 k2L = 256.7;
452 k3L = -267.6;
453 k1T = 0.1430;
454 k2T = 0.04199;
455 k3T = -0.04428;
456 }
457 // laminar flow friction factor for bare Pin bundle - Edge subchannel
458 CfL = k1L + k2L * (w_over_d - 1) + k3L * Utility::pow<2>((w_over_d - 1));
459 // turbulent flow friction factor for bare Pin bundle - Edge subchannel
460 CfT = k1T + k2T * (w_over_d - 1) + k3T * Utility::pow<2>((w_over_d - 1));
461 }
462 else
463 {
464 if (p_over_d < 1.1)
465 {
466 k1L = 28.62;
467 k2L = 715.9;
468 k3L = -2807;
469 k1T = 0.09755;
470 k2T = 1.127;
471 k3T = -6.304;
472 }
473 else
474 {
475 k1L = 58.83;
476 k2L = 160.7;
477 k3L = -203.5;
478 k1T = 0.1452;
479 k2T = 0.02681;
480 k3T = -0.03411;
481 }
482 // laminar flow friction factor for bare Pin bundle - Corner subchannel
483 CfL = k1L + k2L * (w_over_d - 1) + k3L * Utility::pow<2>((w_over_d - 1));
484 // turbulent flow friction factor for bare Pin bundle - Corner subchannel
485 CfT = k1T + k2T * (w_over_d - 1) + k3T * Utility::pow<2>((w_over_d - 1));
486 }
487 // laminar friction factor and turbulent friction factor coefficients
488 const Real mL = -1.0;
489 const Real mT = -0.18;
490 auto fL = CfL * std::pow(Re_eff, mL);
491 auto fT = CfT * std::pow(Re_eff, mT);
492 gamma = 1.0 / 3.0;
493 lambda = 7.0;
494 if (Reb < ReL)
495 {
496 // laminar flow
497 return fL;
498 }
499 else if (Reb > ReT)
500 {
501 // turbulent flow
502 return fT;
503 }
504 else
505 {
506 // Transition regime is selected by bulk Reynolds number, same for all channels.
507 return fL * std::pow((1 - psi), gamma) * (1 - std::pow(psi, lambda)) +
508 fT * std::pow(psi, gamma);
509 }
510}
const double Re
registerMooseObject("SubChannelApp", SCMFrictionChenTodreas)
registerMooseObjectRenamed("SubChannelApp", SCMFrictionUpgradedChengTodreas, "09/30/2027 24:00", SCMFrictionChenTodreas)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
Creates the mesh of subchannels in a quadrilateral lattice.
const Real & getSideGap() const
Returns the side gap, not to be confused with the gap between pins, this refers to the gap next to th...
const SubChannel1PhaseProblem & _scm_problem
Reference to the subchannel problem.
const SubChannelMesh & _subchannel_mesh
Reference to the subchannel mesh.
Class that calculates the friction factor using the Chen-Todreas correlations.
SCMFrictionChenTodreas(const InputParameters &parameters)
const TriSubChannelMesh *const _tri_sch_mesh
Pointer to the tri lattice mesh.
Real computeTriLatticeFrictionFactor(const FrictionStruct &friction_info) const
Real computeQuadLatticeFrictionFactor(const FrictionStruct &friction_info) const
bool _is_tri_lattice
Keep track of the lattice type.
const bool _has_wire_wrap
Whether the triangular assembly has wire-wrap geometry.
virtual Real computeFrictionFactor(const FrictionStruct &friction_info) const override
Computes the friction factor for the local conditions.
static InputParameters validParams()
const MooseEnum & _friction_model
Chen-Todreas correlation version.
const QuadSubChannelMesh *const _quad_sch_mesh
Pointer to the quad lattice mesh.
Base class for friction closures used in SCM.
static InputParameters validParams()
virtual const Real & getPitch() const
Return the undeformed pitch between 2 subchannels.
virtual EChannelType getSubchannelType(unsigned int index) const =0
Return the type of the subchannel for given subchannel 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 & getWireDiameter() const
Return wire diameter.
const Real & getDuctToPinGap() const
Return the the gap thickness between the duct and peripheral fuel pins.
const Real & getWireLeadLength() const
Return the wire lead length.
const unsigned int & getNumOfRings() const
Return the number of fuel-pin rings, counting the center pin as the first ring.
const Real pi
structure with the needed information to compute the friction factor at a specific subchannel cell