Skip to content

Commit 6b45770

Browse files
committed
Create test_objfunc.py
1 parent 1600398 commit 6b45770

File tree

1 file changed

+205
-0
lines changed

1 file changed

+205
-0
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import unittest
2+
from pownet.optim_model import objfunc
3+
4+
5+
class TestObjectiveFunctions(unittest.TestCase):
6+
7+
def setUp(self):
8+
"""Set up common test data."""
9+
self.timesteps = range(3) # As per user request
10+
self.thermal_units = ["coal_unit_1", "gas_unit_1"]
11+
self.nondispatch_units = ["hydro_1", "solar_1"]
12+
13+
def test_get_thermal_fixed_coeff(self):
14+
thermal_rated_capacity = {"coal_unit_1": 300, "gas_unit_1": 150}
15+
thermal_fixed_cost = {"coal_unit_1": 10, "gas_unit_1": 12}
16+
17+
expected_coeffs = {
18+
("coal_unit_1", 0): 300 * 10,
19+
("coal_unit_1", 1): 300 * 10,
20+
("coal_unit_1", 2): 300 * 10,
21+
("gas_unit_1", 0): 150 * 12,
22+
("gas_unit_1", 1): 150 * 12,
23+
("gas_unit_1", 2): 150 * 12,
24+
}
25+
26+
actual_coeffs = objfunc.get_thermal_fixed_coeff(
27+
timesteps=self.timesteps,
28+
thermal_units=self.thermal_units,
29+
thermal_fixed_cost=thermal_fixed_cost,
30+
thermal_rated_capacity=thermal_rated_capacity,
31+
)
32+
self.assertEqual(actual_coeffs, expected_coeffs)
33+
34+
def test_get_thermal_opex_coeff_step_1(self):
35+
step_k = 1
36+
thermal_opex = {"coal_unit_1": 5, "gas_unit_1": 3}
37+
fuel_contracts = {"coal_unit_1": "coal_A", "gas_unit_1": "gas_B"}
38+
# contract_costs: (fuel_type, time_index) -> cost
39+
contract_costs = {
40+
("coal_A", 0): 20,
41+
("coal_A", 1): 21,
42+
("coal_A", 2): 20,
43+
("coal_A", 24): 25,
44+
("gas_B", 0): 30,
45+
("gas_B", 1): 32,
46+
("gas_B", 2): 31,
47+
("gas_B", 24): 35,
48+
}
49+
thermal_heat_rate = {"coal_unit_1": 1.5, "gas_unit_1": 1.2}
50+
51+
expected_coeffs = {
52+
# (unit, t): (contract_costs[(fuel_contracts[unit], t + (step_k - 1) * 24)] * thermal_heat_rate[unit]) + thermal_opex[unit]
53+
("coal_unit_1", 0): (contract_costs[("coal_A", 0 + (1 - 1) * 24)] * 1.5)
54+
+ 5, # (20 * 1.5) + 5 = 30 + 5 = 35
55+
("coal_unit_1", 1): (contract_costs[("coal_A", 1 + (1 - 1) * 24)] * 1.5)
56+
+ 5, # (21 * 1.5) + 5 = 31.5 + 5 = 36.5
57+
("coal_unit_1", 2): (contract_costs[("coal_A", 2 + (1 - 1) * 24)] * 1.5)
58+
+ 5, # (20 * 1.5) + 5 = 30 + 5 = 35
59+
("gas_unit_1", 0): (contract_costs[("gas_B", 0 + (1 - 1) * 24)] * 1.2)
60+
+ 3, # (30 * 1.2) + 3 = 36 + 3 = 39
61+
("gas_unit_1", 1): (contract_costs[("gas_B", 1 + (1 - 1) * 24)] * 1.2)
62+
+ 3, # (32 * 1.2) + 3 = 38.4 + 3 = 41.4
63+
("gas_unit_1", 2): (contract_costs[("gas_B", 2 + (1 - 1) * 24)] * 1.2)
64+
+ 3, # (31 * 1.2) + 3 = 37.2 + 3 = 40.2
65+
}
66+
67+
actual_coeffs = objfunc.get_thermal_opex_coeff(
68+
step_k=step_k,
69+
timesteps=self.timesteps,
70+
thermal_units=self.thermal_units,
71+
thermal_opex=thermal_opex,
72+
fuel_contracts=fuel_contracts,
73+
contract_costs=contract_costs,
74+
thermal_heat_rate=thermal_heat_rate,
75+
)
76+
self.assertEqual(actual_coeffs, expected_coeffs)
77+
78+
def test_get_thermal_opex_coeff_step_2(self):
79+
step_k = 2 # Test with a different step_k
80+
thermal_opex = {"coal_unit_1": 5, "gas_unit_1": 3}
81+
fuel_contracts = {"coal_unit_1": "coal_A", "gas_unit_1": "gas_B"}
82+
contract_costs = {
83+
# Need costs for t + (2-1)*24 => t + 24
84+
("coal_A", 24): 25,
85+
("coal_A", 25): 26,
86+
("coal_A", 26): 24,
87+
("gas_B", 24): 35,
88+
("gas_B", 25): 36,
89+
("gas_B", 26): 34,
90+
}
91+
thermal_heat_rate = {"coal_unit_1": 1.5, "gas_unit_1": 1.2}
92+
93+
expected_coeffs = {
94+
("coal_unit_1", 0): (contract_costs[("coal_A", 0 + (2 - 1) * 24)] * 1.5)
95+
+ 5, # (25 * 1.5) + 5 = 37.5 + 5 = 42.5
96+
("coal_unit_1", 1): (contract_costs[("coal_A", 1 + (2 - 1) * 24)] * 1.5)
97+
+ 5, # (26 * 1.5) + 5 = 39 + 5 = 44
98+
("coal_unit_1", 2): (contract_costs[("coal_A", 2 + (2 - 1) * 24)] * 1.5)
99+
+ 5, # (24 * 1.5) + 5 = 36 + 5 = 41
100+
("gas_unit_1", 0): (contract_costs[("gas_B", 0 + (2 - 1) * 24)] * 1.2)
101+
+ 3, # (35 * 1.2) + 3 = 42 + 3 = 45
102+
("gas_unit_1", 1): (contract_costs[("gas_B", 1 + (2 - 1) * 24)] * 1.2)
103+
+ 3, # (36 * 1.2) + 3 = 43.2 + 3 = 46.2
104+
("gas_unit_1", 2): (contract_costs[("gas_B", 2 + (2 - 1) * 24)] * 1.2)
105+
+ 3, # (34 * 1.2) + 3 = 40.8 + 3 = 43.8
106+
}
107+
108+
actual_coeffs = objfunc.get_thermal_opex_coeff(
109+
step_k=step_k,
110+
timesteps=self.timesteps,
111+
thermal_units=self.thermal_units,
112+
thermal_opex=thermal_opex,
113+
fuel_contracts=fuel_contracts,
114+
contract_costs=contract_costs,
115+
thermal_heat_rate=thermal_heat_rate,
116+
)
117+
self.assertEqual(actual_coeffs, expected_coeffs)
118+
119+
def test_get_thermal_startup_coeff(self):
120+
thermal_rated_capacity = {"coal_unit_1": 300, "gas_unit_1": 150}
121+
thermal_startup_cost = {
122+
"coal_unit_1": 500,
123+
"gas_unit_1": 250,
124+
} # Cost per unit of capacity
125+
126+
expected_coeffs = {
127+
("coal_unit_1", 0): 300 * 500,
128+
("coal_unit_1", 1): 300 * 500,
129+
("coal_unit_1", 2): 300 * 500,
130+
("gas_unit_1", 0): 150 * 250,
131+
("gas_unit_1", 1): 150 * 250,
132+
("gas_unit_1", 2): 150 * 250,
133+
}
134+
actual_coeffs = objfunc.get_thermal_startup_coeff(
135+
timesteps=self.timesteps,
136+
thermal_units=self.thermal_units,
137+
thermal_startup_cost=thermal_startup_cost,
138+
thermal_rated_capacity=thermal_rated_capacity,
139+
)
140+
self.assertEqual(actual_coeffs, expected_coeffs)
141+
142+
def test_get_marginal_cost_coeff_step_1(self):
143+
step_k = 1
144+
nondispatch_contracts = {"hydro_1": "hydro_A", "solar_1": "solar_B"}
145+
# contract_costs: (contract_name, time_index) -> cost
146+
contract_costs = {
147+
("hydro_A", 0): 5,
148+
("hydro_A", 1): 5.5,
149+
("hydro_A", 2): 5.2,
150+
("hydro_A", 24): 6,
151+
("solar_B", 0): 2,
152+
("solar_B", 1): 2.1,
153+
("solar_B", 2): 2.0,
154+
("solar_B", 24): 2.5,
155+
}
156+
expected_coeffs = {
157+
# (unit, t): contract_costs[(nondispatch_contracts[unit], t + (step_k - 1) * 24)]
158+
("hydro_1", 0): contract_costs[("hydro_A", 0 + (1 - 1) * 24)], # 5
159+
("hydro_1", 1): contract_costs[("hydro_A", 1 + (1 - 1) * 24)], # 5.5
160+
("hydro_1", 2): contract_costs[("hydro_A", 2 + (1 - 1) * 24)], # 5.2
161+
("solar_1", 0): contract_costs[("solar_B", 0 + (1 - 1) * 24)], # 2
162+
("solar_1", 1): contract_costs[("solar_B", 1 + (1 - 1) * 24)], # 2.1
163+
("solar_1", 2): contract_costs[("solar_B", 2 + (1 - 1) * 24)], # 2.0
164+
}
165+
actual_coeffs = objfunc.get_marginal_cost_coeff(
166+
step_k=step_k,
167+
timesteps=self.timesteps,
168+
units=self.nondispatch_units,
169+
nondispatch_contracts=nondispatch_contracts,
170+
contract_costs=contract_costs,
171+
)
172+
self.assertEqual(actual_coeffs, expected_coeffs)
173+
174+
def test_get_marginal_cost_coeff_step_2(self):
175+
step_k = 2 # Test with a different step_k
176+
nondispatch_contracts = {"hydro_1": "hydro_A", "solar_1": "solar_B"}
177+
contract_costs = {
178+
# Need costs for t + (2-1)*24 => t + 24
179+
("hydro_A", 24): 6,
180+
("hydro_A", 25): 6.5,
181+
("hydro_A", 26): 6.2,
182+
("solar_B", 24): 3,
183+
("solar_B", 25): 3.1,
184+
("solar_B", 26): 3.0,
185+
}
186+
expected_coeffs = {
187+
("hydro_1", 0): contract_costs[("hydro_A", 0 + (2 - 1) * 24)], # 6
188+
("hydro_1", 1): contract_costs[("hydro_A", 1 + (2 - 1) * 24)], # 6.5
189+
("hydro_1", 2): contract_costs[("hydro_A", 2 + (2 - 1) * 24)], # 6.2
190+
("solar_1", 0): contract_costs[("solar_B", 0 + (2 - 1) * 24)], # 3
191+
("solar_1", 1): contract_costs[("solar_B", 1 + (2 - 1) * 24)], # 3.1
192+
("solar_1", 2): contract_costs[("solar_B", 2 + (2 - 1) * 24)], # 3.0
193+
}
194+
actual_coeffs = objfunc.get_marginal_cost_coeff(
195+
step_k=step_k,
196+
timesteps=self.timesteps,
197+
units=self.nondispatch_units,
198+
nondispatch_contracts=nondispatch_contracts,
199+
contract_costs=contract_costs,
200+
)
201+
self.assertEqual(actual_coeffs, expected_coeffs)
202+
203+
204+
if __name__ == "__main__":
205+
unittest.main()

0 commit comments

Comments
 (0)