naohiro701 commited on
Commit
1dd074a
·
verified ·
1 Parent(s): 233e7a0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -32
app.py CHANGED
@@ -27,12 +27,7 @@ def get_renewable_energy_data(city_code):
27
  return result_df, None
28
 
29
  # Optimize energy system and use MGA
30
- def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range, thresholds, selected_tech):
31
- data, error = get_renewable_energy_data(city_code)
32
- if error:
33
- st.error(error)
34
- return None
35
-
36
  for col in data.columns[1:]:
37
  data[col] = pd.to_numeric(data[col], errors='coerce')
38
  data = data.fillna(0)
@@ -47,7 +42,6 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
47
  demand = demand_cf * yearly_demand * 1e6 / demand_cf.sum() # MW
48
 
49
  regions = ['region1']
50
- technologies = ['solar', 'onshore_wind', 'offshore_wind', 'river']
51
  capacity_factor = {
52
  'solar': solar_cf,
53
  'onshore_wind': onshore_wind_cf,
@@ -120,10 +114,22 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
120
  model.solve()
121
  optimal_cost = pulp.value(model.objective)
122
 
 
 
 
 
 
 
 
 
 
 
123
  # MGA: Generate alternative solutions for selected technologies only
124
- alternative_solutions = []
125
 
126
  for threshold in thresholds:
 
 
127
  relaxed_cost = optimal_cost * (1 + threshold)
128
  for tech in selected_tech:
129
  # Create a copy of the model
@@ -145,11 +151,8 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
145
  alt_battery_storage = pulp.LpVariable.dicts("alt_battery_storage",
146
  time_steps, lowBound=0, cat='Continuous')
147
 
148
- # Objective: minimize or maximize the capacity of the selected technology
149
- if threshold == 0:
150
- alt_model += alt_renewable_capacity[('region1', tech)], f"Minimize_{tech}_Capacity"
151
- else:
152
- alt_model += -alt_renewable_capacity[('region1', tech)], f"Maximize_{tech}_Capacity"
153
 
154
  # Add the cost constraint
155
  alt_model += pulp.lpSum([alt_renewable_capacity[('region1', g)] * renewable_capacity_cost[g] for g in technologies]) + \
@@ -192,14 +195,15 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
192
  # Solve the alternative model
193
  alt_model.solve()
194
  if pulp.LpStatus[alt_model.status] == 'Optimal':
195
- alternative_solutions.append({
196
  'threshold': threshold,
197
- 'type': 'min' if threshold == 0 else 'max',
198
  'technology': tech,
199
  'solution': {g: alt_renewable_capacity[('region1', g)].varValue for g in technologies},
200
  'battery_capacity': alt_battery_capacity.varValue,
201
  'total_cost': pulp.value(alt_model.objective)
202
- })
 
203
 
204
  return alternative_solutions
205
 
@@ -212,17 +216,18 @@ def plot_capacity_distribution(alternative_solutions, selected_technologies):
212
  capacity_data.append({
213
  'Threshold (%)': sol['threshold'] * 100,
214
  'Technology': tech,
215
- 'Capacity (MW)': sol['solution'][tech]
 
 
216
  })
217
 
218
  capacity_df = pd.DataFrame(capacity_data)
219
 
220
- # Create violin plot with Plotly Express (horizontal)
221
- fig_violin = px.violin(capacity_df, y="Technology", x="Capacity (MW)", color="Technology",
222
- box=True, points="all", orientation="h", title="Capacity Distribution by Technology")
223
- fig_violin.update_layout(yaxis_title="Technology", xaxis_title="Installed Capacity (MW)")
224
-
225
- return fig_violin
226
 
227
  # Function to create cost breakdown stacked bar plot for each threshold and technology type
228
  def plot_cost_breakdown(alternative_solutions, selected_technologies, renewable_capacity_cost, battery_cost_per_mwh):
@@ -234,7 +239,7 @@ def plot_cost_breakdown(alternative_solutions, selected_technologies, renewable_
234
  cost_df = pd.DataFrame(cost_data)
235
 
236
  # Create stacked bar chart with unique key to avoid StreamlitDuplicateElementId error
237
- fig_bar = px.bar(cost_df, x='Technology', y='Cost', title=f"Cost Breakdown (Threshold: {sol['threshold'] * 100}%, Type: {sol['type']})",
238
  labels={'Cost': 'Cost (¥)'})
239
  st.plotly_chart(fig_bar, use_container_width=True, key=f"cost_plot_{idx}")
240
 
@@ -251,6 +256,26 @@ def plot_generation_demand(data, alternative_solution, time_steps, technologies)
251
  fig.update_traces(mode='lines')
252
  st.plotly_chart(fig, use_container_width=True)
253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  # Streamlit UI setup
255
  st.set_page_config(page_title='Renewable Energy System Optimization with MGA', layout='wide')
256
  st.title('Modeling to Generate Alternatives (MGA) in Renewable Energy System Optimization')
@@ -269,24 +294,36 @@ with st.sidebar:
269
  wind_range = st.slider("Onshore Wind Capacity Range (MW)", 0, 10000, (0, 10000))
270
  offshore_wind_range = st.slider("Offshore Wind Capacity Range (MW)", 0, 10000, (0, 10000))
271
  river_range = st.slider("River Capacity Range (MW)", 0, 10000, (0, 10000))
 
 
272
  thresholds = st.multiselect(
273
  "Select MGA Cost Deviation Thresholds (%)",
274
- list(np.arange(0, 11, 0.5)),
275
- default=[0, 5, 10]
276
  )
277
- selected_technologies = st.multiselect("Select Technologies to Optimize", ['solar', 'onshore_wind', 'offshore_wind', 'river'], default=['solar', 'onshore_wind', 'offshore_wind', 'river'])
278
 
279
  if st.button("Run MGA Optimization"):
280
  thresholds = [t / 100 for t in thresholds] # Convert percentages to decimals
281
- alternative_solutions = optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range, thresholds, selected_technologies)
 
 
 
 
 
 
 
 
 
 
 
282
 
283
  if alternative_solutions:
284
- # Display capacity distribution using violin plots
285
- fig_violin = plot_capacity_distribution(alternative_solutions, selected_technologies)
286
- st.plotly_chart(fig_violin, use_container_width=True)
287
 
288
  # Display cost breakdown stacked bar plots for each case
289
- plot_cost_breakdown(alternative_solutions, selected_technologies, {
290
  'solar': solar_cost,
291
  'onshore_wind': onshore_wind_cost,
292
  'offshore_wind': offshore_wind_cost,
@@ -296,3 +333,18 @@ if st.button("Run MGA Optimization"):
296
  # Plot generation and demand over time for the first alternative solution
297
  st.header("Generation and Demand Over Time")
298
  plot_generation_demand(data, alternative_solutions[0], data['Time'], technologies)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  return result_df, None
28
 
29
  # Optimize energy system and use MGA
30
+ def optimize_energy_system(data, technologies, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range, thresholds, selected_tech):
 
 
 
 
 
31
  for col in data.columns[1:]:
32
  data[col] = pd.to_numeric(data[col], errors='coerce')
33
  data = data.fillna(0)
 
42
  demand = demand_cf * yearly_demand * 1e6 / demand_cf.sum() # MW
43
 
44
  regions = ['region1']
 
45
  capacity_factor = {
46
  'solar': solar_cf,
47
  'onshore_wind': onshore_wind_cf,
 
114
  model.solve()
115
  optimal_cost = pulp.value(model.objective)
116
 
117
+ # Collect the initial solution
118
+ initial_solution = {
119
+ 'threshold': 0,
120
+ 'type': 'optimal',
121
+ 'technology': 'all',
122
+ 'solution': {g: renewable_capacity[('region1', g)].varValue for g in technologies},
123
+ 'battery_capacity': battery_capacity.varValue,
124
+ 'total_cost': optimal_cost
125
+ }
126
+
127
  # MGA: Generate alternative solutions for selected technologies only
128
+ alternative_solutions = [initial_solution]
129
 
130
  for threshold in thresholds:
131
+ if threshold == 0:
132
+ continue # Already have the optimal solution
133
  relaxed_cost = optimal_cost * (1 + threshold)
134
  for tech in selected_tech:
135
  # Create a copy of the model
 
151
  alt_battery_storage = pulp.LpVariable.dicts("alt_battery_storage",
152
  time_steps, lowBound=0, cat='Continuous')
153
 
154
+ # Objective: maximize the capacity of the selected technology
155
+ alt_model += -alt_renewable_capacity[('region1', tech)], f"Maximize_{tech}_Capacity"
 
 
 
156
 
157
  # Add the cost constraint
158
  alt_model += pulp.lpSum([alt_renewable_capacity[('region1', g)] * renewable_capacity_cost[g] for g in technologies]) + \
 
195
  # Solve the alternative model
196
  alt_model.solve()
197
  if pulp.LpStatus[alt_model.status] == 'Optimal':
198
+ alt_solution = {
199
  'threshold': threshold,
200
+ 'type': 'max',
201
  'technology': tech,
202
  'solution': {g: alt_renewable_capacity[('region1', g)].varValue for g in technologies},
203
  'battery_capacity': alt_battery_capacity.varValue,
204
  'total_cost': pulp.value(alt_model.objective)
205
+ }
206
+ alternative_solutions.append(alt_solution)
207
 
208
  return alternative_solutions
209
 
 
216
  capacity_data.append({
217
  'Threshold (%)': sol['threshold'] * 100,
218
  'Technology': tech,
219
+ 'Capacity (MW)': sol['solution'][tech],
220
+ 'Type': sol['type'],
221
+ 'Varied Technology': sol['technology']
222
  })
223
 
224
  capacity_df = pd.DataFrame(capacity_data)
225
 
226
+ # Create line plot to show capacity changes over thresholds
227
+ fig_line = px.line(capacity_df, x="Threshold (%)", y="Capacity (MW)", color="Technology",
228
+ line_dash="Varied Technology", markers=True,
229
+ title="Technology Capacity Changes Over Thresholds")
230
+ st.plotly_chart(fig_line, use_container_width=True)
 
231
 
232
  # Function to create cost breakdown stacked bar plot for each threshold and technology type
233
  def plot_cost_breakdown(alternative_solutions, selected_technologies, renewable_capacity_cost, battery_cost_per_mwh):
 
239
  cost_df = pd.DataFrame(cost_data)
240
 
241
  # Create stacked bar chart with unique key to avoid StreamlitDuplicateElementId error
242
+ fig_bar = px.bar(cost_df, x='Technology', y='Cost', title=f"Cost Breakdown (Threshold: {sol['threshold'] * 100}%, Technology Varied: {sol['technology']})",
243
  labels={'Cost': 'Cost (¥)'})
244
  st.plotly_chart(fig_bar, use_container_width=True, key=f"cost_plot_{idx}")
245
 
 
256
  fig.update_traces(mode='lines')
257
  st.plotly_chart(fig, use_container_width=True)
258
 
259
+ # Function to plot battery storage levels over time
260
+ def plot_battery_storage(data, alternative_solution, time_steps):
261
+ # For simplicity, re-calculate battery storage levels
262
+ battery_storage = np.zeros(len(time_steps))
263
+ battery_capacity = alternative_solution['battery_capacity']
264
+ battery_charge = data['battery_charge'] if 'battery_charge' in data else np.zeros(len(time_steps))
265
+ battery_discharge = data['battery_discharge'] if 'battery_discharge' in data else np.zeros(len(time_steps))
266
+ battery_efficiency = 0.9
267
+
268
+ for t in range(len(time_steps)):
269
+ if t == 0:
270
+ battery_storage[t] = battery_capacity * 0.5 + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency)
271
+ else:
272
+ battery_storage[t] = battery_storage[t - 1] + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency)
273
+
274
+ fig = px.line(x=time_steps, y=battery_storage,
275
+ labels={'x': 'Time', 'y': 'Battery Storage Level (MWh)'},
276
+ title='Battery Storage Level Over Time')
277
+ st.plotly_chart(fig, use_container_width=True)
278
+
279
  # Streamlit UI setup
280
  st.set_page_config(page_title='Renewable Energy System Optimization with MGA', layout='wide')
281
  st.title('Modeling to Generate Alternatives (MGA) in Renewable Energy System Optimization')
 
294
  wind_range = st.slider("Onshore Wind Capacity Range (MW)", 0, 10000, (0, 10000))
295
  offshore_wind_range = st.slider("Offshore Wind Capacity Range (MW)", 0, 10000, (0, 10000))
296
  river_range = st.slider("River Capacity Range (MW)", 0, 10000, (0, 10000))
297
+ threshold_options = list(np.arange(0, 11, 0.5))
298
+ threshold_default = [0, 5, 10]
299
  thresholds = st.multiselect(
300
  "Select MGA Cost Deviation Thresholds (%)",
301
+ threshold_options,
302
+ default=threshold_default
303
  )
304
+ selected_technologies = st.multiselect("Select Technologies to Optimize", ['solar', 'onshore_wind', 'offshore_wind', 'river'], default=['solar'])
305
 
306
  if st.button("Run MGA Optimization"):
307
  thresholds = [t / 100 for t in thresholds] # Convert percentages to decimals
308
+
309
+ # Fetch data
310
+ data, error = get_renewable_energy_data(city_code)
311
+ if error:
312
+ st.error(error)
313
+ st.stop()
314
+
315
+ # Define technologies
316
+ technologies = ['solar', 'onshore_wind', 'offshore_wind', 'river']
317
+
318
+ # Run optimization
319
+ alternative_solutions = optimize_energy_system(data, technologies, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range, thresholds, selected_technologies)
320
 
321
  if alternative_solutions:
322
+ # Display capacity distribution using line plots
323
+ plot_capacity_distribution(alternative_solutions, technologies)
 
324
 
325
  # Display cost breakdown stacked bar plots for each case
326
+ plot_cost_breakdown(alternative_solutions, technologies, {
327
  'solar': solar_cost,
328
  'onshore_wind': onshore_wind_cost,
329
  'offshore_wind': offshore_wind_cost,
 
333
  # Plot generation and demand over time for the first alternative solution
334
  st.header("Generation and Demand Over Time")
335
  plot_generation_demand(data, alternative_solutions[0], data['Time'], technologies)
336
+
337
+ # Plot battery storage levels over time
338
+ st.header("Battery Storage Level Over Time")
339
+ plot_battery_storage(data, alternative_solutions[0], data['Time'])
340
+
341
+ # Display alternative solutions in a table
342
+ st.header("Alternative Solutions Summary")
343
+ summary_data = []
344
+ for sol in alternative_solutions:
345
+ row = {'Threshold (%)': sol['threshold'] * 100, 'Type': sol['type'], 'Varied Technology': sol['technology'], 'Battery Capacity (MWh)': sol['battery_capacity'], 'Total Cost (¥)': sol['total_cost']}
346
+ for tech in technologies:
347
+ row[f"{tech.capitalize()} Capacity (MW)"] = sol['solution'][tech]
348
+ summary_data.append(row)
349
+ summary_df = pd.DataFrame(summary_data)
350
+ st.dataframe(summary_df)