Spaces:
Runtime error
Runtime error
Upload 2 files
Browse files- Input_Jahr_2021.xlsx +2 -2
- app.py +72 -16
Input_Jahr_2021.xlsx
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:630332987718f2aa27e4cd917a37a95ad9d81d4682367982be8301d79445267b
|
3 |
+
size 994601
|
app.py
CHANGED
@@ -10,16 +10,21 @@ This is a temporary script file.
|
|
10 |
|
11 |
|
12 |
from numpy import arange
|
|
|
13 |
import xarray as xr
|
|
|
14 |
import highspy
|
15 |
-
|
16 |
-
|
|
|
17 |
from linopy import Model, EQUAL
|
|
|
18 |
import pandas as pd
|
|
|
19 |
import plotly.express as px
|
20 |
##import gurobipy
|
21 |
|
22 |
-
|
23 |
import streamlit as st
|
24 |
|
25 |
|
@@ -32,10 +37,10 @@ if url_excel == None:
|
|
32 |
|
33 |
# # %%
|
34 |
# # Slider for gas price [€/MWh_th]
|
35 |
-
price_gas = st.slider(value=
|
36 |
|
37 |
# Slider for CO2 price [€/t]
|
38 |
-
price_co2 = st.slider(value=
|
39 |
|
40 |
# Slider for CO2 limit [mio. t]
|
41 |
limit_co2 = st.slider(value=400, min_value=0, max_value=750, label="CO2 limit [mio. t]", step=50)
|
@@ -45,20 +50,29 @@ price_h2 = st.slider(value=100, min_value=0, max_value=300, label="Hydrogen pric
|
|
45 |
|
46 |
# %%
|
47 |
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
# %%
|
52 |
## Define all sets for the model
|
53 |
# Timesteps
|
54 |
df_excel= pd.read_excel(url_excel, sheet_name = 'Timesteps_All', header=None)
|
55 |
-
t = pd.Index(df_excel.iloc[:,0], name = 't')
|
56 |
#t = pd.Index(df_excel.iloc[:,0], name = 't')
|
57 |
|
58 |
# Technologies
|
59 |
df_excel = pd.read_excel(url_excel, sheet_name = 'Technologies')
|
60 |
i = pd.Index(df_excel.iloc[:,0], name = 'i')
|
61 |
|
|
|
|
|
62 |
|
63 |
df_excel = pd.read_excel(url_excel, sheet_name = 'Technologies')
|
64 |
iConv = pd.Index(df_excel.iloc[0:7,2], name = 'iConv')
|
@@ -78,7 +92,7 @@ iHyRes = pd.Index(df_excel.iloc[0:1,10], name = 'iHyRes')
|
|
78 |
# %%
|
79 |
### Parameters
|
80 |
# CO2 limit (from slider)
|
81 |
-
l_co2 = limit_co2
|
82 |
p_co2 = price_co2
|
83 |
|
84 |
# length of timesteps
|
@@ -92,6 +106,7 @@ df_excel = df_excel.rename(columns = {'Timesteps':'t', 'Unnamed: 1':'Demand'})
|
|
92 |
df_excel = df_excel.fillna(0)
|
93 |
df_excel = df_excel.set_index('t')
|
94 |
D_t = df_excel.iloc[:,0].to_xarray()
|
|
|
95 |
|
96 |
## Efficiencies
|
97 |
df_excel = pd.read_excel(url_excel, sheet_name = 'Efficiency')
|
@@ -127,7 +142,7 @@ df_excel = df_excel.rename(columns = {'All':'i', 'Unnamed: 1':'InvCosts'})
|
|
127 |
df_excel = i.to_frame().reset_index(drop=True).merge(df_excel, how = 'left')
|
128 |
df_excel = df_excel.fillna(0)
|
129 |
df_excel = df_excel.set_index('i')
|
130 |
-
c_inv_i = df_excel.iloc[:,0].to_xarray()
|
131 |
|
132 |
# Emission factor
|
133 |
df_excel = pd.read_excel(url_excel, sheet_name = 'EmFactor')
|
@@ -155,6 +170,7 @@ df_test2 = df_excel
|
|
155 |
#df_test = df_excel.set_index(['Timesteps', 'PV', 'WindOn', 'WindOff', 'RoR']).stack([0])
|
156 |
#df_test.index = df_test.index.set_names(['t','i'])
|
157 |
s_t_r_iRes = df_excel.to_xarray().rename({'level_1': 'i','Timesteps':'t'})
|
|
|
158 |
#s_t_r_iRes = df_excel.iloc[:,0].to_xarray()
|
159 |
|
160 |
# Base capacities
|
@@ -180,6 +196,9 @@ df_excel = df_excel.fillna(0)
|
|
180 |
df_excel = df_excel.set_index('t')
|
181 |
h_t = df_excel.iloc[:,0].to_xarray()
|
182 |
|
|
|
|
|
|
|
183 |
# %%
|
184 |
### Variables
|
185 |
m = Model()
|
@@ -194,7 +213,7 @@ y_ch = m.add_variables(coords = [t,i], name = 'y_ch', lower = 0) # Electricit
|
|
194 |
l = m.add_variables(coords = [t,i], name = 'l', lower = 0) # Storage filling level
|
195 |
w = m.add_variables(coords = [t], name = 'w', lower = 0) # RES curtailment
|
196 |
|
197 |
-
|
198 |
|
199 |
## Objective function
|
200 |
C_tot = C_op + C_inv
|
@@ -202,17 +221,21 @@ m.add_objective(C_tot)
|
|
202 |
|
203 |
## Costs terms for objective function
|
204 |
# Operational costs minus revenue for produced hydrogen
|
205 |
-
C_op_sum = m.add_constraints((y
|
|
|
206 |
|
207 |
# Investment costs
|
208 |
C_inv_sum = m.add_constraints((K * c_inv_i).sum() == C_inv, name = 'C_inv_sum')
|
209 |
|
210 |
## Load serving
|
211 |
-
loadserve_t = m.add_constraints(((y * dt).sum(dims = 'i') - (w * dt) == D_t.sel(t = t) * dt), name = 'load')
|
212 |
|
213 |
## Maximum capacity limit
|
214 |
maxcap_i_t = m.add_constraints((y - K <= K_0_i), name = 'max_cap')
|
215 |
|
|
|
|
|
|
|
216 |
## Maximum storage charging and discharging
|
217 |
maxcha_iSto_t = m.add_constraints((y.sel(i = iSto) + y_ch.sel(i = iSto) - K.sel(i = iSto) <= K_0_i.sel(i = iSto)), name = 'max_cha')
|
218 |
|
@@ -229,17 +252,50 @@ maxcapsto_iSto_t = m.add_constraints((l.sel(i = iSto) - K.sel(i = iSto) * e2p_iS
|
|
229 |
filling_iHydro_t = m.add_constraints(l.sel(i = iHyRes) - l.sel(i = iHyRes).roll(t = -1) + y.sel(i = iHyRes) * dt == h_t.sel(t = t) * dt, name = 'filling_level_hydro')
|
230 |
|
231 |
## Filling level restriction other storages --> Ist Kreisbedingung erfüllt? (JR)
|
232 |
-
filling_iSto_t = m.add_constraints(l.sel(i = iSto) - (l.sel(i = iSto).roll(t = -1)
|
233 |
|
234 |
## CO2 limit --> ggf. hier auch mit Subset arbeiten (Technologien, die Brennstoff verbrauchen). (JR)
|
235 |
-
CO2_limit = m.add_constraints(((y / eff_i) * co2_factor_i * dt).sum() <= l_co2, name = 'CO2_limit')
|
|
|
236 |
|
|
|
237 |
m.solve(solver_name = 'highs')
|
238 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
|
240 |
# %%
|
241 |
# Installed Cap
|
242 |
# Assuming df_excel has columns 'All' and 'Capacities'
|
243 |
-
fig = px.bar(m.solution['K'].to_dataframe().reset_index(), y='i', x='K', orientation='h', title='Installed Capacities', color='i')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
|
|
|
245 |
fig
|
|
|
10 |
|
11 |
|
12 |
from numpy import arange
|
13 |
+
# %%
|
14 |
import xarray as xr
|
15 |
+
# %%
|
16 |
import highspy
|
17 |
+
|
18 |
+
|
19 |
+
# %%
|
20 |
from linopy import Model, EQUAL
|
21 |
+
# %%
|
22 |
import pandas as pd
|
23 |
+
#%%
|
24 |
import plotly.express as px
|
25 |
##import gurobipy
|
26 |
|
27 |
+
# %%
|
28 |
import streamlit as st
|
29 |
|
30 |
|
|
|
37 |
|
38 |
# # %%
|
39 |
# # Slider for gas price [€/MWh_th]
|
40 |
+
price_gas = st.slider(value=100, min_value=0, max_value=400, label="Natural gas price [€/MWh]", step=10)
|
41 |
|
42 |
# Slider for CO2 price [€/t]
|
43 |
+
price_co2 = st.slider(value=0, min_value=0, max_value=400, label="CO2 price [€/t CO2eq]", step=10)
|
44 |
|
45 |
# Slider for CO2 limit [mio. t]
|
46 |
limit_co2 = st.slider(value=400, min_value=0, max_value=750, label="CO2 limit [mio. t]", step=50)
|
|
|
50 |
|
51 |
# %%
|
52 |
|
53 |
+
|
54 |
+
|
55 |
+
#time_steps_aggregate = 6
|
56 |
+
#= xr_profiles.rolling( time_step = time_steps_aggregate).mean().sel(time_step = time[0::time_steps_aggregate])
|
57 |
+
|
58 |
+
def timstep_aggregate(time_steps_aggregate, xr ):
|
59 |
+
return xr.rolling( t = time_steps_aggregate).mean().sel(t = t[0::time_steps_aggregate])
|
60 |
+
|
61 |
+
|
62 |
|
63 |
# %%
|
64 |
## Define all sets for the model
|
65 |
# Timesteps
|
66 |
df_excel= pd.read_excel(url_excel, sheet_name = 'Timesteps_All', header=None)
|
67 |
+
t = pd.Index(df_excel.iloc[:,0], name = 't')
|
68 |
#t = pd.Index(df_excel.iloc[:,0], name = 't')
|
69 |
|
70 |
# Technologies
|
71 |
df_excel = pd.read_excel(url_excel, sheet_name = 'Technologies')
|
72 |
i = pd.Index(df_excel.iloc[:,0], name = 'i')
|
73 |
|
74 |
+
multiselect = st.multiselect(label = 'Technolgy invest', options=i)
|
75 |
+
|
76 |
|
77 |
df_excel = pd.read_excel(url_excel, sheet_name = 'Technologies')
|
78 |
iConv = pd.Index(df_excel.iloc[0:7,2], name = 'iConv')
|
|
|
92 |
# %%
|
93 |
### Parameters
|
94 |
# CO2 limit (from slider)
|
95 |
+
l_co2 = limit_co2*10**6
|
96 |
p_co2 = price_co2
|
97 |
|
98 |
# length of timesteps
|
|
|
106 |
df_excel = df_excel.fillna(0)
|
107 |
df_excel = df_excel.set_index('t')
|
108 |
D_t = df_excel.iloc[:,0].to_xarray()
|
109 |
+
D_t = timstep_aggregate(6,D_t)
|
110 |
|
111 |
## Efficiencies
|
112 |
df_excel = pd.read_excel(url_excel, sheet_name = 'Efficiency')
|
|
|
142 |
df_excel = i.to_frame().reset_index(drop=True).merge(df_excel, how = 'left')
|
143 |
df_excel = df_excel.fillna(0)
|
144 |
df_excel = df_excel.set_index('i')
|
145 |
+
c_inv_i = df_excel.iloc[:,0].to_xarray()*1000*0.1 # kw to MW and annuity factor
|
146 |
|
147 |
# Emission factor
|
148 |
df_excel = pd.read_excel(url_excel, sheet_name = 'EmFactor')
|
|
|
170 |
#df_test = df_excel.set_index(['Timesteps', 'PV', 'WindOn', 'WindOff', 'RoR']).stack([0])
|
171 |
#df_test.index = df_test.index.set_names(['t','i'])
|
172 |
s_t_r_iRes = df_excel.to_xarray().rename({'level_1': 'i','Timesteps':'t'})
|
173 |
+
s_t_r_iRes = timstep_aggregate(6,s_t_r_iRes)
|
174 |
#s_t_r_iRes = df_excel.iloc[:,0].to_xarray()
|
175 |
|
176 |
# Base capacities
|
|
|
196 |
df_excel = df_excel.set_index('t')
|
197 |
h_t = df_excel.iloc[:,0].to_xarray()
|
198 |
|
199 |
+
|
200 |
+
|
201 |
+
t = D_t.get_index('t')
|
202 |
# %%
|
203 |
### Variables
|
204 |
m = Model()
|
|
|
213 |
l = m.add_variables(coords = [t,i], name = 'l', lower = 0) # Storage filling level
|
214 |
w = m.add_variables(coords = [t], name = 'w', lower = 0) # RES curtailment
|
215 |
|
216 |
+
partial_year_factor = (8760/len(t))
|
217 |
|
218 |
## Objective function
|
219 |
C_tot = C_op + C_inv
|
|
|
221 |
|
222 |
## Costs terms for objective function
|
223 |
# Operational costs minus revenue for produced hydrogen
|
224 |
+
C_op_sum = m.add_constraints((y.sel(i = c_var_i.get_index('i')) * c_var_i * dt).sum()*partial_year_factor - \
|
225 |
+
((y_ch.sel(i = iPtG) * eff_i.sel(i = iPtG)) * price_h2 * dt).sum()*partial_year_factor == C_op, name = 'C_op_sum')
|
226 |
|
227 |
# Investment costs
|
228 |
C_inv_sum = m.add_constraints((K * c_inv_i).sum() == C_inv, name = 'C_inv_sum')
|
229 |
|
230 |
## Load serving
|
231 |
+
loadserve_t = m.add_constraints(((y * dt).sum(dims = 'i') - (w * dt) - y_ch.sum(dims = 'i') == D_t.sel(t = t) * dt), name = 'load')
|
232 |
|
233 |
## Maximum capacity limit
|
234 |
maxcap_i_t = m.add_constraints((y - K <= K_0_i), name = 'max_cap')
|
235 |
|
236 |
+
## Maximum capacity limit
|
237 |
+
maxcap_invest_i = m.add_constraints((K.sel(i = ['Electrolyzer','RoR','Biomass','H2']) <= 0), name = 'max_cap_invest')
|
238 |
+
|
239 |
## Maximum storage charging and discharging
|
240 |
maxcha_iSto_t = m.add_constraints((y.sel(i = iSto) + y_ch.sel(i = iSto) - K.sel(i = iSto) <= K_0_i.sel(i = iSto)), name = 'max_cha')
|
241 |
|
|
|
252 |
filling_iHydro_t = m.add_constraints(l.sel(i = iHyRes) - l.sel(i = iHyRes).roll(t = -1) + y.sel(i = iHyRes) * dt == h_t.sel(t = t) * dt, name = 'filling_level_hydro')
|
253 |
|
254 |
## Filling level restriction other storages --> Ist Kreisbedingung erfüllt? (JR)
|
255 |
+
filling_iSto_t = m.add_constraints(l.sel(i = iSto) - (l.sel(i = iSto).roll(t = -1) + (y.sel(i = iSto) ) * dt - y_ch.sel(i = iSto) * eff_i.sel(i = iSto) * dt) == 0, name = 'filling_level')
|
256 |
|
257 |
## CO2 limit --> ggf. hier auch mit Subset arbeiten (Technologien, die Brennstoff verbrauchen). (JR)
|
258 |
+
CO2_limit = m.add_constraints(((y / eff_i) * co2_factor_i * dt).sum()* partial_year_factor <= l_co2 , name = 'CO2_limit')
|
259 |
+
|
260 |
|
261 |
+
# %%
|
262 |
m.solve(solver_name = 'highs')
|
263 |
|
264 |
+
# %%
|
265 |
+
m.solution['K'].to_dataframe().reset_index()
|
266 |
+
|
267 |
+
# %%
|
268 |
+
#((m.solution['y'] / eff_i) * co2_factor_i * dt).sum()*partial_year_factor
|
269 |
+
|
270 |
+
|
271 |
+
# %%
|
272 |
+
#m.solution['C_inv']
|
273 |
|
274 |
# %%
|
275 |
# Installed Cap
|
276 |
# Assuming df_excel has columns 'All' and 'Capacities'
|
277 |
+
fig = px.bar(m.solution['K'].to_dataframe().reset_index() + K_0_i.to_dataframe().reset_index().values, y='i', x='K', orientation='h', title='Installed Capacities', color='i')
|
278 |
+
|
279 |
+
fig
|
280 |
+
|
281 |
+
# %%
|
282 |
+
fig = px.bar(m.solution['K'].to_dataframe().reset_index(), y='i', x='K', orientation='h', title='New Capacities', color='i')
|
283 |
+
|
284 |
+
fig
|
285 |
+
|
286 |
+
|
287 |
+
i_with_capacity = m.solution['K'].where( m.solution['K'] > 0).dropna(dim = 'i').get_index('i')
|
288 |
+
# %%
|
289 |
+
fig = px.area(m.solution['y'].sel(i = i_with_capacity).to_dataframe().reset_index(), y='y', x='t', title='Production', color='i')
|
290 |
+
|
291 |
+
fig
|
292 |
+
# %%
|
293 |
+
# %%
|
294 |
+
fig = px.line(m.solution['l'].to_dataframe().reset_index(), y='l', x='t', title='Fillng level', color='i')
|
295 |
+
|
296 |
+
fig
|
297 |
+
|
298 |
+
# %%
|
299 |
|
300 |
+
fig = px.line(m.solution['y_ch'].to_dataframe().reset_index(), y='y_ch', x='t', title='Production', color='i')
|
301 |
fig
|