对齐AMESim管阻孔口与储气耦合

This commit is contained in:
huojiarong committed 2026-08-10 13:07:03 +00:00
1 parent 7671418582
commit 6abcc220de
14 files changed
+817 -65

No files matched your search

+11
View File
@@ -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()
+14
View File
@@ -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
+11
View File
@@ -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",
+4 -1
View File
@@ -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,