from __future__ import annotations import unittest from PythonModels.core.solver import SolveIVPConfig from PythonModels.systems.test_mql import TestMqlSystem class TestMqlPnl0001ChamberSegmentTests(unittest.TestCase): def setUp(self) -> None: self.system = TestMqlSystem() self.spec = self.system.discover_pneumatic_branch_topology().chamber_segment_specs[0] def test_system_assembles_all_twenty_physical_pnl0001_lines(self) -> None: self.assertEqual(self.system.typed_pnl0001_line_count, 20) self.assertIn("pneumatic_96", self.system.pnl0001_assembly.lines) def test_closure_inserts_topology_derived_inlet_line(self) -> None: closure = self.system.pnl0001_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=16.0e6, outlet_pressure_pa=15.3e6, ) snapshot = closure.snapshot() rhs = closure.rhs(closure.initial_state_vector()) self.assertEqual(closure.components.inlet_line.name, "pneumatic_96") self.assertEqual(len(closure.initial_state_vector()), 4) self.assertEqual(len(rhs), 4) self.assertGreater(snapshot.node_to_line_flow, 0.0) self.assertAlmostEqual(snapshot.line_to_chamber_flow, 0.0, delta=1.0e-7) self.assertAlmostEqual(snapshot.outlet_flow, 0.0, delta=1.0e-7) self.assertAlmostEqual(rhs[0] + rhs[2], snapshot.node_to_line_flow) def test_internal_line_orifice_flow_cancels_from_total_mass_balance(self) -> None: closure = self.system.pnl0001_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=15.3e6, outlet_pressure_pa=14.0e6, ) state = closure.initial_state_vector() state[0] *= 1.01 state[1] *= 1.01 snapshot = closure.snapshot(state) rhs = closure.rhs(state) self.assertGreater(snapshot.line_to_chamber_flow, 0.0) self.assertAlmostEqual( rhs[0] + rhs[2], snapshot.node_to_line_flow - snapshot.outlet_flow, delta=1.0e-12, ) self.assertAlmostEqual( closure.components.inlet_line.port_2.m_flow, -snapshot.line_to_chamber_flow, ) def test_simulates_four_state_line_chamber_segment(self) -> None: solution = self.system.simulate_pnl0001_chamber_segment_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, outlet_pressure_pa=15.29e6, config=SolveIVPConfig( t_start=0.0, t_stop=1.0e-7, max_step=1.0e-8, ), t_eval=[0.0, 5.0e-8, 1.0e-7], ) self.assertTrue(solution.success) self.assertEqual(len(solution.t), 3) self.assertEqual(len(solution.y), 4) self.assertEqual([len(row) for row in solution.y], [3, 3, 3, 3]) class TestMqlPnl0001PairChamberSegmentTests(unittest.TestCase): def setUp(self) -> None: self.system = TestMqlSystem() self.spec = self.system.discover_pneumatic_branch_topology().chamber_segment_specs[0] def test_pair_closure_uses_both_topology_derived_lines(self) -> None: closure = self.system.pnl0001_pair_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=16.0e6, outlet_node_pressure_pa=14.0e6, ) snapshot = closure.snapshot() rhs = closure.rhs(closure.initial_state_vector()) self.assertEqual(closure.components.inlet_line.name, "pneumatic_96") self.assertEqual(closure.components.outlet_line.name, "pneumatic_97") self.assertEqual(len(closure.initial_state_vector()), 6) self.assertEqual(len(rhs), 6) self.assertGreater(snapshot.inlet_node_to_line_flow, 0.0) self.assertLess(snapshot.outlet_node_to_line_flow, 0.0) self.assertAlmostEqual( rhs[0] + rhs[2] + rhs[4], snapshot.inlet_node_to_line_flow + snapshot.outlet_node_to_line_flow, delta=1.0e-12, ) def test_both_internal_orifice_flows_cancel_from_total_mass(self) -> None: closure = self.system.pnl0001_pair_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=15.3e6, outlet_node_pressure_pa=15.3e6, ) state = closure.initial_state_vector() state[0] *= 1.01 state[1] *= 1.01 state[4] *= 0.99 state[5] *= 0.99 snapshot = closure.snapshot(state) rhs = closure.rhs(state) self.assertGreater(snapshot.inlet_line_to_chamber_flow, 0.0) self.assertLess(snapshot.outlet_line_to_chamber_flow, 0.0) self.assertAlmostEqual( rhs[0] + rhs[2] + rhs[4], snapshot.inlet_node_to_line_flow + snapshot.outlet_node_to_line_flow, delta=1.0e-12, ) self.assertAlmostEqual( closure.components.outlet_line.port_2.m_flow, -snapshot.outlet_line_to_chamber_flow, ) def test_simulates_six_state_pair_line_chamber_segment(self) -> None: solution = self.system.simulate_pnl0001_pair_chamber_segment_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, outlet_node_pressure_pa=15.29e6, config=SolveIVPConfig( t_start=0.0, t_stop=1.0e-7, max_step=1.0e-8, ), t_eval=[0.0, 5.0e-8, 1.0e-7], ) self.assertTrue(solution.success) self.assertEqual(len(solution.t), 3) self.assertEqual(len(solution.y), 6) self.assertEqual([len(row) for row in solution.y], [3, 3, 3, 3, 3, 3]) class TestMqlPn3NodeChamberSegmentTests(unittest.TestCase): def setUp(self) -> None: self.system = TestMqlSystem() self.spec = self.system.discover_pneumatic_branch_topology().chamber_segment_specs[0] def test_closure_replaces_outlet_boundary_with_real_pn3_node(self) -> None: closure = self.system.pn3_node_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, resistance_boundary_pressure_pa=15.29e6, ) snapshot = closure.snapshot() rhs = closure.rhs(closure.initial_state_vector()) self.assertEqual(closure.components.inlet_line.name, "pneumatic_96") self.assertEqual(closure.components.outlet_line.name, "pneumatic_97") self.assertEqual(closure.components.node_line.name, "pneumatic_88") self.assertEqual(closure.components.node_resistance.name, "pneumatic_100") self.assertEqual(closure.components.node_orifice.name, "pn_morifice_9") self.assertEqual(closure.components.node.alias, "pn_node3_9") self.assertEqual(len(closure.initial_state_vector()), 10) self.assertEqual(len(rhs), 10) self.assertAlmostEqual( snapshot.node_balance.pressure_pa, snapshot.node_line_port_1.p, ) self.assertAlmostEqual( snapshot.node_balance.temperature_k, snapshot.node_line_port_1.T, ) def test_pn3_node_flow_cancels_between_adjacent_lines(self) -> None: closure = self.system.pn3_node_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=15.3e6, resistance_boundary_pressure_pa=15.0e6, p4_boundary_pressure_pa=15.0e6, ) state = closure.initial_state_vector() state[4] *= 0.99 state[5] *= 0.99 snapshot = closure.snapshot(state) rhs = closure.rhs(state) self.assertGreater(snapshot.outlet_node_to_line_flow, 0.0) self.assertGreater(snapshot.node_to_resistance_flow, 0.0) self.assertAlmostEqual( snapshot.node_balance.port_2_mass_flow_g_s, (snapshot.outlet_node_to_line_flow + snapshot.node_to_resistance_flow) * 1.0e3, ) self.assertAlmostEqual( snapshot.node_to_pnl0003_flow, -(snapshot.outlet_node_to_line_flow + snapshot.node_to_resistance_flow), ) self.assertGreater(snapshot.pnl0003_to_p4_flow, 0.0) self.assertAlmostEqual( closure.components.node_line.port_1.m_flow, snapshot.node_to_pnl0003_flow, ) self.assertAlmostEqual( closure.components.node_line.port_2.m_flow, -snapshot.pnl0003_to_p4_flow, ) mass_derivative_sum = rhs[0] + rhs[2] + rhs[4] + rhs[6] + rhs[8] self.assertAlmostEqual( mass_derivative_sum, ( snapshot.inlet_node_to_line_flow - snapshot.pnl0003_to_p4_flow - snapshot.node_to_resistance_flow ), delta=1.0e-12, ) def test_simulates_ten_state_pn3_node_chamber_segment(self) -> None: solution = self.system.simulate_pn3_node_chamber_segment_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, resistance_boundary_pressure_pa=15.29e6, p4_boundary_pressure_pa=15.29e6, config=SolveIVPConfig( t_start=0.0, t_stop=1.0e-8, max_step=1.0e-9, ), t_eval=[0.0, 5.0e-9, 1.0e-8], ) self.assertTrue(solution.success) self.assertEqual(len(solution.t), 3) self.assertEqual(len(solution.y), 10) self.assertEqual([len(row) for row in solution.y], [3] * 10) class TestMqlPn3P4NodeChamberSegmentTests(unittest.TestCase): def setUp(self) -> None: self.system = TestMqlSystem() self.spec = self.system.discover_pneumatic_branch_topology().chamber_segment_specs[0] def test_closure_replaces_p4_pressure_boundary_with_real_node_and_lines(self) -> None: closure = self.system.pn3_p4_node_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, resistance_boundary_pressure_pa=15.29e6, ) snapshot = closure.snapshot() rhs = closure.rhs(closure.initial_state_vector()) self.assertEqual(closure.components.inlet_line.name, "pneumatic_96") self.assertEqual(closure.components.volume.name, "pn_general_chamber") self.assertEqual(closure.components.outlet_line.name, "pneumatic_97") self.assertEqual(closure.components.inlet_orifice.name, "pn_orifice_18") self.assertEqual(closure.components.outlet_orifice.name, "pn_orifice_19") self.assertEqual(closure.components.node_orifice.name, "pn_morifice_9") self.assertEqual(closure.components.node_resistance.name, "pneumatic_100") self.assertEqual(closure.components.node.alias, "pn_node3_9") self.assertEqual(closure.components.p4_node.alias, "pnnode4_17") self.assertEqual(closure.components.p4_primary_line.name, "pneumatic_68") self.assertEqual(closure.components.p4_primary_chamber.name, "pn_c1_9") self.assertEqual(closure.components.p4_port1_line.name, "pneumatic_86") self.assertEqual(closure.components.p4_port1_remote_node.alias, "pnnode4_18") self.assertEqual( closure.components.p4_port1_remote_primary_line.name, "pneumatic_66", ) self.assertEqual( closure.components.p4_port1_remote_primary_chamber.name, "pn_c1_10", ) self.assertEqual( closure.components.p4_port1_remote_port1_line.name, "pneumatic_80", ) self.assertEqual(closure.components.p4_port1_far_node.alias, "pnnode4_19") self.assertEqual( closure.components.p4_port1_far_primary_line.name, "pneumatic_65", ) self.assertEqual( closure.components.p4_port1_far_primary_chamber.name, "pn_c1_11", ) self.assertEqual(closure.components.p4_port1_far_port1_line.name, "pneumatic_85") self.assertEqual(closure.components.p4_port1_next_node.alias, "pnnode4_23") self.assertEqual( closure.components.p4_port1_next_primary_line.name, "pneumatic_71", ) self.assertEqual( closure.components.p4_port1_next_primary_chamber.name, "pn_c1_12", ) self.assertEqual(closure.components.p4_port1_next_port1_line.name, "pneumatic_81") self.assertEqual(closure.components.p4_bridge_node.alias, "pnnode4_20") self.assertEqual(closure.components.p4_bridge_primary_line.name, "pneumatic_72") self.assertEqual(closure.components.p4_bridge_primary_chamber.name, "pn_c1_13") self.assertEqual( closure.components.p4_port1_remote_orifice.name, "pn_morifice_10", ) self.assertEqual( closure.components.p4_port1_remote_orifice_line.name, "pneumatic_75", ) self.assertEqual( closure.components.p4_port1_remote_orifice_node.alias, "pn_node3_10", ) self.assertEqual(closure.components.p4_port3_line.name, "pneumatic_83") self.assertEqual(closure.components.p4_port3_remote_node.alias, "pnnode4_16") self.assertEqual( closure.components.p4_port3_remote_primary_line.name, "pneumatic_69", ) self.assertEqual( closure.components.p4_port3_remote_primary_chamber.name, "pn_c1_8", ) self.assertEqual( closure.components.p4_port3_remote_port3_line.name, "pneumatic_95", ) self.assertEqual(closure.components.p4_port3_far_node.alias, "pnnode4_22") self.assertEqual( closure.components.p4_port3_far_primary_line.name, "pneumatic_74", ) self.assertEqual( closure.components.p4_port3_far_primary_chamber.name, "pn_c1_15", ) self.assertEqual(closure.components.p4_port3_far_port3_line.name, "pneumatic_82") self.assertEqual(closure.components.p4_port3_next_node.alias, "pnnode4_21") self.assertEqual( closure.components.p4_port3_next_primary_line.name, "pneumatic_73", ) self.assertEqual( closure.components.p4_port3_next_primary_chamber.name, "pn_c1_14", ) self.assertEqual(closure.components.p4_port3_next_port3_line.name, "pneumatic_84") self.assertEqual( closure.components.p4_port3_next_orifice.name, "pn_morifice_13", ) self.assertEqual( closure.components.p4_port3_next_orifice_line.name, "pneumatic_91", ) self.assertEqual( closure.components.p4_port3_next_orifice_node.alias, "pn_node3_14", ) self.assertEqual( closure.components.p4_port3_next_orifice_output_line.name, "pneumatic_93", ) self.assertEqual( closure.components.p4_port3_next_chamber_inlet_line.name, "pneumatic_103", ) self.assertEqual( closure.components.p4_port3_next_chamber.name, "pn_general_chamber_5", ) self.assertEqual( closure.components.p4_port3_next_chamber_outlet_line.name, "pneumatic_104", ) self.assertEqual( closure.components.p4_port3_next_chamber_inlet_orifice.name, "pn_orifice_24", ) self.assertEqual( closure.components.p4_port3_next_chamber_outlet_orifice.name, "pn_orifice_25", ) self.assertEqual( closure.components.p4_port3_remote_orifice.name, "pn_morifice_1", ) self.assertEqual( closure.components.p4_port3_remote_orifice_line.name, "pneumatic_87", ) self.assertEqual( closure.components.p4_port3_remote_orifice_node.alias, "pn_node3_8", ) self.assertEqual( closure.components.p4_port3_remote_orifice_resistance.name, "pneumatic_105", ) self.assertEqual( closure.components.p4_port3_remote_resistance_node.alias, "pn_node3_15", ) self.assertEqual( closure.components.p4_port3_remote_resistance_node_line.name, "pneumatic_92", ) self.assertEqual( closure.components.p4_port3_remote_resistance_orifice.name, "pn_morifice_14", ) self.assertEqual( closure.components.p4_port3_remote_resistance_output_line.name, "pneumatic_94", ) self.assertEqual( closure.components.p4_port3_next_orifice_resistance.name, "pneumatic_106", ) self.assertEqual( closure.components.p4_port3_next_resistance_node.alias, "pn_node3_13", ) self.assertEqual( closure.components.p4_port3_next_resistance_node_line.name, "pneumatic_78", ) self.assertEqual( closure.components.p4_port3_next_resistance_orifice.name, "pn_morifice_12", ) self.assertEqual( closure.components.p4_port3_next_resistance_output_line.name, "pneumatic_70", ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_inlet_line.name, "pneumatic_101", ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber.name, "pn_general_chamber_4", ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_outlet_line.name, "pneumatic_102", ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_inlet_orifice.name, "pn_orifice_22", ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_outlet_orifice.name, "pn_orifice_23", ) self.assertEqual( closure.components.p4_port1_next_orifice.name, "pn_morifice_11", ) self.assertEqual( closure.components.p4_port1_next_orifice_line.name, "pneumatic_77", ) self.assertEqual( closure.components.p4_port1_next_orifice_node.alias, "pn_node3_12", ) self.assertEqual( closure.components.p4_port1_next_orifice_output_line.name, "pneumatic_79", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance.name, "pneumatic_107", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_node.alias, "pn_node3_11", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_line.name, "pneumatic_76", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_orifice.name, "pn_morifice_15", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_inlet_line.name, "pneumatic_98", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber.name, "pn_general_chamber_2", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_outlet_line.name, "pneumatic_99", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_inlet_orifice.name, "pn_orifice_20", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_outlet_orifice.name, "pn_orifice_21", ) self.assertEqual(len(closure.initial_state_vector()), 112) self.assertEqual(len(rhs), 112) self.assertAlmostEqual( snapshot.p4_balance.pressure_pa, snapshot.p4_primary_line.p, ) self.assertAlmostEqual( snapshot.p4_balance.temperature_k, snapshot.p4_primary_line.T, ) def test_full_state_closure_combines_pneumatic_and_mechanical_states(self) -> None: closure = self.system.full_state_closure_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, resistance_boundary_pressure_pa=15.29e6, ) state = closure.initial_state_vector() snapshot = closure.snapshot(state) rhs = closure.rhs(state) self.assertEqual(closure.pneumatic_state_count, 112) self.assertEqual(closure.mechanical_state_count, 20) self.assertEqual(closure.state_count, 132) self.assertEqual(len(state), 132) self.assertEqual(snapshot.state_count, 132) self.assertEqual(snapshot.mechanical.state_count, 20) self.assertEqual(len(rhs), 132) self.assertAlmostEqual( snapshot.pneumatic.p4_balance.pressure_pa, snapshot.pneumatic.p4_primary_line.p, ) self.assertEqual( snapshot.mechanical.states[0].alias, "mass_friction_endstops_10", ) self.assertAlmostEqual(rhs[112], -0.8167936695810917) def test_simulates_full_132_state_closure(self) -> None: solution = self.system.simulate_full_state_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, resistance_boundary_pressure_pa=15.29e6, config=SolveIVPConfig(t_start=0.0, t_stop=1.0e-5, max_step=1.0e-6), t_eval=[0.0, 1.0e-5], ) self.assertTrue(solution.success) self.assertEqual(len(solution.t), 2) self.assertEqual(len(solution.y), 132) self.assertEqual([len(row) for row in solution.y], [2] * 132) def test_p4_closure_uses_structured_neighborhood(self) -> None: closure = self.system.pn3_p4_node_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, resistance_boundary_pressure_pa=15.29e6, ) neighborhood = self.system.p4_node_neighborhood(closure.components.p4_node.alias) self.assertEqual( closure.components.p4_primary_line.name, neighborhood.primary.line_alias, ) self.assertEqual( closure.components.p4_primary_chamber.name, neighborhood.primary.chamber_alias, ) self.assertEqual( closure.components.p4_port1_line.name, neighborhood.port_1.line_alias, ) self.assertEqual( closure.components.p4_port1_remote_node.alias, neighborhood.port_1.remote_node_alias, ) port1_remote_neighborhood = self.system.p4_node_neighborhood( neighborhood.port_1.remote_node_alias ) self.assertEqual( closure.components.p4_port1_remote_port1_line.name, port1_remote_neighborhood.port_1.line_alias, ) self.assertEqual( closure.components.p4_port1_far_node.alias, port1_remote_neighborhood.port_1.remote_node_alias, ) self.assertEqual( closure.components.p4_port1_far_primary_line.name, self.system._p4_primary_connection_for_node( port1_remote_neighborhood.port_1.remote_node_alias ).line_alias, ) port1_far_port1 = self.system._pnl0002_connection_for_node_port( closure.components.p4_port1_far_node.alias, "port_1", ) self.assertEqual( closure.components.p4_port1_far_port1_line.name, port1_far_port1.line_alias, ) self.assertEqual( closure.components.p4_port1_next_node.alias, port1_far_port1.remote_node_alias, ) self.assertEqual( closure.components.p4_port1_next_primary_line.name, self.system._p4_primary_connection_for_node( port1_far_port1.remote_node_alias ).line_alias, ) port1_next_port1 = self.system._pnl0002_connection_for_node_port( closure.components.p4_port1_next_node.alias, "port_1", ) self.assertEqual( closure.components.p4_port1_next_port1_line.name, port1_next_port1.line_alias, ) self.assertEqual( closure.components.p4_port1_next_orifice_output_line.name, self.system._pnl0001_line_for_node_port( closure.components.p4_port1_next_node.alias, "port_4", ).name, ) self.assertEqual( closure.components.p4_port1_next_orifice_node.alias, "pn_node3_12", ) self.assertEqual( closure.components.p4_port1_next_orifice_line.name, self.system._pnl0003_line_for_node_port("pn_node3_12", "port_2").name, ) self.assertEqual( closure.components.p4_port1_next_orifice.name, "pn_morifice_11", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance.name, self.system._pnl00r_line_for_node_port("pn_node3_12", "port_3").name, ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_node.alias, "pn_node3_11", ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_line.name, self.system._pnl0003_line_for_node_port("pn_node3_11", "port_2").name, ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_orifice.name, "pn_morifice_15", ) resistance_chamber_segment = ( self.system.discover_pneumatic_branch_topology().chamber_segment_specs[1] ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_spec, resistance_chamber_segment, ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_inlet_line.name, resistance_chamber_segment.inlet_line_alias, ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_outlet_line.name, resistance_chamber_segment.outlet_line_alias, ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_inlet_orifice.name, resistance_chamber_segment.inlet_orifice_alias, ) self.assertEqual( closure.components.p4_port1_next_orifice_resistance_chamber_outlet_orifice.name, resistance_chamber_segment.outlet_orifice_alias, ) self.assertEqual( closure.components.p4_bridge_node.alias, port1_next_port1.remote_node_alias, ) self.assertEqual( closure.components.p4_bridge_primary_line.name, self.system._p4_primary_connection_for_node( closure.components.p4_bridge_node.alias ).line_alias, ) self.assertEqual( closure.components.p4_port1_remote_orifice.name, port1_remote_neighborhood.port_4.orifice_alias, ) self.assertEqual( closure.components.p4_port1_remote_orifice_line.name, self.system._pnl0003_line_for_node_port("pn_node3_10", "port_2").name, ) self.assertEqual( closure.components.p4_port1_remote_orifice_node.alias, "pn_node3_10", ) self.assertEqual( closure.components.node_resistance.name, self.system._pnl00r_line_for_node_port("pn_node3_10", "port_3").name, ) self.assertEqual( closure.components.node.alias, "pn_node3_9", ) self.assertEqual( closure.components.p4_port3_line.name, neighborhood.port_3.line_alias, ) self.assertEqual( closure.components.p4_port3_remote_node.alias, neighborhood.port_3.remote_node_alias, ) port3_remote_neighborhood = self.system.p4_node_neighborhood( neighborhood.port_3.remote_node_alias ) self.assertEqual( closure.components.p4_port3_remote_port3_line.name, port3_remote_neighborhood.port_3.line_alias, ) self.assertEqual( closure.components.p4_port3_far_node.alias, port3_remote_neighborhood.port_3.remote_node_alias, ) self.assertEqual( closure.components.p4_port3_far_primary_line.name, self.system._p4_primary_connection_for_node( port3_remote_neighborhood.port_3.remote_node_alias ).line_alias, ) port3_far_port3 = self.system._pnl0002_connection_for_node_port( closure.components.p4_port3_far_node.alias, "port_3", ) self.assertEqual( closure.components.p4_port3_far_port3_line.name, port3_far_port3.line_alias, ) self.assertEqual( closure.components.p4_port3_next_node.alias, port3_far_port3.remote_node_alias, ) self.assertEqual( closure.components.p4_port3_next_primary_line.name, self.system._p4_primary_connection_for_node( port3_far_port3.remote_node_alias ).line_alias, ) port3_next_port3 = self.system._pnl0002_connection_for_node_port( closure.components.p4_port3_next_node.alias, "port_3", ) self.assertEqual( closure.components.p4_port3_next_port3_line.name, port3_next_port3.line_alias, ) self.assertEqual( closure.components.p4_bridge_node.alias, port3_next_port3.remote_node_alias, ) self.assertEqual( closure.components.p4_port3_next_orifice_output_line.name, self.system._pnl0001_line_for_node_port( closure.components.p4_port3_next_node.alias, "port_4", ).name, ) self.assertEqual( closure.components.p4_port3_next_orifice.name, "pn_morifice_13", ) self.assertEqual( closure.components.p4_port3_next_orifice_line.name, self.system._pnl0003_line_for_node_port("pn_node3_14", "port_2").name, ) self.assertEqual( closure.components.p4_port3_next_orifice_node.alias, "pn_node3_14", ) chamber_segment = ( self.system.discover_pneumatic_branch_topology().chamber_segment_specs[3] ) self.assertEqual( closure.components.p4_port3_next_chamber_spec, chamber_segment, ) self.assertEqual( closure.components.p4_port3_next_chamber_inlet_line.name, chamber_segment.inlet_line_alias, ) self.assertEqual( closure.components.p4_port3_next_chamber_outlet_line.name, chamber_segment.outlet_line_alias, ) self.assertEqual( closure.components.p4_port3_next_orifice_resistance.name, self.system._pnl00r_line_for_node_port("pn_node3_14", "port_3").name, ) self.assertEqual( closure.components.p4_port3_next_resistance_node.alias, "pn_node3_13", ) self.assertEqual( closure.components.p4_port3_next_resistance_node_line.name, self.system._pnl0003_line_for_node_port("pn_node3_13", "port_2").name, ) self.assertEqual( closure.components.p4_port3_next_resistance_orifice.name, "pn_morifice_12", ) self.assertEqual( closure.components.p4_port3_next_resistance_output_line.name, self.system._pnl0001_line_for_node_port( closure.components.p4_bridge_node.alias, "port_4", ).name, ) resistance_chamber_segment = ( self.system.discover_pneumatic_branch_topology().chamber_segment_specs[2] ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_spec, resistance_chamber_segment, ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_inlet_line.name, resistance_chamber_segment.inlet_line_alias, ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_outlet_line.name, resistance_chamber_segment.outlet_line_alias, ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_inlet_orifice.name, resistance_chamber_segment.inlet_orifice_alias, ) self.assertEqual( closure.components.p4_port3_next_resistance_chamber_outlet_orifice.name, resistance_chamber_segment.outlet_orifice_alias, ) self.assertEqual( closure.components.p4_port3_remote_orifice.name, port3_remote_neighborhood.port_4.orifice_alias, ) self.assertEqual( closure.components.p4_port3_remote_orifice_line.name, self.system._pnl0003_line_for_node_port("pn_node3_8", "port_2").name, ) self.assertEqual( closure.components.p4_port3_remote_orifice_node.alias, "pn_node3_8", ) self.assertEqual( closure.components.p4_port3_remote_orifice_resistance.name, self.system._pnl00r_line_for_node_port("pn_node3_8", "port_3").name, ) self.assertEqual( closure.components.p4_port3_remote_resistance_node.alias, "pn_node3_15", ) self.assertEqual( closure.components.p4_port3_remote_resistance_node_line.name, self.system._pnl0003_line_for_node_port("pn_node3_15", "port_2").name, ) self.assertEqual( closure.components.p4_port3_remote_resistance_orifice.name, "pn_morifice_14", ) self.assertEqual( closure.components.p4_port3_remote_resistance_output_line.name, self.system._pnl0001_line_for_node_port( closure.components.p4_port3_far_node.alias, "port_4", ).name, ) self.assertEqual( closure.components.node_orifice.name, neighborhood.port_4.orifice_alias, ) def test_p4_node_flow_cancels_between_pnvo_pnl0002_and_primary_line(self) -> None: closure = self.system.pn3_p4_node_chamber_segment_closure_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, resistance_boundary_pressure_pa=15.29e6, ) snapshot = closure.snapshot() rhs = closure.rhs(closure.initial_state_vector()) self.assertGreater(snapshot.pnl0003_to_p4_flow, 0.0) self.assertAlmostEqual( snapshot.p4_balance.port_2_mass_flow_g_s, ( -snapshot.p4_to_port1_line_flow - snapshot.p4_to_port3_line_flow + snapshot.pnl0003_to_p4_flow ) * 1.0e3, ) self.assertAlmostEqual( snapshot.p4_node_to_primary_line_flow, snapshot.p4_balance.port_2_mass_flow_g_s * 1.0e-3, ) self.assertAlmostEqual( snapshot.p4_node_to_primary_line_flow + snapshot.p4_to_port1_line_flow + snapshot.p4_to_port3_line_flow - snapshot.pnl0003_to_p4_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port1_remote_node_to_primary_line_flow + snapshot.p4_port1_remote_node_to_line_flow + snapshot.p4_port1_remote_to_port1_line_flow - snapshot.p4_port1_remote_orifice_to_node_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port1_far_node_to_primary_line_flow + snapshot.p4_port1_far_node_to_line_flow + snapshot.p4_port1_far_to_next_line_flow - snapshot.p4_port1_next_orifice_resistance_to_p4_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port1_next_node_to_primary_line_flow + snapshot.p4_port1_next_node_to_line_flow + snapshot.p4_port1_next_to_bridge_line_flow + snapshot.p4_port1_next_orifice_p4_to_output_line_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_bridge_node_to_primary_line_flow + snapshot.p4_bridge_to_port1_next_line_flow + snapshot.p4_bridge_to_port3_next_line_flow - snapshot.p4_port3_next_resistance_output_to_p4_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port1_remote_node_to_orifice_line_flow + snapshot.p4_port1_next_orifice_resistance_chamber_inlet_node_to_line_flow - snapshot.node_to_resistance_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.node_to_pnl0003_flow + snapshot.node_to_resistance_flow + snapshot.outlet_node_to_line_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_remote_node_to_orifice_line_flow + snapshot.inlet_node_to_line_flow + snapshot.p4_port3_remote_node_to_resistance_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_remote_node_to_primary_line_flow + snapshot.p4_port3_remote_node_to_line_flow + snapshot.p4_port3_remote_to_port3_line_flow - snapshot.p4_port3_remote_orifice_to_node_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_remote_resistance_node_to_line_flow - snapshot.p4_port3_remote_node_to_resistance_flow + snapshot.p4_port3_next_chamber_outlet_node_to_line_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_remote_resistance_output_to_p4_flow, snapshot.p4_port3_remote_resistance_to_output_line_flow, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_far_node_to_primary_line_flow + snapshot.p4_port3_far_node_to_line_flow + snapshot.p4_port3_far_to_next_line_flow - snapshot.p4_port3_remote_resistance_output_to_p4_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_next_node_to_primary_line_flow + snapshot.p4_port3_next_node_to_line_flow + snapshot.p4_port3_next_to_bridge_line_flow - snapshot.p4_port3_next_orifice_output_to_p4_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_next_orifice_node_to_line_flow + snapshot.p4_port3_next_chamber_inlet_node_to_line_flow - snapshot.p4_port3_next_resistance_node_to_next_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_next_orifice_output_to_p4_flow, snapshot.p4_port3_next_orifice_to_output_line_flow, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_next_resistance_node_to_line_flow + snapshot.p4_port3_next_resistance_node_to_next_flow + snapshot.p4_port3_next_resistance_chamber_outlet_node_to_line_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port3_next_resistance_output_to_p4_flow, snapshot.p4_port3_next_resistance_to_output_line_flow, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port1_next_orifice_node_to_line_flow + snapshot.p4_port3_next_resistance_chamber_inlet_node_to_line_flow - snapshot.p4_port1_next_orifice_resistance_node_to_next_flow, 0.0, delta=1.0e-12, ) self.assertAlmostEqual( snapshot.p4_port1_next_orifice_resistance_node_to_line_flow + snapshot.p4_port1_next_orifice_resistance_node_to_next_flow + snapshot.p4_port1_next_orifice_resistance_chamber_outlet_node_to_line_flow, 0.0, delta=1.0e-12, ) next_chamber_mass_sum = rhs[78] + rhs[80] + rhs[82] self.assertAlmostEqual( next_chamber_mass_sum, ( snapshot.p4_port3_next_chamber_inlet_node_to_line_flow + snapshot.p4_port3_next_chamber_outlet_node_to_line_flow ), delta=1.0e-12, ) resistance_chamber_mass_sum = rhs[90] + rhs[92] + rhs[94] self.assertAlmostEqual( resistance_chamber_mass_sum, ( snapshot.p4_port3_next_resistance_chamber_inlet_node_to_line_flow + snapshot.p4_port3_next_resistance_chamber_outlet_node_to_line_flow ), delta=1.0e-12, ) p4_port1_next_orifice_line_mass_sum = rhs[96] + rhs[98] self.assertAlmostEqual( p4_port1_next_orifice_line_mass_sum, ( snapshot.p4_port1_next_orifice_node_to_line_flow - snapshot.p4_port1_next_orifice_to_output_line_flow ), delta=1.0e-12, ) self.assertAlmostEqual( rhs[100], ( snapshot.p4_port1_next_orifice_p4_to_output_line_flow + snapshot.p4_port1_next_orifice_to_output_line_flow ), delta=1.0e-12, ) p4_port1_next_orifice_resistance_line_mass_sum = rhs[102] + rhs[104] self.assertAlmostEqual( p4_port1_next_orifice_resistance_line_mass_sum, ( snapshot.p4_port1_next_orifice_resistance_node_to_line_flow - snapshot.p4_port1_next_orifice_resistance_to_p4_flow ), delta=1.0e-12, ) p4_port1_next_orifice_resistance_chamber_mass_sum = ( rhs[106] + rhs[108] + rhs[110] ) self.assertAlmostEqual( p4_port1_next_orifice_resistance_chamber_mass_sum, ( snapshot.p4_port1_next_orifice_resistance_chamber_inlet_node_to_line_flow + snapshot.p4_port1_next_orifice_resistance_chamber_outlet_node_to_line_flow ), delta=1.0e-12, ) mass_derivative_sum = sum(rhs[index] for index in range(0, 112, 2)) self.assertAlmostEqual( mass_derivative_sum, 0.0, delta=1.0e-12, ) def test_simulates_one_hundred_twelve_state_pn3_p4_node_chamber_segment(self) -> None: solution = self.system.simulate_pn3_p4_node_chamber_segment_from_spec( self.spec, inlet_node_pressure_pa=15.31e6, resistance_boundary_pressure_pa=15.29e6, config=SolveIVPConfig( t_start=0.0, t_stop=1.0e-10, max_step=1.0e-11, ), t_eval=[0.0, 5.0e-11, 1.0e-10], ) self.assertTrue(solution.success) self.assertEqual(len(solution.t), 3) self.assertEqual(len(solution.y), 112) self.assertEqual([len(row) for row in solution.y], [3] * 112) if __name__ == "__main__": unittest.main()