LCOV - code coverage report
Current view: top level - src/scmclosures - SCMFrictionUpdatedChengTodreas.C (source / functions) Hit Total Coverage
Test: idaholab/moose subchannel: #32971 (54bef8) with base c6cf66 Lines: 118 124 95.2 %
Date: 2026-05-29 20:40:47 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          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 "SCMFrictionUpdatedChengTodreas.h"
      11             : 
      12             : registerMooseObject("SubChannelApp", SCMFrictionUpdatedChengTodreas);
      13             : 
      14             : InputParameters
      15         359 : SCMFrictionUpdatedChengTodreas::validParams()
      16             : {
      17         359 :   InputParameters params = SCMFrictionClosureBase::validParams();
      18         359 :   params.addClassDescription("Class that computes the axial friction factor using the updated "
      19             :                              "Cheng Todreas correlations.");
      20         359 :   return params;
      21           0 : }
      22             : 
      23         191 : SCMFrictionUpdatedChengTodreas::SCMFrictionUpdatedChengTodreas(const InputParameters & parameters)
      24             :   : SCMFrictionClosureBase(parameters),
      25         191 :     _is_tri_lattice(dynamic_cast<const TriSubChannelMesh *>(&_subchannel_mesh) != nullptr),
      26         191 :     _tri_sch_mesh(dynamic_cast<const TriSubChannelMesh *>(&_subchannel_mesh)),
      27         191 :     _quad_sch_mesh(dynamic_cast<const QuadSubChannelMesh *>(&_subchannel_mesh)),
      28         191 :     _has_wire_wrap(_is_tri_lattice && _tri_sch_mesh->getWireDiameter() != 0.0 &&
      29         349 :                    _tri_sch_mesh->getWireLeadLength() != 0.0)
      30             : {
      31         191 :   if (_is_tri_lattice &&
      32         182 :       ((_tri_sch_mesh->getWireDiameter() != 0.0) != (_tri_sch_mesh->getWireLeadLength() != 0.0)))
      33           0 :     mooseError(name(),
      34             :                ": wire-wrapped bundle friction requires both wire diameter and wire lead length. "
      35             :                "Set both to zero for a bare pin bundle.");
      36             : 
      37         191 :   if (_is_tri_lattice)
      38             :   {
      39         182 :     const auto pitch = _subchannel_mesh.getPitch();
      40         182 :     const auto pin_diameter = _subchannel_mesh.getPinDiameter();
      41         182 :     const auto p_over_d = pitch / pin_diameter;
      42         182 :     const auto wire_lead_to_diameter = _tri_sch_mesh->getWireLeadLength() / pin_diameter;
      43         182 :     const unsigned int Nr = _tri_sch_mesh->getNumOfRings();
      44         182 :     const unsigned int num_pins = 1 + 3 * Nr * (Nr - 1);
      45             : 
      46             :     // The updated Cheng-Todreas detailed triangular friction factor correlation is based on
      47             :     // data spanning 1.0 <= P/D <= 1.42, 4 <= H/D <= 52, 7 <= Npin <= 271,
      48             :     // and 50 <= Re <= 1e6.
      49         182 :     if (p_over_d < 1.0 || p_over_d > 1.42)
      50           0 :       flagSolutionWarning("Pitch-over-pin diameter ratio (P/D) outside the updated "
      51             :                           "Cheng-Todreas friction correlation data range.");
      52         182 :     if (_has_wire_wrap && (wire_lead_to_diameter < 4.0 || wire_lead_to_diameter > 52.0))
      53         132 :       flagSolutionWarning("Wire lead length-over-pin diameter ratio (H/D) outside the updated "
      54             :                           "Cheng-Todreas friction correlation data range.");
      55         182 :     if (num_pins < 7 || num_pins > 271)
      56           0 :       flagSolutionWarning("Number of pins outside the updated Cheng-Todreas friction correlation "
      57             :                           "data range.");
      58             :   }
      59         191 : }
      60             : 
      61             : Real
      62    14201085 : SCMFrictionUpdatedChengTodreas::computeFrictionFactor(const FrictionStruct & friction_args) const
      63             : {
      64    14201085 :   if (_is_tri_lattice)
      65     7175685 :     return computeTriLatticeFrictionFactor(friction_args);
      66             :   else
      67     7025400 :     return computeQuadLatticeFrictionFactor(friction_args);
      68             : }
      69             : 
      70             : Real
      71     7175685 : SCMFrictionUpdatedChengTodreas::computeTriLatticeFrictionFactor(
      72             :     const FrictionStruct & friction_args) const
      73             : {
      74     7175685 :   const auto Re = friction_args.Re;
      75     7175685 :   const auto i_ch = friction_args.i_ch;
      76     7175685 :   const auto S = friction_args.S;
      77     7175685 :   const auto w_perim = friction_args.w_perim;
      78     7175685 :   const auto Dh_i = 4.0 * S / w_perim;
      79             :   Real aL, b1L, b2L, cL;
      80             :   Real aT, b1T, b2T, cT;
      81     7175685 :   const Real & pitch = _subchannel_mesh.getPitch();
      82     7175685 :   const Real & pin_diameter = _subchannel_mesh.getPinDiameter();
      83     7175685 :   const Real & wire_lead_length = _tri_sch_mesh->getWireLeadLength();
      84             :   const Real & wire_diameter = _tri_sch_mesh->getWireDiameter();
      85     7175685 :   const auto p_over_d = pitch / pin_diameter;
      86     7175685 :   const auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
      87             :   // This gap is a constant value for the whole assembly. Might want to make it
      88             :   // subchannel specific in the future if we have duct deformation.
      89     7175685 :   const auto gap = _tri_sch_mesh->getDuctToPinGap();
      90     7175685 :   const auto w_over_d = (pin_diameter + gap) / pin_diameter;
      91             : 
      92     7175685 :   if (Re < 50.0 || Re > 1.0e6)
      93       14367 :     flagSolutionWarning("Reynolds number (Re) outside the updated Cheng-Todreas friction "
      94             :                         "correlation data range.");
      95             : 
      96     7175685 :   const auto ReL = std::pow(10, (p_over_d - 1)) * 320.0;
      97     7175685 :   const auto ReT = std::pow(10, 0.7 * (p_over_d - 1)) * 1.0E+4;
      98     7175685 :   const auto psi = std::log(Re / ReL) / std::log(ReT / ReL);
      99             : 
     100             :   // Find the coefficients of bare Pin bundle friction factor
     101             :   // correlations for turbulent and laminar flow regimes. Todreas & Kazimi, Nuclear Systems
     102             :   // second edition, Volume 1, Chapter 9.6
     103     7175685 :   if (subch_type == EChannelType::CENTER)
     104             :   {
     105     4608591 :     if (p_over_d < 1.1)
     106             :     {
     107             :       aL = 26.0;
     108             :       b1L = 888.2;
     109             :       b2L = -3334.0;
     110             :       aT = 0.09378;
     111             :       b1T = 1.398;
     112             :       b2T = -8.664;
     113             :     }
     114             :     else
     115             :     {
     116             :       aL = 62.97;
     117             :       b1L = 216.9;
     118             :       b2L = -190.2;
     119             :       aT = 0.1458;
     120             :       b1T = 0.03632;
     121             :       b2T = -0.03333;
     122             :     }
     123             :     // laminar flow friction factor for bare Pin bundle - Center subchannel
     124     4608591 :     cL = aL + b1L * (p_over_d - 1) + b2L * Utility::pow<2>((p_over_d - 1));
     125             :     // turbulent flow friction factor for bare Pin bundle - Center subchannel
     126     4608591 :     cT = aT + b1T * (p_over_d - 1) + b2T * Utility::pow<2>((p_over_d - 1));
     127             :   }
     128     2567094 :   else if (subch_type == EChannelType::EDGE)
     129             :   {
     130     1827498 :     if (w_over_d < 1.1)
     131             :     {
     132             :       aL = 26.18;
     133             :       b1L = 554.5;
     134             :       b2L = -1480.0;
     135             :       aT = 0.09377;
     136             :       b1T = 0.8732;
     137             :       b2T = -3.341;
     138             :     }
     139             :     else
     140             :     {
     141             :       aL = 44.4;
     142             :       b1L = 256.7;
     143             :       b2L = -267.6;
     144             :       aT = 0.1430;
     145             :       b1T = 0.04199;
     146             :       b2T = -0.04428;
     147             :     }
     148             :     // laminar flow friction factor for bare Pin bundle - Edge subchannel
     149     1827498 :     cL = aL + b1L * (w_over_d - 1) + b2L * Utility::pow<2>((w_over_d - 1));
     150             :     // turbulent flow friction factor for bare Pin bundle - Edge subchannel
     151     1827498 :     cT = aT + b1T * (w_over_d - 1) + b2T * Utility::pow<2>((w_over_d - 1));
     152             :   }
     153             :   else
     154             :   {
     155      739596 :     if (w_over_d < 1.1)
     156             :     {
     157             :       aL = 26.98;
     158             :       b1L = 1636.0;
     159             :       b2L = -10050.0;
     160             :       aT = 0.1004;
     161             :       b1T = 1.625;
     162             :       b2T = -11.85;
     163             :     }
     164             :     else
     165             :     {
     166             :       aL = 87.26;
     167             :       b1L = 38.59;
     168             :       b2L = -55.12;
     169             :       aT = 0.1499;
     170             :       b1T = 0.006706;
     171             :       b2T = -0.009567;
     172             :     }
     173             :     // laminar flow friction factor for bare Pin bundle - Corner subchannel
     174      739596 :     cL = aL + b1L * (w_over_d - 1) + b2L * Utility::pow<2>((w_over_d - 1));
     175             :     // turbulent flow friction factor for bare Pin bundle - Corner subchannel
     176      739596 :     cT = aT + b1T * (w_over_d - 1) + b2T * Utility::pow<2>((w_over_d - 1));
     177             :   }
     178             : 
     179             :   // Find the coefficients of wire-wrapped Pin bundle friction factor
     180             :   // correlations for turbulent and laminar flow regimes. Todreas & Kazimi, Nuclear Systems
     181             :   // Volume 1 Chapter 9-6 also Chen and Todreas (2018).
     182     7175685 :   if (_has_wire_wrap)
     183             :   {
     184             :     const auto theta =
     185     5417925 :         std::acos(wire_lead_length /
     186     5417925 :                   std::sqrt(Utility::pow<2>(wire_lead_length) +
     187     5417925 :                             Utility::pow<2>(libMesh::pi * (pin_diameter + wire_diameter))));
     188     5417925 :     const auto wd_t = (19.56 - 98.71 * (wire_diameter / pin_diameter) +
     189     5417925 :                        303.47 * Utility::pow<2>((wire_diameter / pin_diameter))) *
     190     5417925 :                       std::pow((wire_lead_length / pin_diameter), -0.541);
     191     5417925 :     const auto wd_l = 1.4 * wd_t;
     192     5417925 :     const auto ws_t = -11.0 * std::log(wire_lead_length / pin_diameter) + 19.0;
     193             :     const auto ws_l = ws_t;
     194             :     Real ar = 0.0;
     195             :     Real a_p = 0.0;
     196             : 
     197     5417925 :     if (subch_type == EChannelType::CENTER)
     198             :     {
     199             :       // wetted perimeter for center subchannel and bare Pin bundle
     200     3465771 :       const Real pw_p = libMesh::pi * pin_diameter / 2.0;
     201             :       // wire projected area - center subchannel wire-wrapped bundle
     202     3465771 :       ar = libMesh::pi * (pin_diameter + wire_diameter) * wire_diameter / 6.0;
     203             :       // bare Pin bundle center subchannel flow area (normal area + wire area)
     204     3465771 :       a_p = S + libMesh::pi * Utility::pow<2>(wire_diameter) / 8.0 / std::cos(theta);
     205             :       // turbulent friction factor equation constant - Center subchannel
     206     3465771 :       cT *= (pw_p / w_perim);
     207     3465771 :       cT += wd_t * (3.0 * ar / a_p) * (Dh_i / wire_lead_length) *
     208     3465771 :             std::pow((Dh_i / wire_diameter), 0.18);
     209             :       // laminar friction factor equation constant - Center subchannel
     210     3465771 :       cL *= (pw_p / w_perim);
     211     3465771 :       cL += wd_l * (3.0 * ar / a_p) * (Dh_i / wire_lead_length) * (Dh_i / wire_diameter);
     212             :     }
     213     1952154 :     else if (subch_type == EChannelType::EDGE)
     214             :     {
     215             :       // wire projected area - edge subchannel wire-wrapped bundle
     216     1366548 :       ar = libMesh::pi * (pin_diameter + wire_diameter) * wire_diameter / 4.0;
     217             :       // bare Pin bundle edge subchannel flow area (normal area + wire area)
     218     1366548 :       a_p = S + libMesh::pi * Utility::pow<2>(wire_diameter) / 8.0 / std::cos(theta);
     219             :       // turbulent friction factor equation constant - Edge subchannel
     220     1366548 :       cT *= std::pow((1 + ws_t * (ar / a_p) * Utility::pow<2>(std::tan(theta))), 1.41);
     221             :       // laminar friction factor equation constant - Edge subchannel
     222     1366548 :       cL *= (1 + ws_l * (ar / a_p) * Utility::pow<2>(std::tan(theta)));
     223             :     }
     224             :     else
     225             :     {
     226             :       // wire projected area - corner subchannel wire-wrapped bundle
     227      585606 :       ar = libMesh::pi * (pin_diameter + wire_diameter) * wire_diameter / 6.0;
     228             :       // bare Pin bundle corner subchannel flow area (normal area + wire area)
     229      585606 :       a_p = S + libMesh::pi * Utility::pow<2>(wire_diameter) / 24.0 / std::cos(theta);
     230             :       // turbulent friction factor equation constant - Corner subchannel
     231      585606 :       cT *= std::pow((1 + ws_t * (ar / a_p) * Utility::pow<2>(std::tan(theta))), 1.41);
     232             :       // laminar friction factor equation constant - Corner subchannel
     233      585606 :       cL *= (1 + ws_l * (ar / a_p) * Utility::pow<2>(std::tan(theta)));
     234             :     }
     235             :   }
     236             :   // laminar friction factor and turbulent friction factor coefficients
     237             :   const Real bL = -1.0;
     238             :   const Real bT = -0.18;
     239     7175685 :   auto fL = cL * std::pow(Re, bL);
     240     7175685 :   auto fT = cT * std::pow(Re, bT);
     241             : 
     242     7175685 :   if (Re < ReL)
     243             :   {
     244             :     // laminar flow
     245             :     return fL;
     246             :   }
     247     7161321 :   else if (Re > ReT)
     248             :   {
     249             :     // turbulent flow
     250             :     return fT;
     251             :   }
     252             :   else
     253             :   {
     254             :     // transient flow: psi definition uses a Bulk ReT/ReL number, same for all channels
     255     1127535 :     return fL * std::pow((1 - psi), 1.0 / 3.0) * (1 - std::pow(psi, 7)) +
     256     1127535 :            fT * std::pow(psi, 1.0 / 3.0);
     257             :   }
     258             : }
     259             : 
     260             : Real
     261     7025400 : SCMFrictionUpdatedChengTodreas::computeQuadLatticeFrictionFactor(
     262             :     const FrictionStruct & friction_args) const
     263             : {
     264     7025400 :   const auto Re = friction_args.Re;
     265     7025400 :   const auto i_ch = friction_args.i_ch;
     266             :   /// Todreas-Kazimi NUCLEAR SYSTEMS, second edition, Volume 1, 2011
     267             :   Real aL, b1L, b2L, cL;
     268             :   Real aT, b1T, b2T, cT;
     269     7025400 :   const auto pitch = _subchannel_mesh.getPitch();
     270     7025400 :   const auto pin_diameter = _subchannel_mesh.getPinDiameter();
     271             :   // This gap is a constant value for the whole assembly. Might want to make it
     272             :   // subchannel specific in the future if we have duct deformation.
     273     7025400 :   const auto side_gap = _quad_sch_mesh->getSideGap();
     274     7025400 :   const auto w = (pin_diameter / 2.0) + (pitch / 2.0) + side_gap;
     275     7025400 :   const auto p_over_d = pitch / pin_diameter;
     276     7025400 :   const auto w_over_d = w / pin_diameter;
     277     7025400 :   const auto ReL = std::pow(10, (p_over_d - 1)) * 320.0;
     278     7025400 :   const auto ReT = std::pow(10, 0.7 * (p_over_d - 1)) * 1.0E+4;
     279     7025400 :   const auto psi = std::log(Re / ReL) / std::log(ReT / ReL);
     280     7025400 :   const auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
     281             : 
     282             :   // Find the coefficients of bare Pin bundle friction factor
     283             :   // correlations for turbulent and laminar flow regimes. Todreas & Kazimi, Nuclear Systems Volume
     284             :   // 1
     285     7025400 :   if (subch_type == EChannelType::CENTER)
     286             :   {
     287     3620600 :     if (p_over_d < 1.1)
     288             :     {
     289             :       aL = 26.37;
     290             :       b1L = 374.2;
     291             :       b2L = -493.9;
     292             :       aT = 0.09423;
     293             :       b1T = 0.5806;
     294             :       b2T = -1.239;
     295             :     }
     296             :     else
     297             :     {
     298             :       aL = 35.55;
     299             :       b1L = 263.7;
     300             :       b2L = -190.2;
     301             :       aT = 0.1339;
     302             :       b1T = 0.09059;
     303             :       b2T = -0.09926;
     304             :     }
     305             :     // laminar flow friction factor for bare Pin bundle - Center subchannel
     306     3620600 :     cL = aL + b1L * (p_over_d - 1) + b2L * Utility::pow<2>((p_over_d - 1));
     307             :     // turbulent flow friction factor for bare Pin bundle - Center subchannel
     308     3620600 :     cT = aT + b1T * (p_over_d - 1) + b2T * Utility::pow<2>((p_over_d - 1));
     309             :   }
     310     3404800 :   else if (subch_type == EChannelType::EDGE)
     311             :   {
     312     2867200 :     if (p_over_d < 1.1)
     313             :     {
     314             :       aL = 26.18;
     315             :       b1L = 554.5;
     316             :       b2L = -1480;
     317             :       aT = 0.09377;
     318             :       b1T = 0.8732;
     319             :       b2T = -3.341;
     320             :     }
     321             :     else
     322             :     {
     323             :       aL = 44.40;
     324             :       b1L = 256.7;
     325             :       b2L = -267.6;
     326             :       aT = 0.1430;
     327             :       b1T = 0.04199;
     328             :       b2T = -0.04428;
     329             :     }
     330             :     // laminar flow friction factor for bare Pin bundle - Edge subchannel
     331     2867200 :     cL = aL + b1L * (w_over_d - 1) + b2L * Utility::pow<2>((w_over_d - 1));
     332             :     // turbulent flow friction factor for bare Pin bundle - Edge subchannel
     333     2867200 :     cT = aT + b1T * (w_over_d - 1) + b2T * Utility::pow<2>((w_over_d - 1));
     334             :   }
     335             :   else
     336             :   {
     337      537600 :     if (p_over_d < 1.1)
     338             :     {
     339             :       aL = 28.62;
     340             :       b1L = 715.9;
     341             :       b2L = -2807;
     342             :       aT = 0.09755;
     343             :       b1T = 1.127;
     344             :       b2T = -6.304;
     345             :     }
     346             :     else
     347             :     {
     348             :       aL = 58.83;
     349             :       b1L = 160.7;
     350             :       b2L = -203.5;
     351             :       aT = 0.1452;
     352             :       b1T = 0.02681;
     353             :       b2T = -0.03411;
     354             :     }
     355             :     // laminar flow friction factor for bare Pin bundle - Corner subchannel
     356      537600 :     cL = aL + b1L * (w_over_d - 1) + b2L * Utility::pow<2>((w_over_d - 1));
     357             :     // turbulent flow friction factor for bare Pin bundle - Corner subchannel
     358      537600 :     cT = aT + b1T * (w_over_d - 1) + b2T * Utility::pow<2>((w_over_d - 1));
     359             :   }
     360             :   // laminar friction factor and turbulent friction factor coefficients
     361             :   const Real bL = -1.0;
     362             :   const Real bT = -0.18;
     363     7025400 :   auto fL = cL * std::pow(Re, bL);
     364     7025400 :   auto fT = cT * std::pow(Re, bT);
     365             : 
     366     7025400 :   if (Re < ReL)
     367             :   {
     368             :     // laminar flow
     369             :     return fL;
     370             :   }
     371     7025400 :   else if (Re > ReT)
     372             :   {
     373             :     // turbulent flow
     374             :     return fT;
     375             :   }
     376             :   else
     377             :   {
     378             :     // transient flow: psi definition uses a Bulk ReT/ReL number, same for all channels
     379           0 :     return fL * std::pow((1 - psi), 1.0 / 3.0) * (1 - std::pow(psi, 7)) +
     380           0 :            fT * std::pow(psi, 1.0 / 3.0);
     381             :   }
     382             : }

Generated by: LCOV version 1.14