diff --git a/tests/test_esipp_network.py b/tests/test_esipp_network.py index 743f24609d6a0c1ecdfaa0b60f0a75f66d6f3e86..2617dbf6f074fe6a32439d99076a16d0e28c5031 100644 --- a/tests/test_esipp_network.py +++ b/tests/test_esipp_network.py @@ -23,16 +23,12 @@ from src.topupopt.data.misc.utils import generate_pseudo_unique_key # ***************************************************************************** # ***************************************************************************** -# TODO: add test for directed arcs between import and export nodes with static losses - class TestNetwork: # ************************************************************************* # ************************************************************************* def test_arc_technologies_static_losses(self): - # ********************************************************************* - # ********************************************************************* number_time_intervals = 3 number_scenarios = 2 @@ -2001,6 +1997,15 @@ class TestNetwork: error_triggered = True assert error_triggered + # undirected arcs cannot involve import nor export nodes + + error_triggered = False + try: + net.add_undirected_arc(node_key_a="I", node_key_b="E", arcs=lossy_arcs) + except ValueError: + error_triggered = True + assert error_triggered + # ********************************************************************* # trigger errors using non-identified nodes diff --git a/tests/test_esipp_problem.py b/tests/test_esipp_problem.py index 6ec6d625f2bbe16dd14c555197b2d621b727a457..eb712858bc11749ee5d1183498cf3492020b981c 100644 --- a/tests/test_esipp_problem.py +++ b/tests/test_esipp_problem.py @@ -460,7 +460,7 @@ class TestESIPPProblem: # ********************************************************************* # validation - # TODO: make a dict with the results and a for loop to reduce extent + # the arc should be installed since it is required for feasibility assert ( True @@ -469,39 +469,18 @@ class TestESIPPProblem: .options_selected ) - # the flows should be 1.0, 0.0 and 2.0 - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, q, 0)]), - 1.0, - abs_tol=1e-6, - ) - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, q, 1)]), - 0.0, - abs_tol=1e-6, - ) - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, q, 2)]), - 2.0, - abs_tol=1e-6, - ) + # flows + true_v_glljqk = { + ("mynet", node_IMP, node_A, 0, q, 0): 1, + ("mynet", node_IMP, node_A, 0, q, 1): 0, + ("mynet", node_IMP, node_A, 0, q, 2): 2, + ("mynet", node_A, node_EXP, 0, q, 0): 0, + ("mynet", node_A, node_EXP, 0, q, 1): 1.5, + ("mynet", node_A, node_EXP, 0, q, 2): 0 + } - # the flows should be 1.0, 0.0 and 2.0 - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_A, node_EXP, 0, q, 0)]), - 0.0, - abs_tol=1e-6, - ) - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_A, node_EXP, 0, q, 1)]), - 1.5, - abs_tol=1e-6, - ) - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_A, node_EXP, 0, q, 2)]), - 0.0, - abs_tol=1e-6, - ) + for key, v in true_v_glljqk.items(): + assert math.isclose(pyo.value(ipp.instance.var_v_glljqk[key]), v, abs_tol=1e-6) # arc amplitude should be two assert math.isclose( @@ -1102,36 +1081,16 @@ class TestESIPPProblem: ) # the flows should be 1.0, 0.0 and 2.0 - - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, 0, 0)]), - 1.0, - abs_tol=1e-6, - ) - - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, 0, 1)]), - 0.0, - abs_tol=1e-6, - ) - - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, 0, 2)]), - 2.0, - abs_tol=1e-6, - ) - - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, 1, 0)]), - 2.5, - abs_tol=1e-6, - ) - - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, 1, 1)]), - 0.6, - abs_tol=1e-6, - ) + true_v_glljqk = { + ("mynet", node_IMP, node_A, 0, 0, 0): 1, + ("mynet", node_IMP, node_A, 0, 0, 1): 0, + ("mynet", node_IMP, node_A, 0, 0, 2): 2, + ("mynet", node_IMP, node_A, 0, 1, 0): 2.5, + ("mynet", node_IMP, node_A, 0, 1, 1): 0.6, + } + + for key, v in true_v_glljqk.items(): + assert math.isclose(pyo.value(ipp.instance.var_v_glljqk[key]), v, abs_tol=1e-6) # arc amplitude should be two @@ -7675,14 +7634,12 @@ class TestESIPPProblem: 0.1, abs_tol=abs_tol, ) - + # ************************************************************************* # ************************************************************************* - # TODO: this test is failing - def test_directed_arc_static_downstream_new(self): - + # time q = 0 tf = EconomicTimeFrame( @@ -7692,18 +7649,19 @@ class TestESIPPProblem: time_intervals={q: (0,)}, time_interval_durations={q: (1,)}, ) - number_intervals = 2 + number_intervals = 1 number_periods = 2 - # 4 nodes: one import, one export, two supply/demand nodes + # 4 nodes: one import, one export, two supply/demand nodes + mynet = Network() - # import node + # import node imp_node_key = generate_pseudo_unique_key(mynet.nodes()) mynet.add_import_node( node_key=imp_node_key, prices={ - (q, p, k): ResourcePrice(prices=0.1, volumes=None) + (q, p, k): ResourcePrice(prices=1 + 0.1, volumes=None) for p in range(number_periods) for k in range(number_intervals) }, @@ -7711,24 +7669,19 @@ class TestESIPPProblem: # other nodes node_A = generate_pseudo_unique_key(mynet.nodes()) - mynet.add_source_sink_node(node_key=node_A, base_flow={(q, 0): 1.0, (q, 1): 1.3}) - - # add arcs + mynet.add_source_sink_node(node_key=node_A, base_flow={(q, 0): 1.0}) - # IA1 - arcs_ia1 = Arcs( - name="IA1", - efficiency={(q, 0): 0.9, (q, 1): 0.9}, - efficiency_reverse=None, - static_loss={(0, q, 0): 0.0, (0, q, 1): 0.1}, - capacity=tuple([0.5 / 0.9]), - minimum_cost=tuple([0.1]), - specific_capacity_cost=0, + # add arcs + # IA1 + mynet.add_preexisting_directed_arc( + node_key_a=imp_node_key, + node_key_b=node_A, + efficiency={(q, 0): 0.9}, + static_loss={(q, 0, 0): 0.1}, + capacity=0.5, capacity_is_instantaneous=False, - validate=True, ) - mynet.add_directed_arc(node_key_a=imp_node_key, node_key_b=node_A, arcs=arcs_ia1) - + # IA2 arcs_ia2 = Arcs( name="IA2", @@ -7743,29 +7696,34 @@ class TestESIPPProblem: ) mynet.add_directed_arc(node_key_a=imp_node_key, node_key_b=node_A, arcs=arcs_ia2) - # identify node types + # identify node types mynet.identify_node_types() - # no sos, regular time intervals + # no sos, regular time intervals ipp = self.build_solve_ipp( - # solver='cbc', + solver='cbc', # TODO: make this work with other solvers solver_options={}, plot_results=False, # True, print_solver_output=False, networks={"mynet": mynet}, time_frame=tf, - static_losses_mode=True, + # static_losses_mode=True, + static_losses_mode=InfrastructurePlanningProblem.STATIC_LOSS_MODE_ARR, mandatory_arcs=[], - max_number_parallel_arcs={} + max_number_parallel_arcs={}, ) - + + # ************************************************************************** + # all arcs should be installed (they are not new) + assert ( True in ipp.networks["mynet"] .edges[(imp_node_key, node_A, 0)][Network.KEY_ARC_TECH] .options_selected ) + assert ( True in ipp.networks["mynet"] @@ -7784,40 +7742,28 @@ class TestESIPPProblem: # there should be imports abs_tol = 1e-6 - assert math.isclose( - flow_in[("mynet", 0, 0)], (1.2 + 0.1 / 0.9 + 1.0 + 0.1), abs_tol=abs_tol - ) + assert math.isclose(flow_in[("mynet", 0, 0)], (1.0 + 0.1), abs_tol=abs_tol) # there should be no exports + abs_tol = 1e-6 + assert math.isclose(flow_out[("mynet", 0, 0)], 0, abs_tol=abs_tol) - # interval 0: flow through IA1 must be 0 - # interval 1: flow through IA1 must be 0.1+0.1/0.9 + # flow through IA1 must be 0.1 abs_tol = 1e-6 assert math.isclose( pyo.value(ipp.instance.var_v_glljqk[("mynet", imp_node_key, node_A, 0, 0, 0)]), - 0, - abs_tol=abs_tol, - ) - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", imp_node_key, node_A, 0, 0, 1)]), - 0.1 + 0.1 / 0.9, + 0.1, abs_tol=abs_tol, ) - # interval 0: flow through IA2 must be 1.0 - # interval 1: flow through IA2 must be 1.2 + # flow through IA2 must be 1.0 assert math.isclose( pyo.value(ipp.instance.var_v_glljqk[("mynet", imp_node_key, node_A, 1, 0, 0)]), 1.0, abs_tol=abs_tol, ) - assert math.isclose( - pyo.value(ipp.instance.var_v_glljqk[("mynet", imp_node_key, node_A, 1, 0, 1)]), - 1.2, - abs_tol=abs_tol, - ) # ************************************************************************* # ************************************************************************* @@ -7887,7 +7833,8 @@ class TestESIPPProblem: print_solver_output=False, networks={"mynet": mynet}, time_frame=tf, - static_losses_mode=True, + # static_losses_mode=True, + static_losses_mode=InfrastructurePlanningProblem.STATIC_LOSS_MODE_ARR, mandatory_arcs=[], max_number_parallel_arcs={}, )