def two_valve_setup_fixed(vAs1_1, vAs1_2, vAs2_1, vAs2_2, vBs1_1, vBs1_2, vBs2_1, vBs2_2): pc1 = create_component(vAs1_1, vAs1_2, vAs2_1, vAs2_2, 'valve1', 'A') pc2 = create_component(vBs1_1, vBs1_2, vBs2_1, vBs2_2, 'valve2', 'B') component_mapping = {'valve1': {1: 1, 2: 2}, 'valve2': {1: 2, 2: 3}} pressures = {3: (100, True)} default_states = {'valve1': 'closed', 'valve2': 'open'} plumb = top.PlumbingEngine({ 'valve1': pc1, 'valve2': pc2 }, component_mapping, pressures, default_states) return plumb
def test_missing_node_pressure(): wrong_node_name = 4 pc1 = test.create_component(0, 0, 0, 0, 'valve1', 'A') pc2 = test.create_component(0, 0, 0, 0, 'valve2', 'B') component_mapping = {'valve1': {1: 1, 2: 2}, 'valve2': {1: 2, 2: 3}} pressures = {wrong_node_name: (100, False), 2: (100, False)} default_states = {'valve1': 'closed', 'valve2': 'open'} with pytest.raises(exceptions.BadInputError) as err: _ = top.PlumbingEngine({ 'valve1': pc1, 'valve2': pc2 }, component_mapping, pressures, default_states) assert str(err.value) == f"Node {wrong_node_name} not found in graph."
def test_5(): pc = test.create_component(1, utils.CLOSED, utils.CLOSED, utils.CLOSED, 'check', 'A') mapping = {'check': {1: 1, 2: 2}} pressures = {1: (100, False)} default_states = {'check': 'open'} steady_by = utils.s_to_micros(1) converged = {1: 50, 2: 50} step_plumb = top.PlumbingEngine({'check': pc}, mapping, pressures, default_states) step_state = step_plumb.step(1e6) solve_plumb = top.PlumbingEngine({'check': pc}, mapping, pressures, default_states) solve_state = solve_plumb.solve() len_plumb = top.PlumbingEngine({'check': pc}, mapping, pressures, default_states) solve_len = len(len_plumb.solve(return_resolution=len_plumb.time_res)) test.validate_plumbing_engine(step_plumb, solve_plumb, steady_by, converged, solve_state, step_state, solve_len, len_plumb.time_res)
def one_component_engine(): states = { 'static': { (1, 2, 'A1'): 1, (2, 1, 'A2'): 1 }, } edges = [(1, 2, 'A1'), (2, 1, 'A2')] c1 = top.PlumbingComponent('c1', states, edges) mapping = {'c1': {1: 1, 2: 2}} pressures = {1: (0, False), 2: (0, False)} initial_states = {'c1': 'static'} return top.PlumbingEngine({'c1': c1}, mapping, pressures, initial_states)
def test_list_functions(): pc1 = test.create_component(0.5, 0.2, 10, utils.CLOSED, 'valve1', 'A') pc2 = test.create_component(0.5, 0.2, 10, utils.CLOSED, 'valve2', 'B') component_mapping = { 'valve1': { 1: 1, 2: 2 }, 'valve2': { 1: 2, 2: 3 } } negative_pressure = -50 pressures = {3: (negative_pressure, False)} default_states = {'valve1': 'closed', 'valve2': 'open'} plumb = top.PlumbingEngine( {'valve1': pc1, 'valve2': pc2}, component_mapping, pressures, default_states) assert plumb.edges() == [ (1, 2, 'valve1.A1', {'FC': utils.teq_to_FC(utils.s_to_micros(10))}), (2, 1, 'valve1.A2', {'FC': 0}), (2, 3, 'valve2.B1', {'FC': utils.teq_to_FC(utils.s_to_micros(0.5))}), (3, 2, 'valve2.B2', {'FC': utils.teq_to_FC(utils.s_to_micros(0.2))}) ] assert plumb.edges(data=False) == [ (1, 2, 'valve1.A1'), (2, 1, 'valve1.A2'), (2, 3, 'valve2.B1'), (3, 2, 'valve2.B2') ] # Pressure at node 3 will be 0, since the provided one was invalid assert plumb.nodes() == [ (1, {'body': top.GenericNode(0)}), (2, {'body': top.GenericNode(0)}), (3, {'body': top.GenericNode(0)}), ] assert plumb.nodes(data=False) == [1, 2, 3] assert plumb.errors() == { invalid.InvalidNodePressure(f"Negative pressure {negative_pressure} not allowed.", 3) }
def test_wrong_node_mapping(): proper_node_name = 1 wrong_node_name = 5 pc1 = test.create_component(0, 0, 0, 0, 'valve1', 'A') pc2 = test.create_component(0, 0, 0, 0, 'valve2', 'B') component_mapping = { 'valve1': { wrong_node_name: 1, 2: 8 }, 'valve2': { 1: 8, 2: 3 } } pressures = {3: (100, False)} default_states = {'valve1': 'closed', 'valve2': 'open'} plumb = top.PlumbingEngine({ 'valve1': pc1, 'valve2': pc2 }, component_mapping, pressures, default_states) assert not plumb.is_valid() # Since the node name is wrong in the mapping, an error should be added # every time the mapping dict is accessed to find the matching graph node. # This translates to twice (once per component) when populating the main graph, # and twice (once per component) when assigning initial states by component, # since the component node stored in the component's states dict needs to be # translated into a main graph node. So 4 errors total, but they're identical # so we should get one original error and one multi-error note. assert len(plumb.errors()) == 2 error = invalid.InvalidComponentNode( f"Component 'valve1', node {proper_node_name} not found in mapping dict.", 'valve1', proper_node_name) duplicate_error = invalid.DuplicateError( invalid.multi_error_msg( f"Component 'valve1', node {proper_node_name} not found in mapping dict." ), error) assert error in plumb.errors() assert duplicate_error in plumb.errors()
def test_invalid_engine(): wrong_component_name = 'potato' pc1 = test.create_component(0, 0, 0, 0, 'valve1', 'A') pc2 = test.create_component(0, 0, 0, 0, 'valve2', 'B') component_mapping = {'valve1': {1: 1, 2: 2}, 'valve2': {1: 2, 2: 3}} pressures = {3: (100, False)} default_states = {'valve1': 'closed', 'valve2': 'open'} plumb = top.PlumbingEngine({ wrong_component_name: pc1, 'valve2': pc2 }, component_mapping, pressures, default_states) assert not plumb.is_valid() with pytest.raises(exceptions.InvalidEngineError) as err: plumb.step(5) assert str( err.value ) == "Step() cannot be called on an invalid engine. Check for errors."
def test_add_to_empty(): plumb = top.PlumbingEngine() pc = test.create_component(2, utils.CLOSED, 0, 0, 'valve', 'A') mapping = {1: 1, 2: 2} plumb.add_component(pc, mapping, 'open', {1: (20, False)}) assert plumb.is_valid() assert plumb.time_res == utils.DEFAULT_TIME_RESOLUTION_MICROS assert plumb.edges() == [(1, 2, 'valve.A1', { 'FC': utils.teq_to_FC(utils.s_to_micros(2)) }), (2, 1, 'valve.A2', { 'FC': 0 })] assert plumb.nodes() == [(1, { 'body': top.GenericNode(20) }), (2, { 'body': top.GenericNode(0) })] assert plumb.current_state('valve') == 'open'
def test_missing_initial_state(): wrong_component_name = 'potato' proper_component_name = 'valve1' pc1 = test.create_component(0, 0, 0, 0, 'valve1', 'A') pc2 = test.create_component(0, 0, 0, 0, 'valve2', 'B') component_mapping = {'valve1': {1: 1, 2: 2}, 'valve2': {1: 2, 2: 3}} pressures = {3: (100, False)} default_states = {wrong_component_name: 'closed', 'valve2': 'open'} plumb = top.PlumbingEngine({ 'valve1': pc1, 'valve2': pc2 }, component_mapping, pressures, default_states) assert not plumb.is_valid() assert len(plumb.errors()) == 1 error = invalid.InvalidComponentName( f"Component '{proper_component_name}' state not found in initial states dict.", proper_component_name) assert error in plumb.errors()
def test_load_errorless_graph(): wrong_component_name = 'potato' pc1 = test.create_component(0, 0, 0, 0, 'valve1', 'A') pc2 = test.create_component(0, 0, 0, 0, 'valve2', 'B') component_mapping = {'valve1': {1: 1, 2: 2}, 'valve2': {1: 2, 2: 3}} pressures = {3: (100, False)} default_states = {'valve1': 'closed', 'valve2': 'open'} plumb = top.PlumbingEngine({ wrong_component_name: pc1, 'valve2': pc2 }, component_mapping, pressures, default_states) assert not plumb.is_valid() assert len(plumb.errors()) == 2 error1 = invalid.InvalidComponentName( f"Component with name '{wrong_component_name}' not found in mapping dict.", wrong_component_name) error2 = invalid.InvalidComponentName( f"Component '{wrong_component_name}' state not found in initial states dict.", wrong_component_name) assert error1 in plumb.errors() assert error2 in plumb.errors() plumb0 = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) pressures = {3: (100, False)} default_states = {'valve1': 'closed', 'valve2': 'open'} plumb.load_graph(plumb0.component_dict, plumb0.mapping, pressures, default_states) assert plumb.is_valid()
def test_engine_dicts_remain_unchanged(): pc1 = test.create_component(0, 0, 0, 0, 'valve1', 'A') pc2 = test.create_component(0, 0, 0, 0, 'valve2', 'B') component_mapping = {'valve1': {1: 1, 2: 2}, 'valve2': {1: 2, 2: 3}} pressures = {3: (100, False)} default_states = {'valve1': 'closed', 'valve2': 'open'} component_dict = {'valve1': pc1, 'valve2': pc2} _ = top.PlumbingEngine(component_dict, component_mapping, pressures, default_states) assert component_mapping == { 'valve1': { 1: 1, 2: 2 }, 'valve2': { 1: 2, 2: 3 } } assert pressures == {3: (100, False)} assert default_states == {'valve1': 'closed', 'valve2': 'open'} assert component_dict == {'valve1': pc1, 'valve2': pc2}
def test_empty_graph(): plumb = top.PlumbingEngine() assert plumb.time_res == utils.DEFAULT_TIME_RESOLUTION_MICROS assert not plumb.edges() assert not plumb.nodes()
def make_engine(self): """Create the plumbing engine from the provided input.""" plumb = top.PlumbingEngine(self.components, self.mapping, self.initial_pressures, self.initial_states) return plumb
def test_empty_engine(): plumb = top.PlumbingEngine() with pytest.raises(exceptions.InvalidEngineError) as err: plumb.step(5) assert str(err.value) == "Step() cannot be called on an empty engine."
def make_engine(): states = {'static': {(1, 2, 'A1'): 1, (2, 1, 'A2'): 1}} edges = [(1, 2, 'A1'), (2, 1, 'A2')] mapping = { 'c1': { 1: 'atm', 2: 1 }, 'c2': { 1: 1, 2: 2 }, 'c3': { 1: 1, 2: 2 }, 'c4': { 1: 2, 2: 3 }, 'c5': { 1: 3, 2: 'atm' }, 'c6': { 1: 3, 2: 4 }, 'c7': { 1: 4, 2: 5 }, 'c8': { 1: 4, 2: 5 }, 'c9': { 1: 5, 2: 6 }, 'c10': { 1: 6, 2: 'atm' }, 'c11': { 1: 6, 2: 'atm' }, 'c12': { 1: 6, 2: 'atm' } } pressures = {} for k1, v1 in mapping.items(): for k2, v2 in v1.items(): pressures[v2] = (0, False) component_dict = { k: top.PlumbingComponent(k, states, edges) for k in mapping.keys() } initial_states = {k: 'static' for k in mapping.keys()} return top.PlumbingEngine(component_dict, mapping, pressures, initial_states)