def test_replace_graph(): plumb0 = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) plumb = test.two_valve_setup(0, 0, utils.CLOSED, utils.CLOSED, 0, 0, utils.CLOSED, 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.time_res == int( utils.s_to_micros(0.2) / utils.DEFAULT_RESOLUTION_SCALE) 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.nodes() == [(1, { 'body': top.GenericNode(0) }), (2, { 'body': top.GenericNode(0) }), (3, { 'body': top.GenericNode(100) })] assert plumb.current_state('valve1') == 'closed' assert plumb.current_state('valve2') == 'open'
def test_misc_engine(): steady_by = utils.s_to_micros(1) converged = {1: 33, 2: 33, 3: 33} solve_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) solve_state = solve_plumb.solve() step_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) step_state = step_plumb.step(steady_by) len_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) 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 test_timeout(): converged = {1: 33, 2: 33, 3: 33} big_teq = 100 plumb = test.two_valve_setup(big_teq, big_teq, big_teq, big_teq, big_teq, big_teq, big_teq, big_teq) solve_state = plumb.solve(max_time=1) assert solve_state != converged plumb_long = test.two_valve_setup(big_teq, big_teq, big_teq, big_teq, big_teq, big_teq, big_teq, big_teq) solve_len = len( plumb_long.solve(max_time=1, return_resolution=plumb_long.time_res)) assert solve_len == utils.s_to_micros(1) / plumb_long.time_res
def test_set_pressure(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) pc = test.create_component(0, 0, 0, 1, 'valve3', 'C') mapping = {1: 3, 2: 4} plumb.add_component(pc, mapping, 'closed', {4: (50, False)}) plumb.set_pressure(1, 200) plumb.set_pressure(2, 7000) assert plumb.nodes() == [(1, { 'body': top.GenericNode(200) }), (2, { 'body': top.GenericNode(7000) }), (3, { 'body': top.GenericNode(100) }), (4, { 'body': top.GenericNode(50) })] plumb.set_pressure(4, 10) plumb.set_pressure(1, 0) assert plumb.nodes() == [(1, { 'body': top.GenericNode(0) }), (2, { 'body': top.GenericNode(7000) }), (3, { 'body': top.GenericNode(100) }), (4, { 'body': top.GenericNode(10) })]
def test_reverse_orientation_three_edges(): pc_states = { 'open': { (1, 2, 'A1'): 5, (2, 1, 'A2'): 0, (1, 3, 'B1'): 3, (3, 1, 'B2'): 0, (2, 3, 'C1'): 4, (3, 2, 'C2'): 5 } } pc_edges = [(1, 2, 'A1'), (2, 1, 'A2'), (1, 3, 'B1'), (3, 1, 'B2'), (2, 3, 'C1'), (3, 2, 'C2')] pc = top.PlumbingComponent('threeway', pc_states, pc_edges) plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) mapping = {1: 3, 2: 4, 3: 5} plumb.add_component(pc, mapping, 'open') with pytest.raises(exceptions.InvalidComponentError) as err: plumb.reverse_orientation('threeway') assert str(err.value) == "Component must only have two edges to be automatically reversed.\n" +\ "Consider adjusting direction manually."
def test_reverse_orientation(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) plumb.reverse_orientation('valve1') assert plumb.is_valid() assert plumb.time_res == int( utils.s_to_micros(0.2) / utils.DEFAULT_RESOLUTION_SCALE) assert plumb.edges() == [(1, 2, 'valve1.A1', { 'FC': 0 }), (2, 1, 'valve1.A2', { 'FC': utils.teq_to_FC(utils.s_to_micros(10)) }), (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.nodes() == [ (1, { 'body': top.GenericNode(0) }), (2, { 'body': top.GenericNode(0) }), (3, { 'body': top.GenericNode(100) }), ] assert plumb.current_state('valve1') == 'closed' assert plumb.current_state('valve2') == 'open'
def test_add_invalid_component(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) wrong_node = 5 pc_states = { 'open': { (1, wrong_node, 'A1'): 0, (2, 1, 'A2'): 0 }, 'closed': { (1, 2, 'A1'): 0, (2, 1, 'A2'): 0 } } pc_edges = [(1, 2, 'A1'), (2, 1, 'A2')] invalid_pc = top.PlumbingComponent('valve', pc_states, pc_edges) assert not invalid_pc.is_valid() with pytest.raises(exceptions.BadInputError) as err: plumb.add_component(invalid_pc, {1: 3, 2: 4}, 'open') assert str( err.value ) == "Component not valid; all errors must be resolved before loading in."
def test_reset_keep_component(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) pc = test.create_component(0, 0, 0, 1, 'valve3', 'C') mapping = {1: 3, 2: 4} plumb.add_component(pc, mapping, 'closed', {4: (50, False)}) plumb.remove_component('valve2') plumb.reset() assert plumb.time == 0 assert plumb.is_valid() assert plumb.time_res == int( utils.s_to_micros(0.2) / utils.DEFAULT_RESOLUTION_SCALE) assert plumb.edges() == [(1, 2, 'valve1.A1', { 'FC': utils.teq_to_FC(utils.s_to_micros(10)) }), (2, 1, 'valve1.A2', { 'FC': 0 }), (3, 4, 'valve3.C1', { 'FC': utils.teq_to_FC(0) }), (4, 3, 'valve3.C2', { 'FC': utils.teq_to_FC(utils.s_to_micros(1)) })] assert plumb.nodes() == [(1, { 'body': top.GenericNode(0) }), (2, { 'body': top.GenericNode(0) }), (3, { 'body': top.GenericNode(100) }), (4, { 'body': top.GenericNode(0) })] assert plumb.current_state('valve1') == 'closed' assert plumb.current_state('valve3') == 'closed'
def test_reset_pressure(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) plumb.set_pressure(2, 150) plumb.reset() plumb_initial = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) assert plumb.time == 0 assert plumb.is_valid() assert plumb.time_res == plumb_initial.time_res assert plumb.edges() == plumb_initial.edges() assert plumb.nodes() == plumb_initial.nodes() assert plumb.current_state() == plumb_initial.current_state()
def test_reset_removed_component(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) plumb.remove_component('valve2') plumb.reset(True) plumb_initial = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) assert plumb.time == 0 assert plumb.is_valid() assert plumb.time_res == plumb_initial.time_res assert plumb.edges() == plumb_initial.edges() assert plumb.nodes() == plumb_initial.nodes() assert plumb.current_state() == plumb_initial.current_state()
def make_plumb(): """ The engine that's been set up looks like this: +-----+ +-----+ +-----+ +-----+ | | --C--> | | --40-> | | --5--> | | | 1 | | 2 | | 3 | | atm | | | <-10-- | | <-45-- | | <-5--- | | +-----+ +-----+ +-----+ +-----+ 100 100 100 0 Result annotation: - node 1 stays at 100 the entire duration because 1->2 is closed, so no pressure can flow out of node 1. - node 3's pressure drops much more quickly than node 2's because its teq to atm (5) is much lower than the teq in the 2->3 connection (50). Pressure from 3 flows into atm much faster than it's replenished by pressure from 2. - pressure at atm stays at 0, because pressure at atm is always 0. """ ret = test.two_valve_setup(1, 1, utils.CLOSED, 10, 40, 45, 1, 1) comp = test.create_component(5, 5, utils.CLOSED, utils.CLOSED, 'vent', 'A') mapping = { 1: 3, 2: utils.ATM, } ret.add_component(comp, mapping, 'open') ret.set_pressure(1, 100) ret.set_pressure(2, 100) return ret
def test_closed_engine(): plumb = test.two_valve_setup(utils.CLOSED, utils.CLOSED, utils.CLOSED, utils.CLOSED, utils.CLOSED, utils.CLOSED, utils.CLOSED, utils.CLOSED) state = plumb.step() assert state == {1: 0, 2: 0, 3: 100} state = plumb.solve() assert state == {1: 0, 2: 0, 3: 100}
def test_fix_node(): plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) assert plumb.fixed_pressures == {} plumb.set_pressure(3, 100, True) assert plumb.fixed_pressures == {3: 100}
def test_reverse_orientation_wrong_component(): wrong_name = 'potato' plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) with pytest.raises(exceptions.BadInputError) as err: plumb.reverse_orientation(wrong_name) assert str( err.value) == f"Component '{wrong_name}' not found in component dict."
def test_remove_nonexistent_component(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) nonexistent_component = 'potato' with pytest.raises(exceptions.BadInputError) as err: plumb.remove_component(nonexistent_component) assert str(err.value) ==\ f"Component with name {nonexistent_component} not found in component dict."
def test_set_component_wrong_component_name(): wrong_component_name = 'potato' plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) with pytest.raises(exceptions.BadInputError) as err: plumb.set_component_state(wrong_component_name, 'open') assert str( err.value ) == f"Component '{wrong_component_name}' not found in mapping dict."
def test_set_pressure_errors(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) pc = test.create_component(0, 0, 0, 1, 'valve3', 'C') mapping = {1: 3, 2: 4} plumb.add_component(pc, mapping, 'closed', {4: (50, False)}) pc_vent = test.create_component(0, 0, 0, 0, 'vent', 'D') mapping_vent = {1: 4, 2: utils.ATM} plumb.add_component(pc_vent, mapping_vent, 'closed') negative_pressure = -20 not_a_number = 'potato' with pytest.raises(exceptions.BadInputError) as err: plumb.set_pressure(4, negative_pressure) assert str( err.value) == f"Negative pressure {negative_pressure} not allowed." with pytest.raises(exceptions.BadInputError) as err: plumb.set_pressure(4, not_a_number) assert str(err.value) == f"Pressure {not_a_number} must be a number." assert plumb.nodes() == [(1, { 'body': top.GenericNode(0) }), (2, { 'body': top.GenericNode(0) }), (3, { 'body': top.GenericNode(100) }), (4, { 'body': top.GenericNode(50) }), (utils.ATM, { 'body': top.AtmNode() })] nonexistent_node = 5 with pytest.raises(exceptions.BadInputError) as err: plumb.set_pressure(nonexistent_node, 100) assert str(err.value) == f"Node {nonexistent_node} not found in graph." plumb.set_pressure(4, 100) assert plumb.nodes() == [(1, { 'body': top.GenericNode(0) }), (2, { 'body': top.GenericNode(0) }), (3, { 'body': top.GenericNode(100) }), (4, { 'body': top.GenericNode(100) }), (utils.ATM, { 'body': top.AtmNode() })] with pytest.raises(exceptions.BadInputError) as err: plumb.set_pressure(utils.ATM, 100) assert str( err.value) == f"Pressure for atmosphere node ({utils.ATM}) must be 0."
def test_set_fixed_pressure(): # steady_by needs to be a bit longer for this one since having the # fixed pressure makes equalization take longer than the teq. steady_by = utils.s_to_micros(3) converged = {1: 100, 2: 100, 3: 100} solve_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) solve_plumb.set_pressure(3, 100, fixed=True) solve_state = solve_plumb.solve() step_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) step_plumb.set_pressure(3, 100, fixed=True) step_state = step_plumb.step(steady_by) len_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) len_plumb.set_pressure(3, 100, fixed=True) 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 test_set_component_wrong_state_name(): wrong_state_name = 'potato' plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) with pytest.raises(exceptions.BadInputError) as err: plumb.set_component_state('valve1', wrong_state_name) assert str( err.value ) == f"State '{wrong_state_name}' not found in valve1 states dict."
def test_reset_added_component(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) pc = test.create_component(0, 0, 0, 1, 'valve3', 'C') mapping = {1: 3, 2: 4} plumb.add_component(pc, mapping, 'closed', {4: (50, False)}) plumb.reset(True) plumb_initial = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) assert plumb.time == 0 assert plumb.is_valid() assert plumb.time_res == plumb_initial.time_res assert plumb.edges() == plumb_initial.edges() assert plumb.nodes() == plumb_initial.nodes() assert plumb.current_state() == plumb_initial.current_state()
def test_add_component_errors(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) name = 'valve3' wrong_node = 3 right_node = 2 pc = test.create_component(0, 0, 0, 1, name, 'C') mapping = {1: 3, wrong_node: 4} with pytest.raises(exceptions.BadInputError) as err: plumb.add_component(pc, mapping, 'closed', {4: (50, False)}) assert str(err.value) ==\ f"Component '{name}', node {right_node} not found in mapping dict."
def test_components(): plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) original_components = copy.deepcopy(plumb.component_dict) queried_components = plumb.components() assert list(original_components.keys()) == list(queried_components.keys()) queried_components.pop('valve1') assert len(queried_components) == 1 assert len(original_components) == 2 # make sure that changes to the returned dict aren't propagated through to the original assert list(original_components.keys()) == list(plumb.component_dict.keys()) assert list(original_components.keys()) == list(plumb.components().keys())
def test_new_component_state(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) plumb.set_component_state('valve1', 'open') assert plumb.edges() == [(1, 2, 'valve1.A1', { 'FC': utils.teq_to_FC(utils.s_to_micros(0.5)) }), (2, 1, 'valve1.A2', { 'FC': utils.teq_to_FC(utils.s_to_micros(0.2)) }), (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.current_state('valve1') == 'open' assert plumb.current_state('valve2') == 'open'
def test_step_errors(): plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1) fl = 102482.2 with pytest.raises(exceptions.BadInputError) as err: plumb.step(fl) assert str(err.value) == f"timestep ({fl}) must be integer." too_low = 0 with pytest.raises(exceptions.BadInputError) as err: plumb.step(too_low) assert str(err.value) ==\ f"timestep ({too_low}) too low, must be greater than {utils.MIN_TIME_RES_MICROS} us." # This shouldn't raise an error, even though 10.0 is a float plumb.step(1000.0)
def test_remove_add_errors(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) name = 'valve3' wrong_node = 3 right_node = 2 pc = test.create_component(0, 0, 0, 1, name, 'C') mapping = {1: 3, wrong_node: 4} with pytest.raises(exceptions.BadInputError) as err: plumb.add_component(pc, mapping, 'closed', {4: (50, False)}) assert str(err.value) ==\ f"Component '{name}', node {right_node} not found in mapping dict." plumb.remove_component(name) assert plumb.is_valid() assert plumb.time_res == int( utils.s_to_micros(0.2) / utils.DEFAULT_RESOLUTION_SCALE) 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.nodes() == [ (1, { 'body': top.GenericNode(0) }), (2, { 'body': top.GenericNode(0) }), (3, { 'body': top.GenericNode(100) }), ] assert plumb.current_state('valve1') == 'closed' assert plumb.current_state('valve2') == 'open'
def test_current_state(): plumb = test.two_valve_setup( 0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) wrong_name = 'potato' assert plumb.current_state('valve1') == 'closed' assert plumb.current_state('valve2') == 'open' plumb.set_component_state('valve1', 'open') assert plumb.current_state('valve1') == 'open' assert plumb.current_state(['valve1']) == 'open' assert plumb.current_state() == { 'valve1': 'open', 'valve2': 'open' } assert plumb.current_state('valve1', 'valve2') == { 'valve1': 'open', 'valve2': 'open' } list_valves = ['valve1', 'valve2'] assert plumb.current_state(list_valves) == { 'valve1': 'open', 'valve2': 'open' } tuple_valves = ('valve1', 'valve2') assert plumb.current_state(tuple_valves) == { 'valve1': 'open', 'valve2': 'open' } assert plumb.current_state(['valve1'], 'valve2') == { 'valve1': 'open', 'valve2': 'open' } with pytest.raises(exceptions.BadInputError) as err: plumb.current_state(wrong_name) assert str(err.value) == f"Component '{wrong_name}' not found in component dict." with pytest.raises(exceptions.BadInputError) as err: plumb.current_state('valve1', wrong_name, 'valve2') assert str(err.value) == f"Component '{wrong_name}' not found in component dict."
def test_add_remove(): old_lowest_teq = 0.2 plumb = test.two_valve_setup(0.5, old_lowest_teq, 10, utils.CLOSED, 0.5, old_lowest_teq, 10, utils.CLOSED) new_lowest_teq = 0.1 pc = test.create_component(0, 0, 0, new_lowest_teq, 'valve3', 'C') mapping = {1: 3, 2: 4} plumb.add_component(pc, mapping, 'closed', {4: (50, False)}) assert plumb.time_res ==\ int(utils.s_to_micros(new_lowest_teq) / utils.DEFAULT_RESOLUTION_SCALE) plumb.remove_component('valve3') assert plumb.is_valid() assert plumb.time_res ==\ int(utils.s_to_micros(old_lowest_teq) / utils.DEFAULT_RESOLUTION_SCALE) 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.nodes() == [ (1, { 'body': top.GenericNode(0) }), (2, { 'body': top.GenericNode(0) }), (3, { 'body': top.GenericNode(100) }), ] assert plumb.current_state('valve1') == 'closed' assert plumb.current_state('valve2') == 'open'
def test_toggle_listing(): plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) pc_states = {'open': {(1, 2, 'A1'): 0, (2, 1, 'A2'): 0}} pc_edges = [(1, 2, 'A1'), (2, 1, 'A2')] pc = top.PlumbingComponent('tank', pc_states, pc_edges) mapping = {1: 3, 2: 4} plumb.add_component(pc, mapping, 'open') toggles = plumb.list_toggles() assert len(toggles) == 2 assert 'valve1' in toggles assert 'valve2' in toggles assert 'tank' not in toggles
def test_current_pressures(): plumb = test.two_valve_setup( 0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED) plumb.set_pressure(2, 50) plumb.set_pressure(1, 100) assert plumb.current_pressures() == { 1: 100, 2: 50, 3: 100 } assert plumb.current_pressures(1, 2) == { 1: 100, 2: 50 } nodes = [1, 2] assert plumb.current_pressures(nodes) == { 1: 100, 2: 50 } tuple_nodes = (1, 2) assert plumb.current_pressures(tuple_nodes) == { 1: 100, 2: 50 } # I don't know why you'd ever do this but if you want to you can assert plumb.current_pressures([1], 2) == { 1: 100, 2: 50 } assert plumb.current_pressures(3) == 100 wrong_node = 4 with pytest.raises(exceptions.BadInputError) as err: plumb.current_pressures(wrong_node) assert str(err.value) == f"Node {wrong_node} not found in graph."
def test_set_teq(): old_lowest_teq = 0.2 plumb = test.two_valve_setup(0.5, old_lowest_teq, 10, utils.CLOSED, 0.5, old_lowest_teq, 10, utils.CLOSED) new_lowest_teq = 0.1 which_edge = { 'closed': { (2, 1, 'A2'): new_lowest_teq, (1, 2, 'A1'): 7 }, 'open': { (1, 2, 'A1'): 1 } } plumb.set_teq('valve1', which_edge) assert plumb.time_res ==\ int(utils.s_to_micros(new_lowest_teq) / utils.DEFAULT_RESOLUTION_SCALE) assert plumb.edges() == [ (1, 2, 'valve1.A1', { 'FC': utils.teq_to_FC(utils.s_to_micros(7)) }), (2, 1, 'valve1.A2', { 'FC': utils.teq_to_FC(utils.s_to_micros(new_lowest_teq)) }), (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.component_dict['valve1'].states == { 'open': { (1, 2, 'A1'): utils.teq_to_FC(utils.s_to_micros(1)), (2, 1, 'A2'): utils.teq_to_FC(utils.s_to_micros(old_lowest_teq)) }, 'closed': { (1, 2, 'A1'): utils.teq_to_FC(utils.s_to_micros(7)), (2, 1, 'A2'): utils.teq_to_FC(utils.s_to_micros(new_lowest_teq)) } }