接入test_mql真实固定气室拓扑
This commit is contained in:
1 parent
c0f28520b4
commit
2d33a8f4bc
8 files changed
+747
-5
No files matched your search
@@ -4,10 +4,12 @@ from dataclasses import dataclass
|
||||
from typing import Callable
|
||||
|
||||
from PythonModels.components.amesim_pneumatic import (
|
||||
AmesimPneumaticGas,
|
||||
AmesimPneumaticOrifice,
|
||||
AmesimPneumaticVolume,
|
||||
)
|
||||
from PythonModels.core.medium import ThermodynamicProperties
|
||||
from PythonModels.core.ports import PortState
|
||||
from PythonModels.core.state import VolumeState
|
||||
|
||||
|
||||
@@ -30,15 +32,72 @@ class TestMqlPneumaticTopologyCandidate:
|
||||
target_port: str
|
||||
source_is_typed_pneumatic: bool
|
||||
target_is_typed_pneumatic: bool
|
||||
category: str
|
||||
reason: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlPneumaticChamberSegmentSpec:
|
||||
name: str
|
||||
inlet_node_alias: str
|
||||
inlet_line_alias: str
|
||||
inlet_orifice_alias: str
|
||||
inlet_orifice_boundary_port: str
|
||||
inlet_orifice_volume_port: str
|
||||
volume_alias: str
|
||||
volume_inlet_port: str
|
||||
volume_outlet_port: str
|
||||
outlet_orifice_alias: str
|
||||
outlet_orifice_volume_port: str
|
||||
outlet_orifice_boundary_port: str
|
||||
outlet_line_alias: str
|
||||
outlet_node_alias: str
|
||||
source: str = "amesim-cir-topology"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlPneumaticTopologyDiscovery:
|
||||
branch_specs: tuple[TestMqlPneumaticBranchSpec, ...]
|
||||
chamber_segment_specs: tuple[TestMqlPneumaticChamberSegmentSpec, ...]
|
||||
blocked_candidates: tuple[TestMqlPneumaticTopologyCandidate, ...]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlPneumaticBoundaryCondition:
|
||||
pressure_pa: float
|
||||
temperature_k: float
|
||||
|
||||
def properties(self, gas: AmesimPneumaticGas) -> ThermodynamicProperties:
|
||||
if self.pressure_pa <= 0.0:
|
||||
raise ValueError("boundary pressure must be positive")
|
||||
if self.temperature_k <= 0.0:
|
||||
raise ValueError("boundary temperature must be positive")
|
||||
return ThermodynamicProperties(
|
||||
p=self.pressure_pa,
|
||||
T=self.temperature_k,
|
||||
rho=gas.density(self.pressure_pa, self.temperature_k),
|
||||
u=gas.specific_internal_energy(self.temperature_k),
|
||||
h=gas.specific_enthalpy(self.temperature_k),
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlPneumaticChamberSegmentComponents:
|
||||
volume: AmesimPneumaticVolume
|
||||
inlet_orifice: AmesimPneumaticOrifice
|
||||
outlet_orifice: AmesimPneumaticOrifice
|
||||
spec: TestMqlPneumaticChamberSegmentSpec
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlPneumaticChamberSegmentSnapshot:
|
||||
chamber: ThermodynamicProperties
|
||||
inlet_boundary: ThermodynamicProperties
|
||||
outlet_boundary: ThermodynamicProperties
|
||||
inlet_flow: float
|
||||
outlet_flow: float
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlPneumaticBranchComponents:
|
||||
name: str
|
||||
@@ -184,3 +243,139 @@ class TestMqlPneumaticClosure:
|
||||
*upstream_derivative.as_vector(),
|
||||
*downstream_derivative.as_vector(),
|
||||
]
|
||||
|
||||
|
||||
class TestMqlPneumaticChamberSegmentClosure:
|
||||
"""Boundary-reduced fixed chamber segment discovered from AMESim topology.
|
||||
|
||||
The two PNL0001 lines remain prescribed boundary interfaces in this first
|
||||
closure. Their aliases are retained in the spec so line dynamics can be
|
||||
inserted later without rediscovering the component path.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
components: TestMqlPneumaticChamberSegmentComponents,
|
||||
inlet_boundary: TestMqlPneumaticBoundaryCondition,
|
||||
outlet_boundary: TestMqlPneumaticBoundaryCondition,
|
||||
) -> None:
|
||||
self.components = components
|
||||
self.inlet_boundary = inlet_boundary
|
||||
self.outlet_boundary = outlet_boundary
|
||||
|
||||
def initial_state_vector(self) -> list[float]:
|
||||
return self.components.volume.get_state_vector()
|
||||
|
||||
def apply_state_vector(self, values: list[float]) -> None:
|
||||
if len(values) != 2:
|
||||
raise ValueError("single-chamber segment state vector requires two values")
|
||||
self.components.volume.set_state_vector(values)
|
||||
|
||||
def snapshot(
|
||||
self,
|
||||
state_vector: list[float] | None = None,
|
||||
) -> TestMqlPneumaticChamberSegmentSnapshot:
|
||||
if state_vector is not None:
|
||||
self.apply_state_vector(state_vector)
|
||||
chamber = self.components.volume.properties()
|
||||
inlet_boundary = self.inlet_boundary.properties(self.components.volume.gas)
|
||||
outlet_boundary = self.outlet_boundary.properties(self.components.volume.gas)
|
||||
inlet_temperature = (
|
||||
inlet_boundary.T if inlet_boundary.p >= chamber.p else chamber.T
|
||||
)
|
||||
outlet_temperature = (
|
||||
chamber.T if chamber.p >= outlet_boundary.p else outlet_boundary.T
|
||||
)
|
||||
inlet_flow = self.components.inlet_orifice.mass_flow(
|
||||
inlet_boundary.p,
|
||||
chamber.p,
|
||||
inlet_temperature,
|
||||
)
|
||||
outlet_flow = self.components.outlet_orifice.mass_flow(
|
||||
chamber.p,
|
||||
outlet_boundary.p,
|
||||
outlet_temperature,
|
||||
)
|
||||
snapshot = TestMqlPneumaticChamberSegmentSnapshot(
|
||||
chamber=chamber,
|
||||
inlet_boundary=inlet_boundary,
|
||||
outlet_boundary=outlet_boundary,
|
||||
inlet_flow=inlet_flow,
|
||||
outlet_flow=outlet_flow,
|
||||
)
|
||||
self._write_port_states(snapshot)
|
||||
return snapshot
|
||||
|
||||
@staticmethod
|
||||
def _port(
|
||||
component: AmesimPneumaticVolume | AmesimPneumaticOrifice,
|
||||
port_name: str,
|
||||
) -> PortState:
|
||||
if port_name == "port_1":
|
||||
return component.port_a
|
||||
if port_name == "port_2":
|
||||
return component.port_b
|
||||
raise ValueError(f"unsupported pneumatic port: {port_name}")
|
||||
|
||||
def _write_port_states(
|
||||
self,
|
||||
snapshot: TestMqlPneumaticChamberSegmentSnapshot,
|
||||
) -> None:
|
||||
spec = self.components.spec
|
||||
chamber = self.components.volume
|
||||
inlet_orifice = self.components.inlet_orifice
|
||||
outlet_orifice = self.components.outlet_orifice
|
||||
|
||||
inlet_boundary_port = self._port(
|
||||
inlet_orifice,
|
||||
spec.inlet_orifice_boundary_port,
|
||||
)
|
||||
inlet_volume_port = self._port(inlet_orifice, spec.inlet_orifice_volume_port)
|
||||
inlet_boundary_port.p = snapshot.inlet_boundary.p
|
||||
inlet_boundary_port.m_flow = snapshot.inlet_flow
|
||||
inlet_boundary_port.h_outflow = snapshot.inlet_boundary.h
|
||||
inlet_volume_port.p = snapshot.chamber.p
|
||||
inlet_volume_port.m_flow = -snapshot.inlet_flow
|
||||
inlet_volume_port.h_outflow = snapshot.chamber.h
|
||||
|
||||
chamber_inlet_port = self._port(chamber, spec.volume_inlet_port)
|
||||
chamber_outlet_port = self._port(chamber, spec.volume_outlet_port)
|
||||
chamber_inlet_port.m_flow = snapshot.inlet_flow
|
||||
chamber_outlet_port.m_flow = -snapshot.outlet_flow
|
||||
|
||||
outlet_volume_port = self._port(
|
||||
outlet_orifice,
|
||||
spec.outlet_orifice_volume_port,
|
||||
)
|
||||
outlet_boundary_port = self._port(
|
||||
outlet_orifice,
|
||||
spec.outlet_orifice_boundary_port,
|
||||
)
|
||||
outlet_volume_port.p = snapshot.chamber.p
|
||||
outlet_volume_port.m_flow = snapshot.outlet_flow
|
||||
outlet_volume_port.h_outflow = snapshot.chamber.h
|
||||
outlet_boundary_port.p = snapshot.outlet_boundary.p
|
||||
outlet_boundary_port.m_flow = -snapshot.outlet_flow
|
||||
outlet_boundary_port.h_outflow = snapshot.outlet_boundary.h
|
||||
|
||||
def rhs(self, state_vector: list[float]) -> list[float]:
|
||||
snapshot = self.snapshot(state_vector)
|
||||
spec = self.components.spec
|
||||
chamber = self.components.volume
|
||||
derivative = chamber.derivatives_from_two_connections(
|
||||
port_a_m_flow=self._port(chamber, "port_1").m_flow,
|
||||
connected_h_a=(
|
||||
snapshot.inlet_boundary.h
|
||||
if spec.volume_inlet_port == "port_1"
|
||||
else snapshot.outlet_boundary.h
|
||||
),
|
||||
port_b_m_flow=self._port(chamber, "port_2").m_flow,
|
||||
connected_h_b=(
|
||||
snapshot.inlet_boundary.h
|
||||
if spec.volume_inlet_port == "port_2"
|
||||
else snapshot.outlet_boundary.h
|
||||
),
|
||||
internal_h=snapshot.chamber.h,
|
||||
)
|
||||
return derivative.as_vector()
|
||||
Reference in new issue
Block a user