STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_fittings_against_fluids.py
Go to the documentation of this file.
1"""Fitting adapters against the ``fluids`` functions they adapt.
2
3The module docstring of :mod:`feedtwin.comps.correlations` says every fitting is
4an adapter onto ``fluids`` and computes nothing of its own. These hold it to
5that: the K a fitting component prices must be the K ``fluids`` gives for the
6same geometry, in the units ``fluids`` documents.
7"""
8
9from __future__ import annotations
10
11import math
12
13import fluids.fittings as ft
14import pytest
15
16from feedtwin.comps import build_component, conditions_from_fluid
17from feedtwin.model import ComponentInstance, Param, Provenance
18from feedtwin.props import Fluid
19
20M = Provenance.MANUFACTURER
21BORE = 0.0095
22
23
24def _ethanol() -> object:
25 return conditions_from_fluid(Fluid("ethanol"), 4.0e6, 293.0)
26
27
28def _K(component: object, mdot: float, flow: object) -> float:
29 rho = flow.rho # type: ignore[attr-defined]
30 v = mdot / (rho * math.pi * BORE**2 / 4.0)
31 return component.pressure_drop(mdot, flow) / (0.5 * rho * v * v) # type: ignore[attr-defined]
32
33
34def _fitting(kind: str, **extra: Param) -> object:
35 params = {"bore": Param(BORE * 1e3, "mm", M, "test")}
36 params.update(extra)
37 return build_component(
38 ComponentInstance.build("F", "fitting", params, options={"kind": kind})
39 )
40
41
42@pytest.mark.parametrize("degrees", [45.0, 90.0, 180.0])
44 """``fluids.bend_rounded`` takes its angle in degrees.
45
46 The fitting's ``angle`` parameter is an *angle* dimension, so the model
47 layer hands it over in radians; passed straight through, a 90-degree bend
48 priced as a 1.57-degree one (K 0.018 against 0.229).
49 """
50 flow = _ethanol()
51 mdot = 1.0
52 bend = _fitting(
53 "bend",
54 angle=Param(degrees, "deg", M, "test"),
55 bend_diameters=Param(1.5, "-", M, "test"),
56 )
57 Re = 4.0 * mdot / (math.pi * BORE * flow.mu) # type: ignore[attr-defined]
58 expected = ft.bend_rounded(
59 Di=BORE, angle=degrees, bend_diameters=1.5, Re=Re, roughness=1.5e-6
60 )
61 assert _K(bend, mdot, flow) == pytest.approx(expected, rel=1e-9)
62
63
64@pytest.mark.parametrize("mdot", [0.05, 0.3, 1.0])
65@pytest.mark.parametrize("kind,n", [("elbow_90_crane", 30.0), ("elbow_45_crane", 16.0)])
67 kind: str, n: float, mdot: float
68) -> None:
69 """Crane TP-410 gives these as ``K = n . f_T``, f_T the fully turbulent
70 friction factor of the pipe size (fluids' ``ft_Crane``) -- not the line's
71 friction factor at its own Reynolds number, which put a 30 f_T elbow
72 anywhere from 0.55 to 1.09 against Crane's 0.885 in 9.5 mm."""
73 flow = _ethanol()
74 assert _K(_fitting(kind), mdot, flow) == pytest.approx(
75 n * ft.ft_Crane(BORE), rel=1e-12
76 )
77
78
79@pytest.mark.parametrize("kind,n", [("tee_run", 20.0), ("tee_branch", 60.0)])
80def test_an_unsplit_tee_is_cranes_f_T_multiple(kind: str, n: float) -> None:
81 """A segment's tee carries one flow and does not know the other leg's, so
82 it is Crane's unsplit tee: through the run 20 f_T, turning through the
83 branch 60 f_T. It used to read fluids' converging-tee correlations at a
84 split of 0.5/0.5 -- which is *all* the flow from the branch -- giving
85 0.41 for the branch (Crane 1.77) and 0.525 for a run carrying nothing."""
86 flow = _ethanol()
87 assert _K(_fitting(kind), 0.3, flow) == pytest.approx(
88 n * ft.ft_Crane(BORE), rel=1e-12
89 )
90
91
93 """Same geometry, two components, one correlation: one K."""
94 flow = _ethanol()
95 fitting = _fitting(
96 "bend",
97 angle=Param(90.0, "deg", M, "test"),
98 bend_diameters=Param(1.5, "-", M, "test"),
99 )
100 bend = build_component(
101 ComponentInstance.build(
102 "B",
103 "bend",
104 {
105 "bore": Param(BORE * 1e3, "mm", M, "test"),
106 "bend_radius": Param(1.5 * BORE * 1e3, "mm", M, "test"),
107 "angle": Param(90.0, "deg", M, "test"),
108 "roughness": Param(1.5e-6, "m", M, "test"),
109 },
110 model="rounded",
111 )
112 )
113 assert _K(fitting, 1.0, flow) == pytest.approx(_K(bend, 1.0, flow), rel=1e-9)
None test_a_bend_fitting_reads_its_angle_in_degrees(float degrees)
None test_an_unsplit_tee_is_cranes_f_T_multiple(str kind, float n)
object _fitting(str kind, **Param extra)
float _K(object component, float mdot, object flow)
None test_a_crane_multiple_is_of_the_fully_turbulent_f_T(str kind, float n, float mdot)