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_6(): states = { 'open': { (1, 2, 'A1'): 1, (2, 1, 'A2'): 1, (1, 3, 'B1'): utils.CLOSED, (3, 1, 'B2'): utils.CLOSED } } edges = [(1, 2, 'A1'), (2, 1, 'A2'), (1, 3, 'B1'), (3, 1, 'B2')] pc = top.PlumbingComponent('three', states, edges) mapping = {'three': {1: 1, 2: 2, 3: 3}} pressures = {1: (100, False), 2: (0, False), 3: (0, False)} steady_by = utils.s_to_micros(1) converged = {1: 50, 2: 50, 3: 0} step_plumb = top.PlumbingEngine({'three': pc}, mapping, pressures, {'three': 'open'}) step_state = step_plumb.step(1e6) solve_plumb = top.PlumbingEngine({'three': pc}, mapping, pressures, {'three': 'open'}) solve_state = solve_plumb.solve() len_plumb = top.PlumbingEngine({'three': pc}, mapping, pressures, {'three': 'open'}) 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 = { 'open': { (1, 2, 'A1'): 1, (2, 1, 'A2'): 1 }, 'closed': { (1, 2, 'A1'): top.CLOSED, (2, 1, 'A2'): top.CLOSED }, 'halfway_open': { (1, 2, 'A1'): 100, (2, 1, 'A2'): 100 } } edges = [(1, 2, 'A1'), (2, 1, 'A2')] c1 = top.PlumbingComponent('c1', states, edges) mapping = {'c1': {1: 1, 2: 2}} pressures = {1: (100, False), 2: (0, False)} initial_states = {'c1': 'open'} return top.PlumbingEngine({'c1': c1}, mapping, pressures, initial_states)
def parse_components(self): """Create and store components for plumbing engine.""" for entry in self.package.components(): name = entry['name'] # extract edge list, plus dict of {edge name: edge tuple} edge_dict = extract_edges(entry) edge_list = [] for edge in edge_dict.values(): edge_list.extend(edge) # extract states dict {state_name: {edge: teq}} for each edge # in both directions states = {} for state_name, edges in entry['states'].items(): edge_teqs = {} for edge_name, teqs in edges.items(): fwd_edge, back_edge = edge_dict[edge_name] edge_teqs[fwd_edge] = teqs['fwd'] edge_teqs[back_edge] = teqs['back'] states[state_name] = edge_teqs component = top.PlumbingComponent(name, states, edge_list) self.components[name] = component
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_invalid_component(): 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() plumb = top.PlumbingEngine() with pytest.raises(exceptions.BadInputError) as err: plumb.load_graph({'valve': invalid_pc}, { 1: 1, 2: 2 }, {1: 100}, {'valve': 'open'}) assert str(err.value) == "Node 1 not found in graph." assert not plumb.is_valid() assert len(plumb.errors()) == 2 error = invalid.InvalidComponentName( "Component with name 'valve' is not valid;" " component cannot be loaded in until errors are resolved.", 'valve') assert error in plumb.errors()
def parallel_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) c2 = top.PlumbingComponent('c2', states, edges) mapping = {'c1': {1: 1, 2: 2}, 'c2': {1: 1, 2: 2}} pressures = {1: (0, False), 2: (0, False)} initial_states = {'c1': 'static', 'c2': 'static'} return top.PlumbingEngine({'c1': c1, 'c2': c2}, mapping, pressures, initial_states)
def create_component(s1v1, s1v2, s2v1, s2v2, name, key): pc_states = { 'open': { (1, 2, key + '1'): s1v1, (2, 1, key + '2'): s1v2 }, 'closed': { (1, 2, key + '1'): s2v1, (2, 1, key + '2'): s2v2 } } pc_edges = [(1, 2, key + '1'), (2, 1, key + '2')] pc = top.PlumbingComponent(name, pc_states, pc_edges) return pc
def test_minimum_teq(): normal_teq = 1 teq_too_low = utils.micros_to_s(utils.TEQ_MIN) / 2 states, edges = two_edge_states_edges(normal_teq, normal_teq, normal_teq, teq_too_low) pc = top.PlumbingComponent('valve', states, edges) assert not pc.is_valid() assert len(pc.errors()) == 1 error = invalid.InvalidTeq( f'Provided teq value too low, minimum value is: {utils.micros_to_s(utils.TEQ_MIN)}s', 'valve', 'closed', (2, 1, 'A2'), teq_too_low) assert error in pc.errors()
def test_invalid_keyword(): normal_teq = 1 wrong_keyword_teq = 'potato' states, edges = two_edge_states_edges(normal_teq, normal_teq, normal_teq, wrong_keyword_teq) pc = top.PlumbingComponent('valve', states, edges) assert not pc.is_valid() assert len(pc.errors()) == 1 error = invalid.InvalidTeq( f"Invalid provided teq value ('potato'), accepted keyword is: '{utils.CLOSED}'", 'valve', 'closed', (2, 1, 'A2'), wrong_keyword_teq) assert error in pc.errors()
def test_component_dicts_remain_unchanged(): teq = 5 pc_states, edges = two_edge_states_edges(teq, teq, teq, teq) _ = top.PlumbingComponent('valve', pc_states, edges) assert pc_states == two_edge_states_edges(teq, teq, teq, teq)[0] assert pc_states != { 'open': { (1, 2, 'A1'): utils.teq_to_FC(teq), (2, 1, 'A2'): utils.teq_to_FC(teq) }, 'closed': { (1, 2, 'B1'): utils.teq_to_FC(teq), (2, 1, 'B2'): utils.teq_to_FC(teq) } }
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_plumbing_component_setup(): pc1_states, pc1_edges = two_edge_states_edges(0, 0, utils.CLOSED, utils.CLOSED) pc1 = top.PlumbingComponent('valve1', pc1_states, pc1_edges) assert pc1.current_state is None assert list(pc1.component_graph.edges(keys=True)) == [(1, 2, 'A1'), (2, 1, 'A2')] assert list(pc1.component_graph.nodes()) == [1, 2] assert pc1.states == { 'open': { (1, 2, 'A1'): utils.FC_MAX, (2, 1, 'A2'): utils.FC_MAX }, 'closed': { (1, 2, 'A1'): 0, (2, 1, 'A2'): 0 } } assert pc1.is_valid() assert not pc1.errors()
def test_duplicate_edges(): states = { 'open': { (1, 2, 'A1'): 0, (2, 1, 'A2'): 0 }, 'closed': { (1, 2, 'A1'): 0, (2, 1, 'A2'): 0 } } edge = (1, 2, 'A1') edges = [edge, edge, (2, 1, 'A2')] pc = top.PlumbingComponent('valve', states, edges) assert not pc.is_valid() error = invalid.InvalidComponentEdge( f"Duplicate edges '{edge}' found in edge list.", edge) assert error in pc.errors()
def test_edge_id_error(): wrong_node = 5 states = { 'open': { (wrong_node, 2, 'A1'): 0, (2, 1, 'A2'): 0 }, 'closed': { (1, 2, 'A1'): 0, (2, 1, 'A2'): 0 } } edges = [(1, 2, 'A1'), (2, 1, 'A2')] pc = top.PlumbingComponent('valve', states, edges) assert not pc.is_valid() error = invalid.InvalidComponentEdge( f"Edge '({wrong_node}, 2, 'A1')' not found in provided edge list.", (wrong_node, 2, 'A1')) assert error in pc.errors()
def test_multiple_errors(): normal_teq = 1 teq_too_low = utils.micros_to_s(utils.TEQ_MIN) / 2 wrong_keyword_teq = 'potato' states, edges = two_edge_states_edges(normal_teq, normal_teq, teq_too_low, wrong_keyword_teq) pc = top.PlumbingComponent('valve', states, edges) assert not pc.is_valid() assert len(pc.errors()) == 2 error1 = invalid.InvalidTeq( f"Provided teq value too low, minimum value is: {utils.micros_to_s(utils.TEQ_MIN)}s", 'valve', 'closed', (1, 2, 'A1'), teq_too_low) error2 = invalid.InvalidTeq( f"Invalid provided teq value ('{wrong_keyword_teq}')," f" accepted keyword is: '{utils.CLOSED}'", 'valve', 'closed', (2, 1, 'A2'), wrong_keyword_teq) assert error1 in pc.errors() assert error2 in pc.errors()
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)