接入test_mql双管路气室与PN3节点

This commit is contained in:
huojiarong committed 2026-07-17 03:39:14 +00:00
1 parent 1193b2dcee
commit c4c1b35dee
5 files changed
+552

No files matched your search

+219
View File
@@ -119,6 +119,29 @@ class TestMqlPnl0001ChamberSegmentSnapshot:
outlet_flow: float
@dataclass(frozen=True)
class TestMqlPnl0001PairChamberSegmentComponents:
inlet_line: AmesimPnl0001Pipe
outlet_line: AmesimPnl0001Pipe
volume: AmesimPneumaticVolume
inlet_orifice: AmesimPneumaticOrifice
outlet_orifice: AmesimPneumaticOrifice
spec: TestMqlPneumaticChamberSegmentSpec
@dataclass(frozen=True)
class TestMqlPnl0001PairChamberSegmentSnapshot:
inlet_line: ThermodynamicProperties
chamber: ThermodynamicProperties
outlet_line: ThermodynamicProperties
inlet_node: ThermodynamicProperties
outlet_node: ThermodynamicProperties
inlet_node_to_line_flow: float
inlet_line_to_chamber_flow: float
outlet_node_to_line_flow: float
outlet_line_to_chamber_flow: float
@dataclass(frozen=True)
class TestMqlPneumaticBranchComponents:
name: str
@@ -555,3 +578,199 @@ class TestMqlPnl0001ChamberSegmentClosure:
internal_h=snapshot.chamber.h,
)
return [*line_derivative.as_vector(), *chamber_derivative.as_vector()]
class TestMqlPnl0001PairChamberSegmentClosure:
"""Six-state fixed chamber segment with both PNL0001 compliance states.
Generated C shows that both line instances receive ``t1/p1`` from their
PN3 nodes and send their explicit ``t2/p2`` states to the fixed orifices.
The reduced closure therefore prescribes node pressure/temperature at both
resistive port-1 boundaries while keeping both line storage states native.
"""
def __init__(
self,
*,
components: TestMqlPnl0001PairChamberSegmentComponents,
inlet_node: TestMqlPneumaticBoundaryCondition,
outlet_node: TestMqlPneumaticBoundaryCondition,
) -> None:
self.components = components
self.inlet_node = inlet_node
self.outlet_node = outlet_node
def initial_state_vector(self) -> list[float]:
return [
*self.components.inlet_line.get_state_vector(),
*self.components.volume.get_state_vector(),
*self.components.outlet_line.get_state_vector(),
]
def apply_state_vector(self, values: list[float]) -> None:
if len(values) != 6:
raise ValueError("PNL0001 pair/chamber state vector requires six values")
self.components.inlet_line.set_state_vector(values[:2])
self.components.volume.set_state_vector(values[2:4])
self.components.outlet_line.set_state_vector(values[4:])
def snapshot(
self,
state_vector: list[float] | None = None,
) -> TestMqlPnl0001PairChamberSegmentSnapshot:
if state_vector is not None:
self.apply_state_vector(state_vector)
inlet_line = self.components.inlet_line.properties()
chamber = self.components.volume.properties()
outlet_line = self.components.outlet_line.properties()
inlet_node = self.inlet_node.properties(self.components.inlet_line.gas)
outlet_node = self.outlet_node.properties(self.components.outlet_line.gas)
inlet_node_to_line_flow = self.components.inlet_line.resistance_mass_flow(
port_1_pressure_pa=inlet_node.p,
port_1_temperature_k=inlet_node.T,
)
outlet_node_to_line_flow = self.components.outlet_line.resistance_mass_flow(
port_1_pressure_pa=outlet_node.p,
port_1_temperature_k=outlet_node.T,
)
inlet_line_to_chamber_flow = self._line_to_chamber_flow(
line=inlet_line,
chamber=chamber,
orifice=self.components.inlet_orifice,
)
outlet_line_to_chamber_flow = self._line_to_chamber_flow(
line=outlet_line,
chamber=chamber,
orifice=self.components.outlet_orifice,
)
snapshot = TestMqlPnl0001PairChamberSegmentSnapshot(
inlet_line=inlet_line,
chamber=chamber,
outlet_line=outlet_line,
inlet_node=inlet_node,
outlet_node=outlet_node,
inlet_node_to_line_flow=inlet_node_to_line_flow,
inlet_line_to_chamber_flow=inlet_line_to_chamber_flow,
outlet_node_to_line_flow=outlet_node_to_line_flow,
outlet_line_to_chamber_flow=outlet_line_to_chamber_flow,
)
self._write_port_states(snapshot)
return snapshot
@staticmethod
def _line_to_chamber_flow(
*,
line: ThermodynamicProperties,
chamber: ThermodynamicProperties,
orifice: AmesimPneumaticOrifice,
) -> float:
upstream_temperature = line.T if line.p >= chamber.p else chamber.T
return orifice.mass_flow(line.p, chamber.p, upstream_temperature)
@staticmethod
def _port(
component: AmesimPneumaticVolume | AmesimPneumaticOrifice,
port_name: str,
) -> PortState:
return TestMqlPneumaticChamberSegmentClosure._port(component, port_name)
def _write_port_states(
self,
snapshot: TestMqlPnl0001PairChamberSegmentSnapshot,
) -> None:
spec = self.components.spec
chamber = self.components.volume
chamber_inlet_port = self._port(chamber, spec.volume_inlet_port)
chamber_outlet_port = self._port(chamber, spec.volume_outlet_port)
self._write_line_side(
line=self.components.inlet_line,
line_properties=snapshot.inlet_line,
node_properties=snapshot.inlet_node,
node_to_line_flow=snapshot.inlet_node_to_line_flow,
line_to_chamber_flow=snapshot.inlet_line_to_chamber_flow,
orifice=self.components.inlet_orifice,
orifice_boundary_port=spec.inlet_orifice_boundary_port,
orifice_volume_port=spec.inlet_orifice_volume_port,
chamber_port=chamber_inlet_port,
chamber_properties=snapshot.chamber,
)
self._write_line_side(
line=self.components.outlet_line,
line_properties=snapshot.outlet_line,
node_properties=snapshot.outlet_node,
node_to_line_flow=snapshot.outlet_node_to_line_flow,
line_to_chamber_flow=snapshot.outlet_line_to_chamber_flow,
orifice=self.components.outlet_orifice,
orifice_boundary_port=spec.outlet_orifice_boundary_port,
orifice_volume_port=spec.outlet_orifice_volume_port,
chamber_port=chamber_outlet_port,
chamber_properties=snapshot.chamber,
)
def _write_line_side(
self,
*,
line: AmesimPnl0001Pipe,
line_properties: ThermodynamicProperties,
node_properties: ThermodynamicProperties,
node_to_line_flow: float,
line_to_chamber_flow: float,
orifice: AmesimPneumaticOrifice,
orifice_boundary_port: str,
orifice_volume_port: str,
chamber_port: PortState,
chamber_properties: ThermodynamicProperties,
) -> None:
line.port_1.p = node_properties.p
line.port_1.m_flow = node_to_line_flow
line.port_1.h_outflow = line_properties.h
line.port_2.p = line_properties.p
line.port_2.m_flow = -line_to_chamber_flow
boundary_port = self._port(orifice, orifice_boundary_port)
volume_port = self._port(orifice, orifice_volume_port)
boundary_port.p = line_properties.p
boundary_port.m_flow = line_to_chamber_flow
boundary_port.h_outflow = line_properties.h
volume_port.p = chamber_properties.p
volume_port.m_flow = -line_to_chamber_flow
volume_port.h_outflow = chamber_properties.h
chamber_port.m_flow = line_to_chamber_flow
def rhs(self, state_vector: list[float]) -> list[float]:
snapshot = self.snapshot(state_vector)
inlet_derivative = self.components.inlet_line.derivatives_from_connections(
port_1_m_flow=snapshot.inlet_node_to_line_flow,
connected_h_1=snapshot.inlet_node.h,
port_2_m_flow=-snapshot.inlet_line_to_chamber_flow,
connected_h_2=snapshot.chamber.h,
)
outlet_derivative = self.components.outlet_line.derivatives_from_connections(
port_1_m_flow=snapshot.outlet_node_to_line_flow,
connected_h_1=snapshot.outlet_node.h,
port_2_m_flow=-snapshot.outlet_line_to_chamber_flow,
connected_h_2=snapshot.chamber.h,
)
chamber = self.components.volume
spec = self.components.spec
chamber_derivative = chamber.derivatives_from_two_connections(
port_a_m_flow=self._port(chamber, "port_1").m_flow,
connected_h_a=(
snapshot.inlet_line.h
if spec.volume_inlet_port == "port_1"
else snapshot.outlet_line.h
),
port_b_m_flow=self._port(chamber, "port_2").m_flow,
connected_h_b=(
snapshot.inlet_line.h
if spec.volume_inlet_port == "port_2"
else snapshot.outlet_line.h
),
internal_h=snapshot.chamber.h,
)
return [
*inlet_derivative.as_vector(),
*chamber_derivative.as_vector(),
*outlet_derivative.as_vector(),
]