Files
SystemSimulationApp/tests/test_amesim_pnl00r_component.py
T

160 lines
6.0 KiB
Python

from __future__ import annotations
import unittest
from app.simulation.components.amesim.flow.pipes import AmesimPnl00r
from app.simulation.core.medium import IdealGasMedium
from app.simulation.registry import COMPONENT_MODEL_REGISTRY
class AmesimPnl00rComponentTests(unittest.TestCase):
def setUp(self) -> None:
self.medium = IdealGasMedium()
def test_default_create_preserves_amesim_parameter_contract(self) -> None:
pipe = COMPONENT_MODEL_REGISTRY["amesim_pnl00r"].create(
"pnl_1",
self.medium,
{},
)
self.assertIsInstance(pipe, AmesimPnl00r)
self.assertEqual(set(pipe.ports), {"port_1", "port_2"})
self.assertEqual(set(pipe.parameter_values), {"diam", "le", "rr", "gi"})
self.assertEqual(pipe.parameter_values["diam"], 0.01)
self.assertEqual(pipe.gi, 0)
def test_rejects_fractional_gas_index(self) -> None:
with self.assertRaisesRegex(ValueError, "gi must be an integer"):
COMPONENT_MODEL_REGISTRY["amesim_pnl00r"].create(
"pnl_1",
self.medium,
{"gi": 1.5},
)
def test_zero_pressure_drop_has_zero_flow_and_finite_results(self) -> None:
pipe = AmesimPnl00r("pnl_1", self.medium)
pipe.port_1.p = 100000.0
pipe.port_2.p = 100000.0
pipe.port_1.m_flow = 0.0
pipe.port_2.m_flow = 0.0
residuals = {
residual.id.rsplit(":", 1)[1]: residual
for residual in pipe.pressure_flow_equation_residuals()
}
self.assertEqual(pipe.mass_flow(100000.0, 100000.0), 0.0)
self.assertEqual(residuals["mass_flow_balance"].value, 0.0)
self.assertEqual(residuals["pressure_flow_relation"].value, 0.0)
self.assertEqual(set(pipe.component_result_values()), {"re", "cm", "v", "ff"})
def test_mass_flow_is_bidirectional_by_pressure_order(self) -> None:
pipe = AmesimPnl00r("pnl_1", self.medium, diam=0.014, le=1.0, rr=0.045 / 14.0)
forward = pipe.mass_flow(501000.0, 500000.0)
reverse = pipe.mass_flow(500000.0, 501000.0)
self.assertGreater(forward, 0.0)
self.assertLess(reverse, 0.0)
self.assertAlmostEqual(forward, -reverse, delta=abs(forward) * 0.02)
def test_mass_flow_is_continuous_across_former_relative_deadband(self) -> None:
pipe = AmesimPnl00r("pnl_1", self.medium, diam=0.014, le=1.0, rr=0.045 / 14.0)
base_pressure = 8.0e6
former_threshold = base_pressure * 1.0e-7
below = pipe.mass_flow(base_pressure + 0.99 * former_threshold, base_pressure)
above = pipe.mass_flow(base_pressure + 1.01 * former_threshold, base_pressure)
reverse = pipe.mass_flow(base_pressure, base_pressure + 0.99 * former_threshold)
self.assertGreater(below, 0.0)
self.assertGreater(above, below)
self.assertLess(reverse, 0.0)
self.assertAlmostEqual(below, -reverse, delta=abs(below) * 1.0e-9)
self.assertLess(abs(above - below), abs(above) * 0.05)
self.assertEqual(pipe.mass_flow(base_pressure, base_pressure), 0.0)
self.assertGreater(pipe.mass_flow(15.3e6 + 0.1, 15.3e6), 0.0)
def test_mass_flow_is_continuous_across_former_relative_deadband(self) -> None:
pipe = AmesimPnl00r("pnl_1", self.medium, diam=0.014, le=1.0, rr=0.045 / 14.0)
base_pressure = 8.0e6
former_threshold = base_pressure * 1.0e-7
below = pipe.mass_flow(base_pressure + 0.99 * former_threshold, base_pressure)
above = pipe.mass_flow(base_pressure + 1.01 * former_threshold, base_pressure)
reverse = pipe.mass_flow(base_pressure, base_pressure + 0.99 * former_threshold)
self.assertGreater(below, 0.0)
self.assertGreater(above, below)
self.assertLess(reverse, 0.0)
self.assertAlmostEqual(below, -reverse, delta=abs(below) * 1.0e-9)
self.assertLess(abs(above - below), abs(above) * 0.05)
self.assertEqual(pipe.mass_flow(base_pressure, base_pressure), 0.0)
def test_friction_factor_transitions_from_laminar_to_turbulent(self) -> None:
pipe = AmesimPnl00r("pnl_1", self.medium, rr=1e-5)
self.assertAlmostEqual(pipe.friction_factor(100.0), 64.0 / 100.0)
self.assertGreater(pipe.friction_factor(100000.0), 0.0)
self.assertLess(pipe.friction_factor(100000.0), 0.1)
def test_friction_factor_matches_amesim_smooth_to_rough_transition(self) -> None:
pipe_20mm = AmesimPnl00r(
"pnl_20mm",
self.medium,
diam=0.02,
rr=0.045 / 20.0,
)
pipe_14mm = AmesimPnl00r(
"pnl_14mm",
self.medium,
diam=0.014,
rr=0.045 / 14.0,
)
self.assertAlmostEqual(
pipe_20mm.friction_factor(56_887.5547),
0.0215740061043,
delta=1.0e-4,
)
self.assertAlmostEqual(
pipe_20mm.friction_factor(700_686.41),
0.02400535718,
delta=8.0e-5,
)
self.assertAlmostEqual(
pipe_14mm.friction_factor(726_799.66),
0.02658268645,
delta=8.0e-5,
)
def test_friction_factor_matches_amesim_transition_regime(self) -> None:
pipe = AmesimPnl00r(
"pnl_20mm",
self.medium,
diam=0.02,
rr=0.045 / 20.0,
)
self.assertAlmostEqual(
pipe.friction_factor(3_699.80236),
0.0391257647759,
delta=4.0e-4,
)
def test_darcy_pressure_drop_uses_flow_sign(self) -> None:
pipe = AmesimPnl00r("pnl_1", self.medium)
density = self.medium.density(500000.0, 300.0)
forward = pipe.darcy_pressure_drop(0.01, density=density, temperature=300.0)
reverse = pipe.darcy_pressure_drop(-0.01, density=density, temperature=300.0)
self.assertGreater(forward, 0.0)
self.assertLess(reverse, 0.0)
self.assertAlmostEqual(forward, -reverse)
if __name__ == "__main__":
unittest.main()