对齐AMESim管阻孔口与储气耦合
This commit is contained in:
1 parent
7671418582
commit
6abcc220de
14 files changed
+817
-65
No files matched your search
@@ -10,6 +10,7 @@ from app.simulation.components.amesim.media.mediums import (
|
||||
AMESIM_HELIUM_PROPERTY_MODELS,
|
||||
AmesimHeliumPengRobinsonMedium,
|
||||
)
|
||||
from app.simulation.core.errors import RecoverableTrialStateError
|
||||
from app.simulation.core.medium import IdealGasMedium
|
||||
from app.simulation.core.peng_robinson import HELIUM_PR
|
||||
from app.simulation.registry import COMPONENT_MODEL_REGISTRY
|
||||
@@ -109,6 +110,16 @@ class AmesimHeliumPengRobinsonMediumTests(unittest.TestCase):
|
||||
delta=2.0e-8,
|
||||
)
|
||||
|
||||
def test_negative_mass_is_a_recoverable_integrator_trial_state(self) -> None:
|
||||
media = (IdealGasMedium(), AmesimHeliumPengRobinsonMedium())
|
||||
|
||||
for medium in media:
|
||||
with self.subTest(medium=medium.name):
|
||||
with self.assertRaises(RecoverableTrialStateError):
|
||||
medium.temperature_from_mass_internal_energy(-1.0, 1.0)
|
||||
with self.assertRaises(RecoverableTrialStateError):
|
||||
medium.properties_from_mU(-1.0, 1.0, 1.0)
|
||||
|
||||
def test_amesim_2404_real_gas_isentropic_factor_reference(self) -> None:
|
||||
medium = AmesimHeliumPengRobinsonMedium()
|
||||
|
||||
|
||||
@@ -88,6 +88,20 @@ class AmesimPnl0001ComponentTests(unittest.TestCase):
|
||||
self.assertLess(reverse, 0.0)
|
||||
self.assertAlmostEqual(abs(forward), abs(reverse), delta=abs(forward) * 0.02)
|
||||
|
||||
def test_high_pressure_near_equal_flow_is_continuous_outside_roundoff(self) -> None:
|
||||
pipe = AmesimPnl0001("pnl_1", self.medium, p0=15.3e6)
|
||||
|
||||
small = pipe.mass_flow(15.3e6 + 0.1, 15.3e6, 293.15)
|
||||
larger = pipe.mass_flow(15.3e6 + 1.0, 15.3e6, 293.15)
|
||||
|
||||
self.assertGreater(small, 0.0)
|
||||
self.assertGreater(larger, small)
|
||||
|
||||
def test_pressure_roundoff_does_not_create_a_fictitious_flow(self) -> None:
|
||||
pipe = AmesimPnl0001("pnl_1", self.medium, p0=15.3e6)
|
||||
|
||||
self.assertEqual(pipe.mass_flow(15.3e6, 15.3e6 + 2.0e-9, 293.15), 0.0)
|
||||
|
||||
def test_pressure_flow_residuals_do_not_force_storage_mass_balance(self) -> None:
|
||||
pipe = AmesimPnl0001("pnl_1", self.medium)
|
||||
pipe.port_1.p = 101000.0
|
||||
|
||||
@@ -62,6 +62,17 @@ class AmesimPnor001ComponentTests(unittest.TestCase):
|
||||
self.assertLess(reverse, 0.0)
|
||||
self.assertAlmostEqual(forward, -reverse)
|
||||
|
||||
def test_high_pressure_near_equal_flow_is_continuous(self) -> None:
|
||||
orifice = AmesimPnor001("pnor_1", self.medium)
|
||||
orifice.port_1.p = 15.3e6
|
||||
orifice.port_2.p = 15.3e6
|
||||
|
||||
small = orifice.mass_flow(15.3e6 + 0.1, 15.3e6)
|
||||
larger = orifice.mass_flow(15.3e6 + 1.0, 15.3e6)
|
||||
|
||||
self.assertGreater(small, 0.0)
|
||||
self.assertGreater(larger, small)
|
||||
|
||||
def test_cv_and_kv_modes_produce_positive_equivalent_area(self) -> None:
|
||||
cv_orifice = AmesimPnor001(
|
||||
"pnor_cv",
|
||||
|
||||
@@ -421,7 +421,10 @@ class ComponentCatalogTests(unittest.TestCase):
|
||||
with self.subTest(model_type=model_type):
|
||||
component = self.components[model_type]
|
||||
model_parameters = parameters(model_type)
|
||||
self.assertEqual(component["modelVersion"], "0.2.0")
|
||||
self.assertEqual(
|
||||
component["modelVersion"],
|
||||
"0.3.0" if model_type == "amesim_pnor001" else "0.2.0",
|
||||
)
|
||||
self.assertEqual(model_parameters["flowset"]["editor"], "choice")
|
||||
self.assertEqual(model_parameters["flowset"]["options"], flow_options)
|
||||
self.assertEqual(
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from app.simulation.components.amesim.boundary.sources import AmesimPnpl01
|
||||
from app.simulation.components.amesim.flow.pipes import AmesimPnl0001, AmesimPnl0003
|
||||
from app.simulation.core.medium import IdealGasMedium
|
||||
from app.simulation.solvers.solver import SolveIVPConfig
|
||||
from app.simulation.systems.generic import GenericFluidSystem, simulation_preparation_issues
|
||||
from app.simulation.systems.network import SimulationNetwork
|
||||
|
||||
|
||||
class IdealPneumaticStorageCouplingTests(unittest.TestCase):
|
||||
def build_network(self) -> SimulationNetwork:
|
||||
medium = IdealGasMedium()
|
||||
network = SimulationNetwork("ideal-pipe-compliance-coupling")
|
||||
for component in (
|
||||
AmesimPnpl01("closed_1"),
|
||||
AmesimPnl0001("pnl0001", medium, p0=15.3e6, T0=293.15),
|
||||
AmesimPnl0003(
|
||||
"pnl0003",
|
||||
medium,
|
||||
p1_0=15.3e6,
|
||||
T1_0=293.15,
|
||||
p2_0=15.3e6,
|
||||
T2_0=293.15,
|
||||
),
|
||||
AmesimPnpl01("closed_2"),
|
||||
):
|
||||
network.add_component(component)
|
||||
network.connect("closed_1", "port_1", "pnl0001", "port_1")
|
||||
network.connect("pnl0001", "port_2", "pnl0003", "port_1")
|
||||
network.connect("pnl0003", "port_2", "closed_2", "port_1")
|
||||
return network
|
||||
|
||||
def test_supported_amesim_pipe_compliances_are_not_rejected(self) -> None:
|
||||
issues = simulation_preparation_issues(self.build_network())
|
||||
|
||||
self.assertNotIn(
|
||||
"IDEAL_STORAGE_COUPLING_UNSUPPORTED",
|
||||
{issue.code for issue in issues},
|
||||
)
|
||||
|
||||
def test_coupled_pipe_compliances_run_without_fictitious_resistance(self) -> None:
|
||||
system = GenericFluidSystem(self.build_network())
|
||||
|
||||
result = system.simulate(
|
||||
SolveIVPConfig(t_stop=0.001, method="BDF", max_step=0.0002),
|
||||
sample_step=0.001,
|
||||
)
|
||||
|
||||
self.assertTrue(result.success)
|
||||
self.assertAlmostEqual(result.final["pnl0001.p"], 15.3e6, delta=1.0e-4)
|
||||
self.assertAlmostEqual(result.final["pnl0003.p1"], 15.3e6, delta=1.0e-4)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -6,11 +6,15 @@ from unittest.mock import patch
|
||||
|
||||
from app.simulation.components.amesim.boundary.sources import AmesimPnpl01
|
||||
from app.simulation.components.amesim.flow.orifices import (
|
||||
AmesimPnor001,
|
||||
AmesimPnvo001SignalOpening,
|
||||
)
|
||||
from app.simulation.components.amesim.flow.pipes import AmesimPnl00r
|
||||
from app.simulation.components.amesim.flow.pipes import AmesimPnl0001
|
||||
from app.simulation.components.amesim.media.mediums import (
|
||||
AmesimHeliumPengRobinsonMedium,
|
||||
)
|
||||
from app.simulation.components.amesim.storage.chambers import AmesimPnch023
|
||||
from app.simulation.components.experimental.storage.cylinder import Cylinder
|
||||
from app.simulation.components.experimental.storage.tank import Tank
|
||||
from app.simulation.core.medium import IdealGasMedium
|
||||
@@ -21,6 +25,50 @@ from app.simulation.systems.network import SimulationNetwork
|
||||
|
||||
|
||||
class PressureFlowSolverInitializationTests(unittest.TestCase):
|
||||
def test_pnor_pnl0001_series_pressure_is_seeded_by_flow_balance(self) -> None:
|
||||
medium = IdealGasMedium()
|
||||
chamber = AmesimPnch023("source", medium, p0=15.3e6)
|
||||
source_plug = AmesimPnpl01("source_closed")
|
||||
orifice = AmesimPnor001("orifice", medium)
|
||||
pipe = AmesimPnl0001("pipe", medium, p0=14.0e6)
|
||||
storage_plug = AmesimPnpl01("storage_closed")
|
||||
network = SimulationNetwork("pnor-pnl0001-series")
|
||||
for component in (chamber, source_plug, orifice, pipe, storage_plug):
|
||||
network.add_component(component)
|
||||
network.connect("source_closed", "port_1", "source", "port_1")
|
||||
network.connect("source", "port_2", "orifice", "port_1")
|
||||
network.connect("orifice", "port_2", "pipe", "port_1")
|
||||
network.connect("pipe", "port_2", "storage_closed", "port_1")
|
||||
chamber.refresh_thermodynamic_ports()
|
||||
pipe.refresh_thermodynamic_ports()
|
||||
|
||||
result = PressureFlowSolver(network).solve()
|
||||
|
||||
self.assertTrue(result.success)
|
||||
self.assertGreater(orifice.port_2.p, pipe.port_2.p)
|
||||
self.assertLess(orifice.port_2.p, chamber.port_2.p)
|
||||
self.assertAlmostEqual(orifice.port_2.p, pipe.port_1.p)
|
||||
self.assertAlmostEqual(-orifice.port_2.m_flow, pipe.port_1.m_flow)
|
||||
|
||||
def test_dead_ended_pnl00r_is_seeded_at_zero_flow_pressure(self) -> None:
|
||||
medium = IdealGasMedium()
|
||||
pipe = AmesimPnl00r("resistance", medium)
|
||||
plug = AmesimPnpl01("closed")
|
||||
pipe.port_1.p = 15.3e6
|
||||
pipe.port_2.p = 100_000.0
|
||||
network = SimulationNetwork("dead-ended-resistance")
|
||||
network.add_component(pipe)
|
||||
network.add_component(plug)
|
||||
network.connect("resistance", "port_2", "closed", "port_1")
|
||||
|
||||
result = PressureFlowSolver(network).solve()
|
||||
|
||||
self.assertTrue(result.success)
|
||||
self.assertEqual(result.evaluations, 0)
|
||||
self.assertAlmostEqual(pipe.port_2.p, pipe.port_1.p)
|
||||
self.assertEqual(pipe.port_1.m_flow, 0.0)
|
||||
self.assertEqual(pipe.port_2.m_flow, 0.0)
|
||||
|
||||
@staticmethod
|
||||
def _near_equal_pressure_network() -> tuple[
|
||||
SimulationNetwork,
|
||||
|
||||
Reference in new issue
Block a user