Skip to content

pumping

Engineering models for pumping system analysis.

CoolantType

Bases: IntEnum

Enum for coolant types.

Source code in process/models/engineering/pumping.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@unique
class CoolantType(IntEnum):
    """Enum for coolant types."""

    HELIUM = (1, "Helium")
    WATER = (2, "Water")

    def __new__(cls, value: int, full_name: str):
        """Create a new CoolantType enum member with value and full_name.

        Parameters
        ----------
        value : int
            The numeric value of the enum member.
        full_name : str
            The full name description of the coolant type.
            This should match the CoolProp name for the coolant type.

        Returns
        -------
        CoolantType
            A new enum member with the specified value and full_name.
        """
        obj = int.__new__(cls, value)
        obj._value_ = value
        obj._full_name_ = full_name
        return obj

    @DynamicClassAttribute
    def full_name(self):
        """The full name of the coolant type."""
        return self._full_name_

HELIUM = (1, 'Helium') class-attribute instance-attribute

WATER = (2, 'Water') class-attribute instance-attribute

full_name()

The full name of the coolant type.

Source code in process/models/engineering/pumping.py
44
45
46
47
@DynamicClassAttribute
def full_name(self):
    """The full name of the coolant type."""
    return self._full_name_

CoolantFrictionLossParameters dataclass

Parameters for calculating coolant friction losses.

Source code in process/models/engineering/pumping.py
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
@dataclass
class CoolantFrictionLossParameters:
    """Parameters for calculating coolant friction losses."""

    dpres_total: float
    """Total pressure drop across the coolant channel [Pa]"""
    dpres_straight: float
    """Pressure drop due to straight length of the coolant channel [Pa]"""
    dpres_90: float
    """Pressure drop due to 90 degree bends in the coolant channel [Pa]"""
    dpres_90_total: float
    """Total pressure drop due to 90 degree bends in the coolant channel [Pa]"""
    dpres_180: float
    """Pressure drop due to 180 degree bends in the coolant channel [Pa]"""
    dpres_180_total: float
    """Total pressure drop due to 180 degree bends in the coolant channel [Pa]"""
    dpres_bends_total: float
    """Total pressure drop due to bends in the coolant channel [Pa]"""
    reynolds_number: float
    """Reynolds number of the coolant flow in the channel"""
    darcy_friction_factor: float
    """Darcy friction factor for the coolant flow in the channel"""
    f_straight: float
    """Friction factor for straight length of the coolant channel"""
    len_straight: float
    """Length of straight sections of the coolant channel [m]"""
    f_elbow_90: float
    """Friction factor for 90 degree bends in the coolant channel"""
    f_elbow_180: float
    """Friction factor for 180 degree bends in the coolant channel"""

dpres_total instance-attribute

Total pressure drop across the coolant channel [Pa]

dpres_straight instance-attribute

Pressure drop due to straight length of the coolant channel [Pa]

dpres_90 instance-attribute

Pressure drop due to 90 degree bends in the coolant channel [Pa]

dpres_90_total instance-attribute

Total pressure drop due to 90 degree bends in the coolant channel [Pa]

dpres_180 instance-attribute

Pressure drop due to 180 degree bends in the coolant channel [Pa]

dpres_180_total instance-attribute

Total pressure drop due to 180 degree bends in the coolant channel [Pa]

dpres_bends_total instance-attribute

Total pressure drop due to bends in the coolant channel [Pa]

reynolds_number instance-attribute

Reynolds number of the coolant flow in the channel

darcy_friction_factor instance-attribute

Darcy friction factor for the coolant flow in the channel

f_straight instance-attribute

Friction factor for straight length of the coolant channel

len_straight instance-attribute

Length of straight sections of the coolant channel [m]

f_elbow_90 instance-attribute

Friction factor for 90 degree bends in the coolant channel

f_elbow_180 instance-attribute

Friction factor for 180 degree bends in the coolant channel

coolant_friction_pressure_drop(i_ps, radius_pipe_90_deg_bend, radius_pipe_180_deg_bend, n_pipe_90_deg_bends, n_pipe_180_deg_bends, len_pipe, den_coolant, visc_coolant, vel_coolant, roughness_channel, radius_channel, a_bz_liq, b_bz_liq)

Pressure drops are calculated for a pipe with a number of 90 and 180 degree bends. The pressure drop due to frictional forces along the total straight length of the pipe is calculated, then the pressure drop due to the bends is calculated. The total pressure drop is the sum of all contributions.

Parameters:

Name Type Description Default
i_ps int

switch for primary or secondary coolant

required
radius_pipe_90_deg_bend float

radius of 90 degree bend in pipe [m]

required
radius_pipe_180_deg_bend float

radius of 180 degree bend in pipe [m]

required
n_pipe_90_deg_bends float

number of 90 degree bends in the pipe

required
n_pipe_180_deg_bends float

number of 180 degree bends in the pipe

required
len_pipe float

total flow length along pipe [m]

required
den_coolant float

coolant density [kg/m³]

required
visc_coolant float

coolant viscosity [Pa s]

required
vel_coolant float

coolant flow velocity [m/s]

required
roughness_channel float

roughness of the channel wall (ε) [m]

required
radius_channel float

radius of the channel [m]

required
a_bz_liq float

width of the breeding blanket coolant channel [m]

required
b_bz_liq float

height of the breeding blanket coolant channel [m]

required

Returns:

Type Description
CoolantFrictionLossParameters

CoolantFrictionLossParameters dataclass containing: - Total pressure drop due to friction (Pa) - Pressure drop due to straight sections (Pa) - Pressure drop due to 90 degree bends (Pa) - Pressure drop due to 180 degree bends (Pa) - Reynolds number - Darcy friction factor - Pressure drop coefficient for straight sections - Pressure drop coefficient for 90 degree bends - Pressure drop coefficient for 180 degree bends

Notes
Darcy-Weisbach Equation (straight pipe):

ΔP = λ * L/D * (p 〈v〉²) / 2

λ - Darcy friction factor, L - pipe length, D - hydraulic diameter,
p - fluid density, 〈v〉 - fluid flow average velocity

This function also calculates pressure drop equations for elbow bends,
with modified coefficients.

N.B. Darcy friction factor is estimated from the Haaland approximation.
Source code in process/models/engineering/pumping.py
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
def coolant_friction_pressure_drop(
    i_ps: int,
    radius_pipe_90_deg_bend: float,
    radius_pipe_180_deg_bend: float,
    n_pipe_90_deg_bends: float,
    n_pipe_180_deg_bends: float,
    len_pipe: float,
    den_coolant: float,
    visc_coolant: float,
    vel_coolant: float,
    roughness_channel: float,
    radius_channel: float,
    a_bz_liq: float,
    b_bz_liq: float,
) -> CoolantFrictionLossParameters:
    """Pressure drops are calculated for a pipe with a number of 90
    and 180 degree bends. The pressure drop due to frictional forces along
    the total straight length of the pipe is calculated, then the pressure
    drop due to the bends is calculated. The total pressure drop is the sum
    of all contributions.

    Parameters
    ----------
    i_ps :
        switch for primary or secondary coolant
    radius_pipe_90_deg_bend :
        radius of 90 degree bend in pipe [m]
    radius_pipe_180_deg_bend :
        radius of 180 degree bend in pipe [m]
    n_pipe_90_deg_bends :
        number of 90 degree bends in the pipe
    n_pipe_180_deg_bends :
        number of 180 degree bends in the pipe
    len_pipe :
        total flow length along pipe [m]
    den_coolant :
        coolant density [kg/m³]
    visc_coolant :
        coolant viscosity [Pa s]
    vel_coolant :
        coolant flow velocity [m/s]
    roughness_channel :
        roughness of the channel wall (ε) [m]
    radius_channel :
        radius of the channel [m]
    a_bz_liq :
        width of the breeding blanket coolant channel [m]
    b_bz_liq :
        height of the breeding blanket coolant channel [m]


    Returns
    -------
    :
        `CoolantFrictionLossParameters` dataclass containing:
        - Total pressure drop due to friction (Pa)
        - Pressure drop due to straight sections (Pa)
        - Pressure drop due to 90 degree bends (Pa)
        - Pressure drop due to 180 degree bends (Pa)
        - Reynolds number
        - Darcy friction factor
        - Pressure drop coefficient for straight sections
        - Pressure drop coefficient for 90 degree bends
        - Pressure drop coefficient for 180 degree bends

    Notes
    -----
        Darcy-Weisbach Equation (straight pipe):

        ΔP = λ * L/D * (p 〈v〉²) / 2

        λ - Darcy friction factor, L - pipe length, D - hydraulic diameter,
        p - fluid density, 〈v〉 - fluid flow average velocity

        This function also calculates pressure drop equations for elbow bends,
        with modified coefficients.

        N.B. Darcy friction factor is estimated from the Haaland approximation.
    """
    # Calculate hydraulic dimater for round or retancular pipe (m)
    dia_pipe = pipe_hydraulic_diameter(
        i_channel_shape=i_ps,
        radius_fw_channel=radius_channel,
        a_bz_liq=a_bz_liq,
        b_bz_liq=b_bz_liq,
    )

    # Reynolds number (Re)
    reynolds_number = calculate_reynolds_number(
        den_coolant=den_coolant,
        vel_coolant=vel_coolant,
        radius_channel=dia_pipe / 2,
        visc_coolant=visc_coolant,
    )

    # Calculate Darcy friction factor
    # N.B. friction function Uses Haaland approx. which assumes a filled
    # circular pipe.
    # Use dh which allows us to do fluid calculations for non-circular tubes
    # (dh is estimate appropriate for fully developed flow).

    darcy_friction_factor = darcy_friction_haaland(
        reynolds=reynolds_number,
        roughness_channel=roughness_channel,
        dia_channel=dia_pipe,
    )

    # Pressure drop coefficient

    # Straight section
    f_straight = darcy_friction_factor * len_pipe / dia_pipe

    # 90 degree elbow pressure drop coefficient
    f_elbow_90 = elbow_coeff(
        radius_pipe_elbow=radius_pipe_90_deg_bend,
        deg_pipe_elbow=90.0,
        darcy_friction=darcy_friction_factor,
        dia_pipe=dia_pipe,
    )

    # 180 degree elbow pressure drop coefficient
    f_elbow_180 = elbow_coeff(
        radius_pipe_elbow=radius_pipe_180_deg_bend,
        deg_pipe_elbow=180.0,
        darcy_friction=darcy_friction_factor,
        dia_pipe=dia_pipe,
    )

    # Pressure drop due to friction in straight sections
    dpres_straight = f_straight * 0.5 * den_coolant * vel_coolant**2

    # Pressure drop due to 90 and 180 degree bends
    dpres_90 = f_elbow_90 * 0.5 * den_coolant * vel_coolant**2
    dpres_90_total = n_pipe_90_deg_bends * dpres_90
    dpres_180 = f_elbow_180 * 0.5 * den_coolant * vel_coolant**2
    dpres_180_total = n_pipe_180_deg_bends * dpres_180

    dpres_bends_total = dpres_90_total + dpres_180_total

    # Total pressure drop (Pa)
    dpres_total = dpres_straight + dpres_bends_total

    return CoolantFrictionLossParameters(
        dpres_total=dpres_total,
        dpres_straight=dpres_straight,
        dpres_90=dpres_90,
        dpres_90_total=dpres_90_total,
        dpres_180=dpres_180,
        dpres_180_total=dpres_180_total,
        dpres_bends_total=dpres_bends_total,
        reynolds_number=reynolds_number,
        darcy_friction_factor=darcy_friction_factor,
        f_straight=f_straight,
        len_straight=len_pipe,
        f_elbow_90=f_elbow_90,
        f_elbow_180=f_elbow_180,
    )

pipe_hydraulic_diameter(i_channel_shape, radius_fw_channel, a_bz_liq, b_bz_liq)

Caculate the hydraulic diameter [m] for a given coolant pipe size/shape.

Parameters:

Name Type Description Default
i_channel_shape

switch for circular or rectangular channel crossection. Shape depends on whether primary or secondary coolant is used. 1 = circular channel (primary coolant) 2 = rectangular channel (secondary coolant)

required

Returns:

Type Description
float

Hydraulic diameter of the coolant channel [m].

Raises:

Type Description
ProcessValueError

If i_channel_shape is not 1 or 2.

Source code in process/models/engineering/pumping.py
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
def pipe_hydraulic_diameter(
    i_channel_shape, radius_fw_channel: float, a_bz_liq: float, b_bz_liq: float
) -> float:
    """Caculate the hydraulic diameter [m] for a given coolant pipe size/shape.


    Parameters
    ----------
    i_channel_shape :
        switch for circular or rectangular channel crossection.
        Shape depends on whether primary or secondary coolant is used.
        1 = circular channel (primary coolant)
        2 = rectangular channel (secondary coolant)

    Returns
    -------
    :
        Hydraulic diameter of the coolant channel [m].

    Raises
    ------
    ProcessValueError
        If i_channel_shape is not 1 or 2.
    """
    # If primary coolant then circular channels assumed
    if i_channel_shape == 1:
        return 2.0 * radius_fw_channel

    # If secondary coolant then rectangular channels assumed
    if i_channel_shape == 2:
        return 2 * a_bz_liq * b_bz_liq / (a_bz_liq + b_bz_liq)

    raise ProcessValueError(f"i_channel_shape ={i_channel_shape} is an invalid option.")

darcy_friction_haaland(reynolds, roughness_channel, dia_channel)

Calculate Darcy friction factor using the Haaland equation.

Parameters:

Name Type Description Default
reynolds float

Reynolds number.

required
roughness_channel float

Roughness of the coolant channel [m].

required
dia_channel float

Hydraulic diameter of the coolant channel [m].

required

Returns:

Type Description
float

Darcy friction factor.

Notes
  • The Haaland equation is an approximation to the implicit Colebrook-White equation.
  • It is used to calculate the Darcy friction factor for turbulent flow in pipes.
References

[1] https://en.wikipedia.org/wiki/Darcy_friction_factor_formulae#Haaland_equation

Source code in process/models/engineering/pumping.py
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
def darcy_friction_haaland(
    reynolds: float, roughness_channel: float, dia_channel: float
) -> float:
    """Calculate Darcy friction factor using the Haaland equation.

    Parameters
    ----------
    reynolds:
        Reynolds number.
    roughness_channel:
        Roughness of the coolant channel [m].
    dia_channel:
        Hydraulic diameter of the coolant channel [m].

    Returns
    -------
    :
        Darcy friction factor.

    Notes
    -----
    - The Haaland equation is an approximation to the implicit Colebrook-White equation.
    - It is used to calculate the Darcy friction factor for turbulent flow in pipes.

    References
    ----------
    [1] https://en.wikipedia.org/wiki/Darcy_friction_factor_formulae#Haaland_equation
    """
    # Bracketed term in Haaland equation
    bracket = (roughness_channel / dia_channel / 3.7) ** 1.11 + 6.9 / reynolds

    # Calculate Darcy friction factor
    return (1.8 * np.log10(bracket)) ** (-2)

coolant_pumping_power(i_liquid_breeder, temp_coolant_pump_outlet, temp_coolant_pump_inlet, pres_coolant_pump_inlet, dpres_coolant, mflow_coolant_total, i_coolant_type, den_coolant, etaiso, etaiso_liq)

Calculate the coolant pumping power in MW for the first wall (FW) or breeding blanket (BZ) coolant.

Parameters:

Name Type Description Default
i_liquid_breeder int

Switch for primary coolant or secondary coolant/breeder (1=primary He/H2O, 2=secondary PbLi/Li).

required
temp_coolant_pump_outlet float

Pump outlet temperature [K].

required
temp_coolant_pump_inlet float

Pump inlet temperature [K].

required
pres_coolant_pump_inlet float

Pump inlet pressure [Pa].

required
dpres_coolant float

Coolant pressure drop [Pa].

required
mflow_coolant_total float

Total coolant mass flow rate [kg/s].

required
i_coolant_type int

Type of FW/blanket coolant (e.g., 1=Helium, 2=Water)

required
den_coolant float

Density of coolant or liquid breeder [kg/m³].

required
etaiso float

Isentropic efficiency of the pump for primary coolant.

required
etaiso_liq float

Isentropic efficiency of the pump for secondary coolant/breeder.

required

Returns:

Type Description
float

Pumping power [MW].

Raises:

Type Description
ProcessValueError

If the pressure drops in the coolant are too large to be feasible.

References

[1] Idel'Cik, I. E. (1969), Memento des pertes de charge [2] S.P. Sukhatme (2005), A Textbook on Heat Transfer

Source code in process/models/engineering/pumping.py
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
def coolant_pumping_power(
    i_liquid_breeder: int,
    temp_coolant_pump_outlet: float,
    temp_coolant_pump_inlet: float,
    pres_coolant_pump_inlet: float,
    dpres_coolant: float,
    mflow_coolant_total: float,
    i_coolant_type: int,
    den_coolant: float,
    etaiso: float,
    etaiso_liq: float,
) -> float:
    """Calculate the coolant pumping power in MW for the first wall (FW) or breeding
    blanket (BZ) coolant.

    Parameters
    ----------
    i_liquid_breeder : int
        Switch for primary coolant or secondary coolant/breeder
        (1=primary He/H2O, 2=secondary PbLi/Li).
    temp_coolant_pump_outlet : float
        Pump outlet temperature [K].
    temp_coolant_pump_inlet : float
        Pump inlet temperature [K].
    pres_coolant_pump_inlet : float
        Pump inlet pressure [Pa].
    dpres_coolant : float
        Coolant pressure drop [Pa].
    mflow_coolant_total : float
        Total coolant mass flow rate [kg/s].
    i_coolant_type : int
        Type of FW/blanket coolant (e.g., 1=Helium, 2=Water)
    den_coolant : float
        Density of coolant or liquid breeder [kg/m³].
    etaiso : float
        Isentropic efficiency of the pump for primary coolant.
    etaiso_liq : float
        Isentropic efficiency of the pump for secondary coolant/breeder.

    Returns
    -------
    :float
        Pumping power [MW].

    Raises
    ------
    ProcessValueError
        If the pressure drops in the coolant are too large to be feasible.

    References
    ----------
    [1] Idel'Cik, I. E. (1969), Memento des pertes de charge
    [2] S.P. Sukhatme (2005), A Textbook on Heat Transfer
    """
    # Pump outlet pressure [Pa]
    # The pump adds the pressure lost going through the coolant channels back
    pres_coolant_pump_outlet = pres_coolant_pump_inlet + dpres_coolant

    # If calculating for primary coolant
    if i_liquid_breeder == 1:
        # The pumping power is be calculated in the most general way,
        # using enthalpies before and after the pump.

        pump_outlet_fluid_properties = FluidProperties.of(
            fluid_name=CoolantType(i_coolant_type).full_name,
            temperature=temp_coolant_pump_outlet,
            pressure=pres_coolant_pump_outlet,
        )

        # Real gamma (cp/cv) at the pump outlet state, so liquid water (γ~1) # noqa: RUF003
        # and superheated steam (γ~1.3) are both handled correctly # noqa: RUF003
        gamma = (
            pump_outlet_fluid_properties.specific_heat_const_p
            / pump_outlet_fluid_properties.specific_heat_const_v
        )

        # Assume isentropic pump so that s1 = s2
        s1 = pump_outlet_fluid_properties.entropy

        # Get specific enthalpy at the outlet [J/kg] before pump using pressure and
        # entropy s1
        pump_inlet_fluid_properties = FluidProperties.of(
            fluid_name=CoolantType(i_coolant_type).full_name,
            pressure=pres_coolant_pump_inlet,
            entropy=s1,
        )

        # Pumping power [MW] is given by enthalpy change, with a correction for
        # the isentropic efficiency of the pump.
        fp = (
            temp_coolant_pump_outlet
            * (
                1
                - (pres_coolant_pump_outlet / pres_coolant_pump_inlet)
                ** -((gamma - 1) / gamma)
            )
            / (etaiso * (temp_coolant_pump_inlet - temp_coolant_pump_outlet))
        )
        pumppower = (
            1e-6
            * mflow_coolant_total
            * (
                pump_outlet_fluid_properties.enthalpy
                - pump_inlet_fluid_properties.enthalpy
            )
            / etaiso
        ) / (1 - fp)

    # If calculating for secondary coolant/breeder...
    else:
        # Calculate specific volume
        spec_vol = 1 / den_coolant

        # Liquid metal breeders (PbLi/Li) are incompressible, so there is no
        # gas-law reheat effect from compression: fp is negligible (gamma~1).
        fp = 0.0
        pumppower = (
            1e-6 * mflow_coolant_total * spec_vol * dpres_coolant / etaiso_liq
        ) / (1 - fp)

    # Error for dpres_coolant too large
    if fp >= 1:
        raise ProcessValueError("Pressure drops in coolant are too large to be feasible")

    return pumppower

gnielinski_heat_transfer_coefficient(mflux_coolant, den_coolant, radius_channel, heatcap_coolant, visc_coolant, thermcond_coolant, roughness_channel)

Calculate heat transfer coefficient using Gnielinski correlation.

Parameters:

Name Type Description Default
mflux_coolant float

Coolant mass flux in a single channel [kg/m²/s].

required
den_coolant float

Coolant density (average of inlet and outlet) [kg/m³].

required
radius_channel float

Coolant pipe radius [m].

required
heatcap_coolant float

Coolant specific heat capacity (average of inlet and outlet) [J/kg/K].

required
visc_coolant float

Coolant viscosity (average of inlet and outlet) [Pa.s].

required
thermcond_coolant float

Thermal conductivity of coolant (average of inlet and outlet) [W/m.K].

required
roughness_channel float

Roughness of the coolant channel [m].

required

Returns:

Type Description
float

Heat transfer coefficient [W/m²K].

Notes
  • Gnielinski correlation. Ignore the distinction between wall and bulk temperatures. Valid for: 3000 < Re < 5e6, 0.5 < Pr < 2000
References

[1] https://en.wikipedia.org/wiki/Nusselt_number#Gnielinski_correlation

Source code in process/models/engineering/pumping.py
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
def gnielinski_heat_transfer_coefficient(
    mflux_coolant: float,
    den_coolant: float,
    radius_channel: float,
    heatcap_coolant: float,
    visc_coolant: float,
    thermcond_coolant: float,
    roughness_channel: float,
) -> float:
    """Calculate heat transfer coefficient using Gnielinski correlation.

    Parameters
    ----------
    mflux_coolant:
        Coolant mass flux in a single channel [kg/m²/s].
    den_coolant:
        Coolant density (average of inlet and outlet) [kg/m³].
    radius_channel:
        Coolant pipe radius [m].
    heatcap_coolant:
        Coolant specific heat capacity (average of inlet and outlet) [J/kg/K].
    visc_coolant:
        Coolant viscosity (average of inlet and outlet) [Pa.s].
    thermcond_coolant:
        Thermal conductivity of coolant (average of inlet and outlet) [W/m.K].
    roughness_channel:
        Roughness of the coolant channel [m].

    Returns
    -------
    :
        Heat transfer coefficient [W/m²K].

    Notes
    -----
    - Gnielinski correlation. Ignore the distinction between wall and
    bulk temperatures. Valid for: 3000 < Re < 5e6, 0.5 < Pr < 2000

    References
    ----------
    [1] https://en.wikipedia.org/wiki/Nusselt_number#Gnielinski_correlation

    """
    # Calculate pipe diameter (m)
    diameter = 2 * radius_channel

    # Calculate flow velocity (m/s)
    vel_coolant = mflux_coolant / den_coolant

    # Calculate Reynolds number (Re)
    reynolds = calculate_reynolds_number(
        den_coolant=den_coolant,
        vel_coolant=vel_coolant,
        radius_channel=diameter / 2,
        visc_coolant=visc_coolant,
    )

    # Calculate Prandtl number (Pr)
    pr = heatcap_coolant * visc_coolant / thermcond_coolant

    # Calculate Darcy friction factor, using Haaland equation
    f = darcy_friction_haaland(
        reynolds=reynolds,
        roughness_channel=roughness_channel,
        dia_channel=2 * radius_channel,
    )

    # Calculate the Nusselt number (Nu)
    nusselt = (
        (f / 8.0)
        * (reynolds - 1000.0)
        * pr
        / (1 + 12.7 * np.sqrt(f / 8.0) * (pr ** (2 / 3) - 1.0))
    )

    # Calculate the heat transfer coefficient  [W/m²K]
    heat_transfer_coefficient = nusselt * thermcond_coolant / (2.0 * radius_channel)

    # Check that Reynolds number is in valid range for the Gnielinski correlation
    if (reynolds <= 3000.0) or (reynolds > 5.0e6):
        logger.error("Reynolds number out of range [3e3-5000e3]: %s", reynolds)

    # Check that Prandtl number is in valid range for the Gnielinski correlation
    if (pr < 0.5) or (pr > 2000.0):
        logger.error("Prandtl number out of range [0.5-2000]: %s", pr)

    # Check that the Darcy friction factor is in valid range for the Gnielinski
    # correlation
    if f <= 0.0:
        logger.error("Negative Darcy friction factor (f): %s", f)

    return heat_transfer_coefficient

calculate_reynolds_number(den_coolant, vel_coolant, radius_channel, visc_coolant)

Calculate Reynolds number (Re) for flow in a pipe.

Parameters:

Name Type Description Default
den_coolant float

Coolant density (average of inlet and outlet) [kg/m³].

required
vel_coolant float

Coolant velocity in a single channel [m/s].

required
radius_channel float

Coolant pipe radius [m].

required
visc_coolant float

Coolant viscosity (average of inlet and outlet) [Pa.s].

required

Returns:

Type Description
float

Reynolds number (Re).

Source code in process/models/engineering/pumping.py
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
def calculate_reynolds_number(
    den_coolant: float,
    vel_coolant: float,
    radius_channel: float,
    visc_coolant: float,
) -> float:
    """Calculate Reynolds number (Re) for flow in a pipe.

    Parameters
    ----------
    den_coolant:
        Coolant density (average of inlet and outlet) [kg/m³].
    vel_coolant:
        Coolant velocity in a single channel [m/s].
    radius_channel:
        Coolant pipe radius [m].
    visc_coolant:
        Coolant viscosity (average of inlet and outlet) [Pa.s].

    Returns
    -------
    :
        Reynolds number (Re).

    """
    # Calculate pipe diameter (m)
    diameter = 2 * radius_channel

    # Calculate Reynolds number
    return den_coolant * vel_coolant * diameter / visc_coolant

elbow_coeff(radius_pipe_elbow, deg_pipe_elbow, darcy_friction, dia_pipe)

Calculates elbow bend coefficients for pressure drop calculations.

Parameters:

Name Type Description Default
radius_pipe_elbow float

Pipe elbow radius [m].

required
deg_pipe_elbow float

Pipe elbow angle [degrees]

required
darcy_friction float

Darcy friction factor

required
dia_pipe float

Pipe diameter [m]

required

Returns:

Type Description
float

Elbow coefficient for pressure drop calculation

Raises:

Type Description
ProcessValueError

If deg_pipe_elbow is between 70 and 100 degrees, as no formula is available for this range.

References

[1] Idel'Cik, I. E. (1969), Memento des pertes de charge, Collection de la Direction des Etudes et Recherches d'Electricité de France.

Source code in process/models/engineering/pumping.py
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
def elbow_coeff(
    radius_pipe_elbow: float,
    deg_pipe_elbow: float,
    darcy_friction: float,
    dia_pipe: float,
) -> float:
    """Calculates elbow bend coefficients for pressure drop calculations.

    Parameters
    ----------
    radius_pipe_elbow : float
        Pipe elbow radius [m].
    deg_pipe_elbow : float
        Pipe elbow angle [degrees]
    darcy_friction : float
        Darcy friction factor
    dia_pipe : float
        Pipe diameter [m]

    Returns
    -------
    :float
        Elbow coefficient for pressure drop calculation

    Raises
    ------
    ProcessValueError
        If deg_pipe_elbow is between 70 and 100 degrees, as no formula is
        available for this range.

    References
    ----------
    [1] Idel'Cik, I. E. (1969), Memento des pertes de charge,
    Collection de la Direction des Etudes et Recherches d'Electricité de France.
    """
    if deg_pipe_elbow == 90:
        a = 1.0
    elif deg_pipe_elbow < 70:
        a = 0.9 * np.sin(deg_pipe_elbow * np.pi / 180.0)
    elif deg_pipe_elbow > 100:
        a = 0.7 + (0.35 * np.sin((deg_pipe_elbow / 90.0) * (np.pi / 180.0)))
    else:
        raise ProcessValueError(
            "No formula for 70 <= elbow angle(deg) <= 100, only 90 deg option available "
            "in this range."
        )

    r_ratio = radius_pipe_elbow / dia_pipe

    if r_ratio > 1:
        b = 0.21 / r_ratio**0.5
    elif r_ratio < 1:
        b = 0.21 / r_ratio**2.5
    else:
        b = 0.21

    # Singularity
    ximt = a * b

    # Friction
    xift = (
        (np.pi / 180.0)
        * darcy_friction
        * (radius_pipe_elbow / dia_pipe)
        * deg_pipe_elbow
    )

    # Elbow Coefficient
    return ximt + xift

calculate_required_mass_flow_rate(p_heat_total, heatcap_coolant, temp_in_coolant, temp_out_coolant)

Calculate the required mass flow rate of coolant to remove the specified heat load, due to the fundamental energy balance formula.

Parameters:

Name Type Description Default
p_heat_total float

Total heat load to be removed [W].

required
heatcap_coolant float

Specific heat capacity of the coolant [J/kg/K].

required
temp_in_coolant float

Inlet temperature of the coolant [K].

required
temp_out_coolant float

Outlet temperature of the coolant [K].

required

Returns:

Type Description
float

Required mass flow rate of the coolant [kg/s].

Notes
  • The heat capacity is assumed to be constant over the temperature range of the coolant.
Source code in process/models/engineering/pumping.py
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
def calculate_required_mass_flow_rate(
    p_heat_total: float,
    heatcap_coolant: float,
    temp_in_coolant: float,
    temp_out_coolant: float,
) -> float:
    """Calculate the required mass flow rate of coolant to remove the specified heat
    load, due to the fundamental energy balance formula.

    Parameters
    ----------
    p_heat_total:
        Total heat load to be removed [W].
    heatcap_coolant:
        Specific heat capacity of the coolant [J/kg/K].
    temp_in_coolant:
        Inlet temperature of the coolant [K].
    temp_out_coolant:
        Outlet temperature of the coolant [K].

    Returns
    -------
    :float
        Required mass flow rate of the coolant [kg/s].

    Notes
    -----
    - The heat capacity is assumed to be constant over the temperature range of the
    coolant.

    """
    return p_heat_total / (heatcap_coolant * (temp_out_coolant - temp_in_coolant))