Files
SystemSimulationApp/tests/test_amesim_helium_medium.py
T

260 lines
9.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import unittest
from app.main import ReactFlowProjectPayload, compile_reactflow_network
from app.simulation.components.amesim.library import LIBRARY
from app.simulation.components.amesim.media.mediums import (
AMESIM_AIR_PROPERTY_MODELS,
AMESIM_HELIUM_PENG_ROBINSON_PROPERTY_MODEL,
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
from tests.test_generic_system_xml_simulation import component_node
from tests.test_system_xml_protocol import physical_port
class AmesimHeliumPengRobinsonMediumTests(unittest.TestCase):
def test_uses_amesim_2404_peng_robinson_and_nasa_constants(
self,
) -> None:
medium = AmesimHeliumPengRobinsonMedium()
pressure = 15.3e6
temperature = 293.15
density = medium.density(pressure, temperature)
volume = 0.02
self.assertIs(medium.fluid, HELIUM_PR)
self.assertEqual(medium.SUBSTANCE_ID, "helium")
self.assertEqual(medium.PROPERTY_METHOD_ID, "peng_robinson")
self.assertAlmostEqual(medium.R_gas, HELIUM_PR.specific_gas_constant)
self.assertEqual(medium.cp_ref, 2.5 * medium.R_gas)
self.assertEqual(medium.cv, 1.5 * medium.R_gas)
self.assertEqual(medium.cp_at_temperature(400.0), 2.5 * medium.R_gas)
self.assertEqual(medium.cv_at_temperature(400.0), 1.5 * medium.R_gas)
self.assertAlmostEqual(medium.gamma, 5.0 / 3.0)
self.assertAlmostEqual(density, HELIUM_PR.density(pressure, temperature))
self.assertAlmostEqual(
medium.pressure(density * volume, temperature, volume),
pressure,
delta=pressure * 1.0e-12,
)
def test_nasa_caloric_reference_and_sutherland_viscosity_complete_contract(
self,
) -> None:
medium = AmesimHeliumPengRobinsonMedium()
temperature = 340.0
internal_energy = medium.specific_internal_energy(temperature)
enthalpy = medium.specific_enthalpy(temperature)
self.assertEqual(
internal_energy,
medium.R_gas * (1.5 * temperature - 745.375),
)
self.assertEqual(
enthalpy,
medium.R_gas * (2.5 * temperature - 745.375),
)
self.assertEqual(
medium.temperature_from_internal_energy(internal_energy),
temperature,
)
self.assertEqual(
medium.temperature_from_enthalpy(enthalpy),
temperature,
)
self.assertAlmostEqual(medium.dynamic_viscosity(293.15), 1.96e-5)
self.assertEqual(medium.sutherland_constant, 79.4)
def test_pressure_transport_enthalpy_includes_peng_robinson_departure(
self,
) -> None:
medium = AmesimHeliumPengRobinsonMedium()
pressure = 13_839_965.0
temperature = 287.7322
ideal_enthalpy = medium.specific_enthalpy(temperature)
transport_enthalpy = medium.specific_enthalpy_at_pressure(pressure, temperature)
self.assertGreater(
transport_enthalpy,
ideal_enthalpy,
)
self.assertAlmostEqual(
medium.temperature_from_pressure_enthalpy(pressure, transport_enthalpy),
temperature,
delta=1.0e-8,
)
medium.temperature_from_pressure_enthalpy.cache_clear()
first = medium.temperature_from_pressure_enthalpy(
pressure,
transport_enthalpy,
)
after_first = medium.temperature_from_pressure_enthalpy.cache_info()
second = medium.temperature_from_pressure_enthalpy(
pressure,
transport_enthalpy,
)
after_second = medium.temperature_from_pressure_enthalpy.cache_info()
self.assertEqual(second, first)
self.assertEqual(after_first.misses, 1)
self.assertEqual(after_second.hits, 1)
density = medium.density(pressure, temperature)
volume = 0.01
properties = medium.properties_from_mU(
density * volume,
density
* volume
* medium.specific_internal_energy_at_pressure(pressure, temperature),
volume,
)
self.assertAlmostEqual(properties.p, pressure, delta=pressure * 1.0e-10)
self.assertAlmostEqual(properties.T, temperature, delta=1.0e-8)
self.assertAlmostEqual(
properties.h,
transport_enthalpy,
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_exact_repeated_real_gas_state_recovery_is_cached(self) -> None:
medium = AmesimHeliumPengRobinsonMedium()
pressure = 15.3e6
temperature = 293.15
volume = 0.057
mass = medium.density(pressure, temperature) * volume
internal_energy = mass * medium.specific_internal_energy_at_pressure(
pressure,
temperature,
)
first = medium.properties_from_mU(mass, internal_energy, volume)
second = medium.properties_from_mU(mass, internal_energy, volume)
changed = medium.properties_from_mU(
mass,
internal_energy,
volume * 1.01,
)
self.assertIs(second, first)
self.assertIsNot(changed, first)
def test_amesim_2404_real_gas_isentropic_factor_reference(self) -> None:
medium = AmesimHeliumPengRobinsonMedium()
self.assertAlmostEqual(
medium.isentropic_density_pressure_factor(
15_201_996.778497815,
292.3997890954483,
405_072.8123335606,
),
0.5807873871273339,
delta=1.0e-12,
)
def test_definition_maps_local_selector_to_amesim_fluid_and_eos_codes(
self,
) -> None:
self.assertEqual(LIBRARY.version, "0.3.0")
self.assertEqual(AMESIM_HELIUM_PENG_ROBINSON_PROPERTY_MODEL, 0)
self.assertEqual(AMESIM_HELIUM_PROPERTY_MODELS[0].value, 0)
self.assertEqual(AMESIM_HELIUM_PROPERTY_MODELS[0].eos_type, 6)
self.assertEqual(AMESIM_AIR_PROPERTY_MODELS[0].eos_type, 1)
spec = COMPONENT_MODEL_REGISTRY["amesim_helium_medium"]
property_model = spec.parameter_by_name["property_model"]
self.assertEqual(spec.display.category_id, "media")
self.assertEqual(spec.display.role, "amesimGasMediumDefinition")
self.assertEqual(spec.display.label, "氦气介质定义")
self.assertEqual(spec.model_version, "0.1.0")
self.assertEqual(spec.ports, ())
self.assertEqual(property_model.default, 0.0)
self.assertEqual(property_model.editor, "amesimGasPropertyModel")
self.assertEqual(
[(option.value, option.label) for option in property_model.options],
[(0, "Peng–Robinson")],
)
component = spec.create(
"helium_properties",
IdealGasMedium(),
{"gi": 2.0, "property_model": 0.0},
)
definition = component.gas_definition()
self.assertEqual(component.parameter_values, {"gi": 2.0, "property_model": 0.0})
self.assertEqual(definition.label, "氦气(Peng–Robinson)")
self.assertEqual(definition.fluid_type, 12)
self.assertEqual(definition.eos_type, 6)
self.assertIsInstance(definition.medium, AmesimHeliumPengRobinsonMedium)
def test_project_compile_injects_helium_before_dynamic_state_initialization(
self,
) -> None:
pressure = 13_839_965.0
temperature = 287.7322
volume = 0.01
project = ReactFlowProjectPayload(
projectSchemaVersion=1,
name="helium-peng-robinson-compile",
nodes=[
component_node(
"helium_properties",
"amesim_helium_medium",
[],
{"gi": 2.0, "property_model": 0.0},
),
component_node(
"chamber_1",
"amesim_pnch023",
[
physical_port("port_1", "bidirectional", "left"),
physical_port("port_2", "bidirectional", "right"),
],
{
"gi": 2.0,
"cvol": volume,
"kth": 0.0,
"sth": 0.1,
"extemp": 293.15,
"p0": pressure,
"T0": temperature,
},
),
],
)
network = compile_reactflow_network(project)
chamber = network.components["chamber_1"]
self.assertNotIn("helium_properties", network.components)
self.assertIsInstance(chamber.medium, AmesimHeliumPengRobinsonMedium)
self.assertAlmostEqual(
chamber.state.m,
HELIUM_PR.density(pressure, temperature) * volume,
delta=1.0e-12,
)
if __name__ == "__main__":
unittest.main()