补充test_mql pneumatic_69局部参考RHS候选

This commit is contained in:
huojiarong committed 2026-07-29 09:23:05 +00:00
1 parent e17a952bee
commit 420bafeb4e
4 files changed
+185 -6

No files matched your search

@@ -784,6 +784,7 @@ class TestMqlFullStateComparisonExecutionConfig:
inlet_node_temperature_k: float = 293.15
resistance_boundary_temperature_k: float = 293.15
use_pneumatic_96_reference_rhs: bool = False
use_pneumatic_69_reference_rhs: bool = False
@dataclass(frozen=True)
@@ -827,6 +828,9 @@ def run_test_mql_full_state_comparison(
use_pneumatic_96_reference_rhs=(
config.execution.use_pneumatic_96_reference_rhs
),
use_pneumatic_69_reference_rhs=(
config.execution.use_pneumatic_69_reference_rhs
),
config=config.execution.solver,
t_eval=list(config.execution.t_eval) if config.execution.t_eval is not None else None,
data_paths=selected_paths,
@@ -844,6 +848,9 @@ def run_test_mql_full_state_comparison(
use_pneumatic_96_reference_rhs=(
config.execution.use_pneumatic_96_reference_rhs
),
use_pneumatic_69_reference_rhs=(
config.execution.use_pneumatic_69_reference_rhs
),
)
series_by_data_path = {
data_path: result.series[data_path]
@@ -923,6 +930,9 @@ def run_test_mql_pnvo_event_boundary_diagnostic(
"use_pneumatic_96_reference_rhs": (
config.execution.use_pneumatic_96_reference_rhs
),
"use_pneumatic_69_reference_rhs": (
config.execution.use_pneumatic_69_reference_rhs
),
}
solution = system.simulate_full_state_from_spec(
spec,
@@ -3290,6 +3300,9 @@ def run_test_mql_pnvo_event_window_diagnostic(
"use_pneumatic_96_reference_rhs": (
config.execution.use_pneumatic_96_reference_rhs
),
"use_pneumatic_69_reference_rhs": (
config.execution.use_pneumatic_69_reference_rhs
),
}
closure = system.full_state_closure_from_spec(spec, **closure_kwargs)
state_vector = closure.initial_state_vector()
@@ -4550,15 +4563,25 @@ def main() -> None:
action="store_true",
help="enable the local reference/mass-offset RHS candidate for pneumatic_96",
)
parser.add_argument(
"--pneumatic-69-reference-rhs",
action="store_true",
help="enable the local reference/mass-offset RHS candidate for pneumatic_69",
)
args = parser.parse_args()
config = None
if args.amesim_results_archive is not None or args.pneumatic_96_reference_rhs:
if (
args.amesim_results_archive is not None
or args.pneumatic_96_reference_rhs
or args.pneumatic_69_reference_rhs
):
config = TestMqlFullStateComparisonScriptConfig(
paths=TestMqlFullStateComparisonPathConfig(
amesim_results_archive_path=args.amesim_results_archive,
),
execution=TestMqlFullStateComparisonExecutionConfig(
use_pneumatic_96_reference_rhs=args.pneumatic_96_reference_rhs,
use_pneumatic_69_reference_rhs=args.pneumatic_69_reference_rhs,
),
)
if args.pnvo_event_boundary:
+12
View File
@@ -4803,6 +4803,7 @@ class TestMqlSystem:
inlet_node_temperature_k: float = 293.15,
resistance_boundary_temperature_k: float = 293.15,
use_pneumatic_96_reference_rhs: bool = False,
use_pneumatic_69_reference_rhs: bool = False,
) -> TestMqlFullStateClosure:
return TestMqlFullStateClosure(
pneumatic_closure=self.pn3_p4_node_chamber_segment_closure_from_spec(
@@ -4812,6 +4813,9 @@ class TestMqlSystem:
inlet_node_temperature_k=inlet_node_temperature_k,
resistance_boundary_temperature_k=resistance_boundary_temperature_k,
use_inlet_line_reference_rhs=use_pneumatic_96_reference_rhs,
use_p4_port3_remote_primary_reference_rhs=(
use_pneumatic_69_reference_rhs
),
),
mechanical_closure=self.mechanical_mass_closure(),
pneumatic_assembly=self.pneumatic_assembly,
@@ -4826,6 +4830,7 @@ class TestMqlSystem:
inlet_node_temperature_k: float = 293.15,
resistance_boundary_temperature_k: float = 293.15,
use_pneumatic_96_reference_rhs: bool = False,
use_pneumatic_69_reference_rhs: bool = False,
config: SolveIVPConfig | None = None,
t_eval: list[float] | None = None,
):
@@ -4836,6 +4841,7 @@ class TestMqlSystem:
inlet_node_temperature_k=inlet_node_temperature_k,
resistance_boundary_temperature_k=resistance_boundary_temperature_k,
use_pneumatic_96_reference_rhs=use_pneumatic_96_reference_rhs,
use_pneumatic_69_reference_rhs=use_pneumatic_69_reference_rhs,
)
return integrate_ode(
rhs=lambda t, state: closure.rhs_at(t, state),
@@ -4856,6 +4862,7 @@ class TestMqlSystem:
t_eval: list[float] | None = None,
data_paths: tuple[str, ...] | list[str] | None = None,
use_pneumatic_96_reference_rhs: bool = False,
use_pneumatic_69_reference_rhs: bool = False,
) -> TestMqlSimulationResult:
closure = self.full_state_closure_from_spec(
spec,
@@ -4864,6 +4871,7 @@ class TestMqlSystem:
inlet_node_temperature_k=inlet_node_temperature_k,
resistance_boundary_temperature_k=resistance_boundary_temperature_k,
use_pneumatic_96_reference_rhs=use_pneumatic_96_reference_rhs,
use_pneumatic_69_reference_rhs=use_pneumatic_69_reference_rhs,
)
solution = integrate_ode(
rhs=lambda t, state: closure.rhs_at(t, state),
@@ -5336,6 +5344,7 @@ class TestMqlSystem:
inlet_node_temperature_k: float = 293.15,
resistance_boundary_temperature_k: float = 293.15,
use_inlet_line_reference_rhs: bool = False,
use_p4_port3_remote_primary_reference_rhs: bool = False,
):
"""Close a PN3 chamber segment through the adjacent real P4 node.
@@ -6082,6 +6091,9 @@ class TestMqlSystem:
temperature_k=resistance_boundary_temperature_k,
),
use_inlet_line_reference_rhs=use_inlet_line_reference_rhs,
use_p4_port3_remote_primary_reference_rhs=(
use_p4_port3_remote_primary_reference_rhs
),
)
def simulate_pn3_p4_node_chamber_segment_from_spec(
+108 -5
View File
@@ -491,11 +491,15 @@ class TestMqlPn3P4NodeChamberSegmentClosure:
inlet_node: TestMqlPneumaticBoundaryCondition,
resistance_boundary: TestMqlPneumaticBoundaryCondition,
use_inlet_line_reference_rhs: bool = False,
use_p4_port3_remote_primary_reference_rhs: bool = False,
) -> None:
self.components = components
self.inlet_node = inlet_node
self.resistance_boundary = resistance_boundary
self.use_inlet_line_reference_rhs = use_inlet_line_reference_rhs
self.use_p4_port3_remote_primary_reference_rhs = (
use_p4_port3_remote_primary_reference_rhs
)
def initial_state_vector(self) -> list[float]:
return [
@@ -1937,6 +1941,69 @@ class TestMqlPn3P4NodeChamberSegmentClosure:
return fallback_h
return balance.port_2_enthalpy_flow_w / mass_flow_kg_s
@staticmethod
def _reference_enthalpy_flow_for_node_port(
*,
gas,
node_properties: ThermodynamicProperties,
connected_properties: ThermodynamicProperties,
flow_kg_s: float,
port_mass_flow_kg_s: float,
reference_temperature_k: float = 298.15,
) -> float:
stream_properties = (
node_properties if flow_kg_s >= 0.0 else connected_properties
)
return port_mass_flow_kg_s * gas.pressure_reference_enthalpy(
stream_properties.p,
stream_properties.T,
reference_temperature=reference_temperature_k,
)
def _p4_port3_remote_port_2_reference_h(
self,
*,
snapshot: TestMqlPn3P4NodeChamberSegmentSnapshot,
reference_temperature_k: float = 298.15,
) -> float:
gas = self.components.p4_port3_remote_primary_line.gas
port_2_mass_flow = snapshot.p4_port3_remote_balance.port_2_mass_flow_g_s * 1.0e-3
if abs(port_2_mass_flow) <= 1.0e-12:
return gas.pressure_reference_enthalpy(
snapshot.p4_port3_remote_primary_line.p,
snapshot.p4_port3_remote_primary_line.T,
reference_temperature=reference_temperature_k,
)
port_2_enthalpy_flow = sum(
(
self._reference_enthalpy_flow_for_node_port(
gas=gas,
node_properties=snapshot.p4_port3_remote_primary_line,
connected_properties=snapshot.p4_port3_line,
flow_kg_s=snapshot.p4_port3_remote_node_to_line_flow,
port_mass_flow_kg_s=-snapshot.p4_port3_remote_node_to_line_flow,
reference_temperature_k=reference_temperature_k,
),
self._reference_enthalpy_flow_for_node_port(
gas=gas,
node_properties=snapshot.p4_port3_remote_primary_line,
connected_properties=snapshot.p4_port3_remote_port3_line,
flow_kg_s=snapshot.p4_port3_remote_to_port3_line_flow,
port_mass_flow_kg_s=-snapshot.p4_port3_remote_to_port3_line_flow,
reference_temperature_k=reference_temperature_k,
),
self._reference_enthalpy_flow_for_node_port(
gas=gas,
node_properties=snapshot.p4_port3_remote_orifice_line_port_2,
connected_properties=snapshot.p4_port3_remote_primary_line,
flow_kg_s=snapshot.p4_port3_remote_orifice_to_node_flow,
port_mass_flow_kg_s=snapshot.p4_port3_remote_orifice_to_node_flow,
reference_temperature_k=reference_temperature_k,
),
)
)
return port_2_enthalpy_flow / port_2_mass_flow
def _p4_node_balance(
self,
*,
@@ -2097,25 +2164,42 @@ class TestMqlPn3P4NodeChamberSegmentClosure:
port_1_flow: float,
port_2_properties: ThermodynamicProperties,
port_2_flow: float,
port_1_connected_reference_h: float | None = None,
port_2_connected_reference_h: float | None = None,
reference_temperature_k: float = 298.15,
) -> VolumeState:
def reference_enthalpy_flow(
def specific_reference_h(
*,
port_flow: float,
connected: ThermodynamicProperties,
connected_reference_h: float | None,
) -> float:
if port_flow > 0.0 and connected_reference_h is not None:
return connected_reference_h
if port_flow > 0.0:
pressure = connected.p
temperature = connected.T
else:
pressure = line_properties.p
temperature = line_properties.T
return port_flow * line.gas.pressure_reference_enthalpy(
return line.gas.pressure_reference_enthalpy(
pressure,
temperature,
reference_temperature=reference_temperature_k,
)
def reference_enthalpy_flow(
*,
port_flow: float,
connected: ThermodynamicProperties,
connected_reference_h: float | None,
) -> float:
return port_flow * specific_reference_h(
port_flow=port_flow,
connected=connected,
connected_reference_h=connected_reference_h,
)
mass_derivative = port_1_flow + port_2_flow
heat_flow = (
line.heat_transfer_coefficient
@@ -2125,9 +2209,11 @@ class TestMqlPn3P4NodeChamberSegmentClosure:
enthalpy_flow = reference_enthalpy_flow(
port_flow=port_1_flow,
connected=port_1_properties,
connected_reference_h=port_1_connected_reference_h,
) + reference_enthalpy_flow(
port_flow=port_2_flow,
connected=port_2_properties,
connected_reference_h=port_2_connected_reference_h,
)
reference_offset_flow = (
line.gas.cp * reference_temperature_k - line.gas.cv * line_properties.T
@@ -2880,6 +2966,10 @@ class TestMqlPn3P4NodeChamberSegmentClosure:
port_2_properties=snapshot.p4_primary_line,
port_2_flow=snapshot.p4_to_port3_line_flow,
)
p4_port3_remote_node_connected_h = self._p4_node_port_2_connected_h(
balance=snapshot.p4_port3_remote_balance,
fallback_h=snapshot.p4_port3_remote_primary_line.h,
)
(
p4_port3_remote_primary_derivative,
p4_port3_remote_chamber_derivative,
@@ -2890,11 +2980,24 @@ class TestMqlPn3P4NodeChamberSegmentClosure:
chamber_properties=snapshot.p4_port3_remote_primary_chamber,
chamber_to_line_flow=snapshot.p4_port3_remote_chamber_to_line_flow,
node_to_line_flow=snapshot.p4_port3_remote_node_to_primary_line_flow,
node_connected_h=self._p4_node_port_2_connected_h(
balance=snapshot.p4_port3_remote_balance,
fallback_h=snapshot.p4_port3_remote_primary_line.h,
node_connected_h=p4_port3_remote_node_connected_h,
)
if self.use_p4_port3_remote_primary_reference_rhs:
p4_port3_remote_primary_derivative = (
self._pnl0001_reference_enthalpy_derivative(
line=self.components.p4_port3_remote_primary_line,
line_properties=snapshot.p4_port3_remote_primary_line,
port_1_properties=snapshot.p4_port3_remote_primary_chamber,
port_1_flow=snapshot.p4_port3_remote_chamber_to_line_flow,
port_2_properties=snapshot.p4_port3_remote_primary_line,
port_2_flow=snapshot.p4_port3_remote_node_to_primary_line_flow,
port_2_connected_reference_h=(
self._p4_port3_remote_port_2_reference_h(
snapshot=snapshot
)
),
)
)
p4_port3_remote_port3_derivative = self._connection_line_derivative(
line=self.components.p4_port3_remote_port3_line,
port_1_properties=snapshot.p4_port3_far_primary_line,
+41
View File
@@ -778,6 +778,47 @@ class TestMqlPn3P4NodeChamberSegmentTests(unittest.TestCase):
self.assertAlmostEqual(candidate_rhs[1], expected.U)
self.assertNotAlmostEqual(candidate_rhs[1], default_rhs[1])
def test_full_state_closure_can_enable_pneumatic_69_reference_rhs_candidate(
self,
) -> None:
default_closure = self.system.full_state_closure_from_spec(
self.spec,
inlet_node_pressure_pa=15.31e6,
resistance_boundary_pressure_pa=15.29e6,
)
candidate_closure = self.system.full_state_closure_from_spec(
self.spec,
inlet_node_pressure_pa=15.31e6,
resistance_boundary_pressure_pa=15.29e6,
use_pneumatic_69_reference_rhs=True,
)
state = default_closure.initial_state_vector()
default_rhs = default_closure.rhs_at(0.04, state)
candidate_rhs = candidate_closure.rhs_at(0.04, state)
snapshot = candidate_closure.snapshot_at(0.04, state).pneumatic
line = candidate_closure.pneumatic_closure.components.p4_port3_remote_primary_line
expected = candidate_closure.pneumatic_closure._pnl0001_reference_enthalpy_derivative(
line=line,
line_properties=snapshot.p4_port3_remote_primary_line,
port_1_properties=snapshot.p4_port3_remote_primary_chamber,
port_1_flow=snapshot.p4_port3_remote_chamber_to_line_flow,
port_2_properties=snapshot.p4_port3_remote_primary_line,
port_2_flow=snapshot.p4_port3_remote_node_to_primary_line_flow,
port_2_connected_reference_h=(
candidate_closure.pneumatic_closure._p4_port3_remote_port_2_reference_h(
snapshot=snapshot
)
),
)
self.assertAlmostEqual(candidate_rhs[0], default_rhs[0])
self.assertAlmostEqual(candidate_rhs[1], default_rhs[1])
self.assertAlmostEqual(candidate_rhs[44], default_rhs[44])
self.assertAlmostEqual(candidate_rhs[44], expected.m)
self.assertAlmostEqual(candidate_rhs[45], expected.U)
self.assertNotAlmostEqual(candidate_rhs[45], default_rhs[45])
def test_full_state_closure_applies_step_controls_to_variable_orifices(self) -> None:
closure = self.system.full_state_closure_from_spec(
self.spec,