657 lines
33 KiB
Python
657 lines
33 KiB
Python
from __future__ import annotations
|
|
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from PythonModels.core.solver import SolveIVPConfig
|
|
from PythonModels.systems.test_mql import TestMqlPnl0001LineRhsDiagnostic
|
|
|
|
from PythonModels.scripts.run_test_mql_full_state_comparison import (
|
|
TestMqlFullStateComparisonExecutionConfig,
|
|
TestMqlFullStateComparisonPathConfig,
|
|
TestMqlFullStateComparisonScriptConfig,
|
|
TestMqlPnl0001EnergyFlowDiagnostic,
|
|
TestMqlP4NodeEnthalpyBreakdownDiagnostic,
|
|
TestMqlPnl0003EnergyDiagnostic,
|
|
TestMqlPnch012EnergyEquationDiagnostic,
|
|
TestMqlPnvoUpstreamEnthalpyDiagnostic,
|
|
TestMqlPnl0001PressureLossCalibrationDiagnostic,
|
|
TestMqlPnvoEventBoundaryDiagnostic,
|
|
TestMqlPnvoEventWindowDiagnostic,
|
|
TestMqlPnvoEventWindowSampleDiagnostic,
|
|
TestMqlPnvoFlowParameterDiagnostic,
|
|
TestMqlPnvoEventWindowSegmentDiagnostic,
|
|
format_test_mql_full_state_comparison_summary,
|
|
format_test_mql_pnvo_event_boundary_summary,
|
|
format_test_mql_pnvo_event_window_summary,
|
|
run_test_mql_full_state_comparison,
|
|
_series_sample_bracket,
|
|
)
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
TEST_MQL_AME = REPO_ROOT / "AmesimModels" / "test_mql.ame"
|
|
|
|
|
|
class RunTestMqlFullStateComparisonScriptTests(unittest.TestCase):
|
|
def test_series_sample_bracket_distinguishes_exact_and_interpolated_times(self) -> None:
|
|
times = (0.04000000000000009, 0.050000000000000114)
|
|
|
|
exact_left, exact_right = _series_sample_bracket(
|
|
times=times,
|
|
time_s=0.04,
|
|
)
|
|
interpolated_left, interpolated_right = _series_sample_bracket(
|
|
times=times,
|
|
time_s=0.041,
|
|
)
|
|
|
|
self.assertEqual(exact_left, exact_right)
|
|
self.assertAlmostEqual(exact_left, 0.04)
|
|
self.assertAlmostEqual(interpolated_left, 0.04)
|
|
self.assertAlmostEqual(interpolated_right, 0.05)
|
|
|
|
def test_full_state_script_writes_summary_and_comparison_csv(self) -> None:
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
output_dir = Path(tmpdir)
|
|
run, returned_output_dir = run_test_mql_full_state_comparison(
|
|
TestMqlFullStateComparisonScriptConfig(
|
|
paths=TestMqlFullStateComparisonPathConfig(
|
|
archive_path=TEST_MQL_AME,
|
|
output_dir=output_dir,
|
|
),
|
|
execution=TestMqlFullStateComparisonExecutionConfig(
|
|
data_paths=(
|
|
"press@pn_c1_8",
|
|
"vol1@pn_brp2_8",
|
|
"dm1@pneumatic_69",
|
|
"xv@pn_morifice_1",
|
|
"dm2@pn_morifice_1",
|
|
),
|
|
solver=SolveIVPConfig(t_start=0.0, t_stop=0.0),
|
|
t_eval=(0.0,),
|
|
),
|
|
)
|
|
)
|
|
summary_path = output_dir / "test_mql_full_state_comparison_summary.txt"
|
|
csv_path = output_dir / "test_mql_amesim_comparison.csv"
|
|
csv_summary_path = output_dir / "test_mql_amesim_comparison_summary.txt"
|
|
summary = summary_path.read_text(encoding="utf-8")
|
|
csv_header = csv_path.read_text(encoding="utf-8").splitlines()[0]
|
|
csv_summary_exists = csv_summary_path.exists()
|
|
|
|
self.assertEqual(returned_output_dir, output_dir)
|
|
self.assertEqual(run.sample_count, 1)
|
|
self.assertEqual(run.signal_count, 5)
|
|
self.assertAlmostEqual(run.comparison.max_abs_error, 0.0, delta=1.0e-8)
|
|
self.assertEqual(
|
|
run.metrics_by_max_abs_error()[0].data_path,
|
|
"press@pn_c1_8",
|
|
)
|
|
diagnostic = run.signal_diagnostic("press@pn_c1_8")
|
|
self.assertEqual(diagnostic.data_path, "press@pn_c1_8")
|
|
self.assertAlmostEqual(diagnostic.initial_python_value, -1300.0)
|
|
self.assertAlmostEqual(diagnostic.final_python_value, -1300.0)
|
|
self.assertAlmostEqual(diagnostic.final_abs_error, 0.0, delta=1.0e-8)
|
|
self.assertEqual(
|
|
run.diagnostics_by_final_abs_error()[0].data_path,
|
|
"press@pn_c1_8",
|
|
)
|
|
flow_diagnostic = run.pnl0001_mass_flow_diagnostic()
|
|
self.assertEqual(flow_diagnostic.data_path, "dm1@pneumatic_69")
|
|
self.assertAlmostEqual(flow_diagnostic.initial_python_dm1_g_s, 0.0)
|
|
self.assertAlmostEqual(flow_diagnostic.initial_amesim_dm1_g_s, 0.0)
|
|
self.assertAlmostEqual(
|
|
flow_diagnostic.initial_python_canonical_kg_s,
|
|
-flow_diagnostic.initial_python_dm1_g_s * 1.0e-3,
|
|
)
|
|
pnvo_diagnostic = run.pnvo_diagnostic()
|
|
self.assertEqual(pnvo_diagnostic.alias, "pn_morifice_1")
|
|
self.assertAlmostEqual(pnvo_diagnostic.initial_python_opening, 0.0)
|
|
self.assertAlmostEqual(pnvo_diagnostic.initial_amesim_opening, 0.0)
|
|
self.assertAlmostEqual(pnvo_diagnostic.initial_python_mass_flow_kg_s, 0.0)
|
|
self.assertAlmostEqual(pnvo_diagnostic.initial_amesim_mass_flow_kg_s, 0.0)
|
|
chamber_diagnostic = run.chamber_rhs_diagnostic("pn_c1_8")
|
|
self.assertEqual(chamber_diagnostic.chamber_alias, "pn_c1_8")
|
|
self.assertEqual(chamber_diagnostic.piston_alias, "pn_brp2_8")
|
|
self.assertAlmostEqual(chamber_diagnostic.chamber_volume_m3, 0.015)
|
|
self.assertAlmostEqual(
|
|
chamber_diagnostic.energy_derivative_w,
|
|
chamber_diagnostic.port_a_energy_flow_w
|
|
+ chamber_diagnostic.port_b_energy_flow_w
|
|
+ chamber_diagnostic.boundary_work_w
|
|
+ chamber_diagnostic.thermal_energy_flow_w,
|
|
)
|
|
self.assertTrue(csv_summary_exists)
|
|
self.assertIn("Mode: Python 132 full-state closure comparison", summary)
|
|
self.assertIn("Compared signals: 5", summary)
|
|
self.assertIn("AMESim first saved interval: 0.010000000000000023", summary)
|
|
self.assertIn("Final time aligns with AMESim sample: True", summary)
|
|
self.assertIn("Largest absolute error: press@pn_c1_8=", summary)
|
|
self.assertIn("Largest final endpoint error: press@pn_c1_8=", summary)
|
|
self.assertIn("Metrics by max absolute error:", summary)
|
|
self.assertIn("Endpoint diagnostics by final absolute error:", summary)
|
|
self.assertIn(
|
|
"PNL0001 canonical mass-flow diagnostic: dm1@pneumatic_69",
|
|
summary,
|
|
)
|
|
self.assertIn("equals -AMESim dm1 * 1e-3", summary)
|
|
self.assertIn("PNVO diagnostic: pn_morifice_1", summary)
|
|
self.assertIn("final_python_opening=", summary)
|
|
self.assertIn("final_python_mass_flow_kg_s=", summary)
|
|
self.assertIn("Largest endpoint chamber RHS breakdown: pn_c1_8", summary)
|
|
self.assertIn("piston_alias=pn_brp2_8", summary)
|
|
self.assertIn("mass_derivative_kg_s=", summary)
|
|
self.assertIn("boundary_work_w=", summary)
|
|
self.assertIn("thermal_energy_flow_w=", summary)
|
|
self.assertIn("final_python=", summary)
|
|
self.assertIn("final_amesim=", summary)
|
|
self.assertIn("python.press@pn_c1_8", csv_header)
|
|
self.assertIn("amesim.vol1@pn_brp2_8", csv_header)
|
|
self.assertIn("python.dm1@pneumatic_69", csv_header)
|
|
self.assertIn("python.xv@pn_morifice_1", csv_header)
|
|
self.assertIn("python.dm2@pn_morifice_1", csv_header)
|
|
|
|
def test_default_execution_aligns_first_amesim_saved_sample(self) -> None:
|
|
execution = TestMqlFullStateComparisonExecutionConfig()
|
|
|
|
self.assertEqual(execution.solver.t_stop, 0.01)
|
|
self.assertEqual(execution.solver.max_step, 1.0e-3)
|
|
self.assertEqual(execution.t_eval, (0.0, 0.01))
|
|
self.assertIn("xv@pn_morifice_1", execution.data_paths)
|
|
self.assertIn("dm2@pn_morifice_1", execution.data_paths)
|
|
|
|
def test_formats_pnvo_event_boundary_diagnostic(self) -> None:
|
|
data_paths = (
|
|
"press@pn_c1_8",
|
|
"dm1@pneumatic_69",
|
|
"xv@pn_morifice_1",
|
|
"dm2@pn_morifice_1",
|
|
)
|
|
diagnostic = TestMqlPnvoEventBoundaryDiagnostic(
|
|
orifice_alias="pn_morifice_1",
|
|
event_time_s=0.04,
|
|
integration_stop_time_s=0.039999999999999994,
|
|
data_paths=data_paths,
|
|
python_values_by_data_path={
|
|
"press@pn_c1_8": -1090.9,
|
|
"dm1@pneumatic_69": -0.00949,
|
|
"xv@pn_morifice_1": 1.0,
|
|
"dm2@pn_morifice_1": 502.945,
|
|
},
|
|
amesim_values_by_data_path={
|
|
"press@pn_c1_8": -1146.38,
|
|
"dm1@pneumatic_69": -0.00667,
|
|
"xv@pn_morifice_1": 1.0,
|
|
"dm2@pn_morifice_1": 497.824,
|
|
},
|
|
)
|
|
|
|
self.assertEqual(diagnostic.orifice_alias, "pn_morifice_1")
|
|
self.assertLess(diagnostic.integration_stop_time_s, diagnostic.event_time_s)
|
|
self.assertEqual(diagnostic.abs_error("xv@pn_morifice_1"), 0.0)
|
|
self.assertAlmostEqual(
|
|
diagnostic.abs_error("dm2@pn_morifice_1"),
|
|
5.121,
|
|
)
|
|
summary = format_test_mql_pnvo_event_boundary_summary(diagnostic)
|
|
self.assertIn("PNVO event boundary diagnostic (pn_morifice_1)", summary)
|
|
self.assertIn("Observation side: right-continuous STEP0 opening", summary)
|
|
self.assertTrue(summary.endswith("\n"))
|
|
|
|
def test_formats_pnvo_event_window_diagnostic_with_samples(self) -> None:
|
|
data_paths = (
|
|
"press@pn_c1_8",
|
|
"temp@pn_c1_8",
|
|
"vol@pn_c1_8",
|
|
"mgas1@pn_c1_8",
|
|
"p2@pneumatic_69",
|
|
"t2@pneumatic_69",
|
|
"mgas@pneumatic_69",
|
|
"re@pneumatic_69",
|
|
"v@pneumatic_69",
|
|
"ff@pneumatic_69",
|
|
"dm1@pneumatic_69",
|
|
"xv@pn_morifice_1",
|
|
"dm2@pn_morifice_1",
|
|
)
|
|
sample = TestMqlPnvoEventWindowSampleDiagnostic(
|
|
time_s=0.05,
|
|
data_paths=data_paths,
|
|
python_values_by_data_path={
|
|
"press@pn_c1_8": 219127.9,
|
|
"temp@pn_c1_8": 372.3,
|
|
"vol@pn_c1_8": 15000.0,
|
|
"mgas1@pn_c1_8": 5.46,
|
|
"p2@pneumatic_69": 93250.0,
|
|
"t2@pneumatic_69": 293.15,
|
|
"mgas@pneumatic_69": 0.53,
|
|
"re@pneumatic_69": 1.41e6,
|
|
"v@pneumatic_69": 832.0,
|
|
"ff@pneumatic_69": 0.0243,
|
|
"dm1@pneumatic_69": 443.2,
|
|
"xv@pn_morifice_1": 1.0,
|
|
"dm2@pn_morifice_1": 463.7,
|
|
},
|
|
amesim_values_by_data_path={
|
|
"press@pn_c1_8": 187060.0,
|
|
"temp@pn_c1_8": 296.1,
|
|
"vol@pn_c1_8": 15000.0,
|
|
"mgas1@pn_c1_8": 5.47,
|
|
"p2@pneumatic_69": 1484689.6,
|
|
"t2@pneumatic_69": 296.1,
|
|
"mgas@pneumatic_69": 0.81,
|
|
"re@pneumatic_69": 1.35e6,
|
|
"v@pneumatic_69": 519.8,
|
|
"ff@pneumatic_69": 0.0241,
|
|
"dm1@pneumatic_69": 419.9,
|
|
"xv@pn_morifice_1": 1.0,
|
|
"dm2@pn_morifice_1": 456.8,
|
|
},
|
|
amesim_sample_left_time_s=0.05,
|
|
amesim_sample_right_time_s=0.05,
|
|
pnl0001_rhs_diagnostics=(
|
|
TestMqlPnl0001LineRhsDiagnostic(
|
|
line_alias="pneumatic_69",
|
|
chamber_alias="pn_c1_8",
|
|
line_pressure_pa=1034250.0,
|
|
line_temperature_k=293.15,
|
|
chamber_pressure_pa=320427.9,
|
|
chamber_temperature_k=379.9,
|
|
chamber_to_line_flow_kg_s=-0.4432,
|
|
node_to_line_flow_kg_s=0.4210,
|
|
mass_derivative_kg_s=-0.0222,
|
|
port_1_energy_flow_w=-404000.0,
|
|
port_2_energy_flow_w=384000.0,
|
|
thermal_energy_flow_w=0.0,
|
|
energy_derivative_w=-20000.0,
|
|
),
|
|
),
|
|
pnl0001_pressure_loss_diagnostics=(
|
|
TestMqlPnl0001PressureLossCalibrationDiagnostic(
|
|
line_alias="pneumatic_69",
|
|
chamber_alias="pn_c1_8",
|
|
time_s=0.05,
|
|
amesim_cm=0.0159,
|
|
amesim_dm1_g_s=419.9,
|
|
amesim_mass_flow_magnitude_kg_s=0.4199,
|
|
amesim_line_gauge_pressure_pa=1484689.6,
|
|
amesim_chamber_gauge_pressure_pa=187060.0,
|
|
amesim_line_temperature_k=296.1,
|
|
amesim_pressure_drop_pa=1297629.6,
|
|
current_darcy_pressure_drop_pa=422633.2,
|
|
pressure_drop_multiplier=3.07,
|
|
candidate_pn2pipefr_dm1_g_s=424.2,
|
|
candidate_pn2pipefr_to_amesim_dm1_ratio=1.01,
|
|
amesim_linear_conductance_kg_s_sqrt_k_per_pa=5.56e-6,
|
|
python_linear_conductance_kg_s_sqrt_k_per_pa=1.06e-5,
|
|
python_to_amesim_linear_conductance_ratio=1.91,
|
|
),
|
|
),
|
|
pnvo_flow_parameter_diagnostics=(
|
|
TestMqlPnvoFlowParameterDiagnostic(
|
|
orifice_alias="pn_morifice_1",
|
|
time_s=0.05,
|
|
amesim_cm=0.0158,
|
|
amesim_dm2_g_s=456.8,
|
|
amesim_opening=1.0,
|
|
amesim_gas_velocity_m_s=885.9,
|
|
python_opening=1.0,
|
|
python_flow_coefficient=0.45,
|
|
python_effective_area_m2=78.5e-6,
|
|
python_line_pressure_pa=15310000.0,
|
|
python_boundary_pressure_pa=1586000.0,
|
|
python_upstream_pressure_pa=15310000.0,
|
|
python_upstream_temperature_k=293.15,
|
|
python_mass_flow_kg_s=0.4637,
|
|
python_cm=0.0147,
|
|
python_to_amesim_cm_ratio=0.93,
|
|
),
|
|
),
|
|
pnvo_upstream_enthalpy_diagnostics=(
|
|
TestMqlPnvoUpstreamEnthalpyDiagnostic(
|
|
orifice_alias="pn_morifice_1",
|
|
upstream_line_alias="pneumatic_87",
|
|
time_s=0.05,
|
|
amesim_orifice_port_2_enthalpy_flow_w=-18851.7,
|
|
amesim_orifice_port_2_mass_flow_g_s=456.8,
|
|
amesim_orifice_port_3_enthalpy_flow_w=18851.7,
|
|
amesim_orifice_port_3_mass_flow_g_s=-456.8,
|
|
amesim_upstream_line_center_enthalpy_flow_w=15823.7,
|
|
amesim_upstream_line_center_mass_flow_g_s=-454.2,
|
|
amesim_upstream_line_port_2_temperature_k=287.7,
|
|
amesim_upstream_line_port_2_pressure_pa=13.871e6,
|
|
amesim_orifice_port_2_implied_reference_temperature_k=290.2,
|
|
amesim_orifice_port_2_implied_temperature_delta_to_line_k=2.5,
|
|
amesim_upstream_line_port_2_reference_enthalpy_flow_w=-24714.8,
|
|
amesim_upstream_line_port_2_reference_enthalpy_error_w=-5863.1,
|
|
amesim_upstream_line_port_2_real_gas_reference_enthalpy_flow_w=-19240.8,
|
|
amesim_upstream_line_port_2_real_gas_reference_enthalpy_error_w=-389.1,
|
|
python_orifice_to_node_flow_kg_s=0.4637,
|
|
python_upstream_line_port_2_temperature_k=282.2,
|
|
python_upstream_line_port_2_pressure_pa=13.84e6,
|
|
python_current_port_2_enthalpy_flow_w=679490.8,
|
|
python_reference_port_2_enthalpy_flow_w=-38478.5,
|
|
python_real_gas_reference_port_2_enthalpy_flow_w=-32998.5,
|
|
python_current_port_2_enthalpy_error_w=698342.5,
|
|
python_reference_port_2_enthalpy_error_w=-19626.8,
|
|
python_real_gas_reference_port_2_enthalpy_error_w=-14146.8,
|
|
),
|
|
),
|
|
pnl0003_energy_diagnostics=(
|
|
TestMqlPnl0003EnergyDiagnostic(
|
|
line_alias="pneumatic_87",
|
|
time_s=0.05,
|
|
amesim_port_1_temperature_k=293.1,
|
|
amesim_port_2_temperature_k=287.7,
|
|
amesim_port_1_pressure_pa=15.2e6,
|
|
amesim_port_2_pressure_pa=13.9e6,
|
|
amesim_port_1_mass_flow_g_s=-8.5,
|
|
amesim_port_1_enthalpy_flow_w=85.0,
|
|
amesim_center_mass_flow_g_s=-454.2,
|
|
amesim_center_enthalpy_flow_w=15823.7,
|
|
amesim_port_2_mass_flow_g_s=-456.8,
|
|
amesim_port_2_enthalpy_flow_w=18851.7,
|
|
amesim_port_1_storage_mass_derivative_g_s=-462.7,
|
|
amesim_port_1_storage_enthalpy_sum_w=15908.7,
|
|
amesim_port_2_storage_mass_derivative_g_s=-2.6,
|
|
amesim_port_2_storage_enthalpy_sum_w=3028.0,
|
|
amesim_total_mass_derivative_fd_g_s=-470.0,
|
|
amesim_total_mass_derivative_backward_g_s=-540.0,
|
|
amesim_total_mass_derivative_forward_g_s=-400.0,
|
|
amesim_total_storage_mass_derivative_g_s=-465.3,
|
|
amesim_total_storage_mass_derivative_residual_g_s=4.7,
|
|
amesim_center_flow_python_sign_equivalent_g_s=454.2,
|
|
amesim_center_flow_python_sign_error_g_s=-0.2,
|
|
python_center_mass_flow_g_s=454.0,
|
|
python_total_mass_derivative_kg_s=-0.47,
|
|
amesim_port_1_temperature_derivative_fd_k_s=-210.0,
|
|
amesim_port_1_temperature_derivative_backward_k_s=-420.0,
|
|
amesim_port_1_temperature_derivative_forward_k_s=100.0,
|
|
amesim_port_2_temperature_derivative_fd_k_s=-540.0,
|
|
amesim_port_2_temperature_derivative_backward_k_s=-600.0,
|
|
amesim_port_2_temperature_derivative_forward_k_s=120.0,
|
|
amesim_port_1_pn2vol_dtemp_k_s=-220.0,
|
|
amesim_port_2_pn2vol_dtemp_k_s=-530.0,
|
|
amesim_port_1_pn2vol_dtemp_residual_k_s=-10.0,
|
|
amesim_port_2_pn2vol_dtemp_residual_k_s=10.0,
|
|
python_port_1_temperature_k=293.15,
|
|
python_port_2_temperature_k=282.2,
|
|
python_port_1_pressure_pa=15.3e6,
|
|
python_port_2_pressure_pa=13.8e6,
|
|
python_port_1_mass_derivative_kg_s=-0.46,
|
|
python_port_2_mass_derivative_kg_s=-0.01,
|
|
python_port_1_current_dtemp_k_s=0.0,
|
|
python_port_2_current_dtemp_k_s=-1200.0,
|
|
python_port_1_real_gas_reference_dtemp_k_s=-100.0,
|
|
python_port_2_real_gas_reference_dtemp_k_s=-650.0,
|
|
python_port_2_temperature_error_to_amesim_k=-5.5,
|
|
),
|
|
),
|
|
pnl0001_energy_flow_diagnostics=(
|
|
TestMqlPnl0001EnergyFlowDiagnostic(
|
|
line_alias="pneumatic_69",
|
|
chamber_alias="pn_c1_8",
|
|
node_alias="pnnode4_16",
|
|
time_s=0.05,
|
|
amesim_port_1_enthalpy_flow_w=-4248.6,
|
|
amesim_port_1_mass_flow_g_s=419.9,
|
|
amesim_node_port_2_enthalpy_flow_w=-18664.2,
|
|
amesim_node_port_2_mass_flow_g_s=438.3,
|
|
amesim_observed_port_enthalpy_sum_w=-22912.8,
|
|
python_port_1_internal_energy_flow_w=-378000.0,
|
|
python_port_2_internal_energy_flow_w=398000.0,
|
|
python_current_energy_derivative_w=20000.0,
|
|
python_direct_enthalpy_port_1_flow_w=-629000.0,
|
|
python_direct_enthalpy_port_2_flow_w=663000.0,
|
|
python_direct_enthalpy_energy_derivative_w=34000.0,
|
|
python_direct_minus_current_energy_derivative_w=14000.0,
|
|
python_p4_node_port_2_enthalpy_flow_w=640000.0,
|
|
python_p4_node_port_2_mass_flow_g_s=430.0,
|
|
python_p4_node_port_2_connected_h_j_kg=1488372.1,
|
|
python_p4_node_port_2_connected_temperature_k=286.6,
|
|
python_p4_node_port_2_connected_h_delta_to_line_h_j_kg=-34000.0,
|
|
python_p4_node_port_2_counterfactual_dtemp_k_s=-5100.0,
|
|
reference_temperature_k=298.15,
|
|
amesim_port_1_reference_enthalpy_estimate_w=-4467.0,
|
|
amesim_port_1_reference_enthalpy_error_w=-218.4,
|
|
amesim_candidate_pn2pipefr_dm2i_g_s=-419.9,
|
|
amesim_candidate_pn2pipefr_dh2i_w=4467.0,
|
|
amesim_candidate_storage_enthalpy_sum_w=-14197.2,
|
|
amesim_candidate_pn2pipefr_dtemp_k_s=-5480.0,
|
|
amesim_candidate_pn2pipefr_dtemp_residual_k_s=-5420.3,
|
|
python_reference_port_1_enthalpy_flow_w=-10760.0,
|
|
python_reference_node_port_2_enthalpy_flow_w=-18500.0,
|
|
python_reference_observed_port_enthalpy_sum_w=-29260.0,
|
|
python_reference_port_1_to_amesim_error_w=-6511.4,
|
|
python_reference_node_port_2_to_amesim_error_w=164.2,
|
|
python_reference_sum_to_amesim_error_w=-6347.2,
|
|
python_current_line_temperature_derivative_k_s=0.0,
|
|
amesim_line_temperature_derivative_fd_k_s=277.3,
|
|
amesim_pn2vol2_dtemp_node_plus_dh1_k_s=-9000.0,
|
|
amesim_pn2vol2_dtemp_node_minus_dh1_k_s=-5600.0,
|
|
python_reference_pn2vol2_dtemp_node_minus_dh1_k_s=-11200.0,
|
|
),
|
|
),
|
|
p4_node_enthalpy_breakdown_diagnostics=(
|
|
TestMqlP4NodeEnthalpyBreakdownDiagnostic(
|
|
node_alias="pnnode4_16",
|
|
time_s=0.05,
|
|
amesim_port_1_enthalpy_flow_w=-1000.0,
|
|
amesim_port_1_mass_flow_g_s=-30.0,
|
|
amesim_port_3_enthalpy_flow_w=-2000.0,
|
|
amesim_port_3_mass_flow_g_s=-40.0,
|
|
amesim_port_4_enthalpy_flow_w=-15664.2,
|
|
amesim_port_4_mass_flow_g_s=508.3,
|
|
amesim_port_2_enthalpy_flow_w=-18664.2,
|
|
amesim_port_2_mass_flow_g_s=438.3,
|
|
python_port_1_enthalpy_flow_w=-900.0,
|
|
python_port_1_mass_flow_g_s=-29.0,
|
|
python_port_3_enthalpy_flow_w=-2100.0,
|
|
python_port_3_mass_flow_g_s=-41.0,
|
|
python_port_4_enthalpy_flow_w=643000.0,
|
|
python_port_4_mass_flow_g_s=500.0,
|
|
python_port_2_enthalpy_flow_w=640000.0,
|
|
python_port_2_mass_flow_g_s=430.0,
|
|
python_reference_port_1_enthalpy_flow_w=-800.0,
|
|
python_reference_port_3_enthalpy_flow_w=-1700.0,
|
|
python_reference_port_4_enthalpy_flow_w=-16000.0,
|
|
python_reference_port_2_enthalpy_flow_w=-18500.0,
|
|
python_port_2_enthalpy_error_w=658664.2,
|
|
python_reference_port_2_enthalpy_error_w=164.2,
|
|
),
|
|
),
|
|
pnch012_energy_equation_diagnostics=(
|
|
TestMqlPnch012EnergyEquationDiagnostic(
|
|
chamber_alias="pn_c1_8",
|
|
piston_alias="pn_brp2_8",
|
|
line_alias="pneumatic_69",
|
|
time_s=0.05,
|
|
amesim_port_1_enthalpy_flow_w=-4248.6,
|
|
amesim_port_1_mass_flow_g_s=419.9,
|
|
amesim_chamber_mass_derivative_fd_g_s=370.8,
|
|
amesim_chamber_mass_derivative_residual_g_s=49.1,
|
|
amesim_chamber_temperature_derivative_fd_k_s=5134.6,
|
|
amesim_chamber_volume_rate_fd_m3_s=0.001004,
|
|
amesim_piston_volume_rate_m3_s=2.5e-8,
|
|
amesim_heat_flow_w=-0.0,
|
|
amesim_boundary_work_fd_volume_w=-289.5,
|
|
amesim_pn2vol_reference_dtemp_fd_volume_k_s=8090.0,
|
|
amesim_pn2vol_reference_dtemp_fd_volume_residual_k_s=2955.4,
|
|
amesim_pn2vol_reference_dtemp_piston_volume_k_s=8107.0,
|
|
amesim_pn2vol_reference_dtemp_piston_volume_residual_k_s=2972.4,
|
|
python_port_a_mass_flow_kg_s=-0.42,
|
|
python_current_energy_derivative_w=-28000.0,
|
|
python_current_chamber_temperature_derivative_k_s=-7800.0,
|
|
reference_temperature_k=298.15,
|
|
),
|
|
),
|
|
)
|
|
diagnostic = TestMqlPnvoEventWindowDiagnostic(
|
|
orifice_alias="pn_morifice_1",
|
|
event_time_s=0.04,
|
|
final_time_s=0.05,
|
|
data_paths=data_paths,
|
|
segment_diagnostics=(
|
|
TestMqlPnvoEventWindowSegmentDiagnostic(
|
|
t_start=0.048,
|
|
t_stop=0.05,
|
|
method="BDF",
|
|
rtol=1.0e-5,
|
|
atol=1.0e-8,
|
|
max_step=1.0e-5,
|
|
rhs_evaluations=8154,
|
|
success=True,
|
|
message="success",
|
|
),
|
|
),
|
|
sample_diagnostics=(sample,),
|
|
python_values_by_data_path=sample.python_values_by_data_path,
|
|
amesim_values_by_data_path=sample.amesim_values_by_data_path,
|
|
)
|
|
|
|
summary = format_test_mql_pnvo_event_window_summary(diagnostic)
|
|
|
|
self.assertAlmostEqual(diagnostic.abs_error("dm2@pn_morifice_1"), 6.9)
|
|
self.assertAlmostEqual(sample.abs_error("press@pn_c1_8"), 32067.9)
|
|
self.assertIn("PNVO event window diagnostic (pn_morifice_1)", summary)
|
|
self.assertIn("Sample comparisons:", summary)
|
|
self.assertFalse(sample.amesim_values_are_interpolated)
|
|
self.assertIn("t=0.05 (amesim=exact@0.05)", summary)
|
|
self.assertIn("rhs=8154", summary)
|
|
self.assertIn("rhs@pneumatic_69", summary)
|
|
self.assertIn("dm_dt=-0.0222", summary)
|
|
self.assertIn("pressure_loss@pneumatic_69", summary)
|
|
self.assertIn("cm=0.0159", summary)
|
|
self.assertIn("dp_multiplier=3.07", summary)
|
|
self.assertIn("candidate_pn2pipefr_dm1=424.2", summary)
|
|
self.assertIn("candidate_pn2pipefr_ratio=1.01", summary)
|
|
self.assertIn("amesim_linear_k=5.56e-06", summary)
|
|
self.assertIn("python_linear_k=1.06e-05", summary)
|
|
self.assertIn("linear_k_ratio=1.91", summary)
|
|
self.assertIn("flow_parameter@pn_morifice_1", summary)
|
|
self.assertIn("amesim_cm=0.0158", summary)
|
|
self.assertIn("python_cm=0.0147", summary)
|
|
self.assertIn("cm_ratio=0.93", summary)
|
|
self.assertIn("amesim_gasvel=885.9", summary)
|
|
self.assertIn("pnvo_upstream_enthalpy@pn_morifice_1", summary)
|
|
self.assertIn("amesim_dh2=-18851.7", summary)
|
|
self.assertIn("amesim_line_dhctr=15823.7", summary)
|
|
self.assertIn("amesim_implied_t2=290.2", summary)
|
|
self.assertIn("amesim_implied_t2_delta=2.5", summary)
|
|
self.assertIn("amesim_ref_dh2=-24714.8", summary)
|
|
self.assertIn("amesim_real_ref_dh2=-19240.8", summary)
|
|
self.assertIn("amesim_real_ref_dh2_error=-389.1", summary)
|
|
self.assertIn("python_current_dh2=679490.8", summary)
|
|
self.assertIn("python_ref_dh2=-38478.5", summary)
|
|
self.assertIn("python_real_ref_dh2=-32998.5", summary)
|
|
self.assertIn("pnl0003_energy@pneumatic_87", summary)
|
|
self.assertIn("amesim_sdm1=-462.7", summary)
|
|
self.assertIn("amesim_sdh2=3028.0", summary)
|
|
self.assertIn("amesim_fd_dmgas=-470.0", summary)
|
|
self.assertIn("amesim_back_dmgas=-540.0", summary)
|
|
self.assertIn("amesim_fwd_dmgas=-400.0", summary)
|
|
self.assertIn("amesim_storage_dmgas=-465.3", summary)
|
|
self.assertIn("amesim_storage_dmgas_residual=4.7", summary)
|
|
self.assertIn("amesim_dmctr_py_sign=454.2", summary)
|
|
self.assertIn("python_center_dm=454.0", summary)
|
|
self.assertIn("python_center_dm_error=-0.2", summary)
|
|
self.assertIn("python_dmgas_dt=-0.47", summary)
|
|
self.assertIn("amesim_back_dT2=-600.0", summary)
|
|
self.assertIn("amesim_fwd_dT2=120.0", summary)
|
|
self.assertIn("amesim_pn2vol_dT2=-530.0", summary)
|
|
self.assertIn("python_real_ref_dT2=-650.0", summary)
|
|
self.assertIn("python_t2_error=-5.5", summary)
|
|
self.assertIn("energy_flow@pneumatic_69", summary)
|
|
self.assertIn("amesim_dh1=-4248.6", summary)
|
|
self.assertIn("amesim_node_dh2=-18664.2", summary)
|
|
self.assertIn("direct_h_dU_dt=34000.0", summary)
|
|
self.assertIn("python_p4_node_dh2=640000.0", summary)
|
|
self.assertIn("python_p4_node_dm2=430.0", summary)
|
|
self.assertIn("python_p4_node_h2=1488372.1", summary)
|
|
self.assertIn("python_p4_node_t2=286.6", summary)
|
|
self.assertIn("python_p4_node_h2_delta=-34000.0", summary)
|
|
self.assertIn("python_p4_node_counterfactual_dT=-5100.0", summary)
|
|
self.assertIn("ref_dh1_est=-4467.0", summary)
|
|
self.assertIn("ref_dh1_error=-218.4", summary)
|
|
self.assertIn("candidate_dm2i=-419.9", summary)
|
|
self.assertIn("candidate_dh2i=4467.0", summary)
|
|
self.assertIn("candidate_storage_sdh=-14197.2", summary)
|
|
self.assertIn("candidate_pn2pipefr_dT=-5480.0", summary)
|
|
self.assertIn("python_ref_dh1=-10760.0", summary)
|
|
self.assertIn("python_ref_node_dh2=-18500.0", summary)
|
|
self.assertIn("python_ref_sdh=-29260.0", summary)
|
|
self.assertIn("python_ref_sdh_error=-6347.2", summary)
|
|
self.assertIn("python_current_dT=0.0", summary)
|
|
self.assertIn("amesim_fd_dT=277.3", summary)
|
|
self.assertIn("amesim_pn2vol2_dT_node_plus_dh1=-9000.0", summary)
|
|
self.assertIn("python_ref_pn2vol2_dT_node_minus_dh1=-11200.0", summary)
|
|
self.assertIn("p4_node_enthalpy@pnnode4_16", summary)
|
|
self.assertIn("amesim_p4_dh=-15664.2", summary)
|
|
self.assertIn("python_p4_dh=643000.0", summary)
|
|
self.assertIn("python_ref_p2_dh=-18500.0", summary)
|
|
self.assertIn("python_ref_p2_dh_error=164.2", summary)
|
|
self.assertIn("pnch012_energy@pn_c1_8", summary)
|
|
self.assertIn("amesim_fd_dmgas=370.8", summary)
|
|
self.assertIn("amesim_dmgas_residual=49.1", summary)
|
|
self.assertIn("amesim_fd_dvol=0.001004", summary)
|
|
self.assertIn("amesim_pn2vol_ref_dT_fdvol=8090.0", summary)
|
|
self.assertIn("python_current_dT=-7800.0", summary)
|
|
self.assertIn("Final comparison:", summary)
|
|
self.assertTrue(summary.endswith("\n"))
|
|
|
|
def test_full_state_script_can_skip_artifact_files(self) -> None:
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
output_dir = Path(tmpdir)
|
|
run, returned_output_dir = run_test_mql_full_state_comparison(
|
|
TestMqlFullStateComparisonScriptConfig(
|
|
paths=TestMqlFullStateComparisonPathConfig(
|
|
archive_path=TEST_MQL_AME,
|
|
output_dir=output_dir,
|
|
),
|
|
execution=TestMqlFullStateComparisonExecutionConfig(
|
|
write_summary=False,
|
|
write_comparison_csv=False,
|
|
data_paths=("press@pn_c1_8",),
|
|
solver=SolveIVPConfig(t_start=0.0, t_stop=0.0),
|
|
t_eval=(0.0,),
|
|
),
|
|
)
|
|
)
|
|
|
|
self.assertEqual(returned_output_dir, output_dir)
|
|
self.assertEqual(run.signal_count, 1)
|
|
self.assertFalse((output_dir / "test_mql_full_state_comparison_summary.txt").exists())
|
|
self.assertFalse((output_dir / "test_mql_amesim_comparison.csv").exists())
|
|
|
|
def test_format_test_mql_full_state_comparison_summary(self) -> None:
|
|
run, _ = run_test_mql_full_state_comparison(
|
|
TestMqlFullStateComparisonScriptConfig(
|
|
paths=TestMqlFullStateComparisonPathConfig(archive_path=TEST_MQL_AME),
|
|
execution=TestMqlFullStateComparisonExecutionConfig(
|
|
write_summary=False,
|
|
write_comparison_csv=False,
|
|
data_paths=("press@pn_c1_8",),
|
|
solver=SolveIVPConfig(t_start=0.0, t_stop=0.0),
|
|
t_eval=(0.0,),
|
|
),
|
|
)
|
|
)
|
|
|
|
summary = format_test_mql_full_state_comparison_summary(run)
|
|
|
|
self.assertIn("Model: test_mql", summary)
|
|
self.assertIn("Output schema signals: 858", summary)
|
|
self.assertIn("Compared signals: 1", summary)
|
|
self.assertIn("Largest absolute error: press@pn_c1_8=", summary)
|
|
self.assertIn("Largest final endpoint error: press@pn_c1_8=", summary)
|
|
self.assertIn("Metrics by max absolute error:", summary)
|
|
self.assertIn("Endpoint diagnostics by final absolute error:", summary)
|
|
self.assertIn("Largest endpoint chamber RHS breakdown: pn_c1_8", summary)
|
|
self.assertTrue(summary.endswith("\n"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|