CJahns commited on
Commit
919458a
·
1 Parent(s): e9a20eb

Upload 2 files

Browse files
Files changed (2) hide show
  1. Input_Jahr_2021.xlsx +2 -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:29deba7c045949c344a272c36778075df949d2f030ad240cfb8ed6912f73d8f5
3
- size 994606
 
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
- import linopy
16
- import openpyxl
 
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=10, min_value=0, max_value=400, label="Natural gas price [€/MWh]", step=10)
36
 
37
  # Slider for CO2 price [€/t]
38
- price_co2 = st.slider(value=80, min_value=0, max_value=400, label="CO2 price [€/t CO2eq]", step=10)
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
- # %% [markdown]
49
- # Read Sets
 
 
 
 
 
 
 
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')[1:168]
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
- ### Model
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 * c_var_i * dt).sum() - ((y_ch.sel(i = iPtG) / eff_i.sel(i = iPtG)) * price_h2 * dt).sum() == C_op, name = 'C_op_sum')
 
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) - (y.sel(i = iSto) / eff_i.sel(i = iSto)) * dt + y_ch.sel(i = iSto) * eff_i.sel(i = iSto) * dt) == 0, name = 'filling_level')
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