naohiro701 commited on
Commit
0d4f673
·
verified ·
1 Parent(s): 46fd3a4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +141 -47
app.py CHANGED
@@ -44,6 +44,8 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
44
  river_cf = data['river hourly capacity factor']
45
  demand_cf = data['demand hourly capacity factor']
46
 
 
 
47
  regions = ['region1']
48
  technologies = ['solar', 'onshore_wind', 'offshore_wind', 'river']
49
  capacity_factor = {
@@ -57,71 +59,146 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
57
  battery_cost_per_mwh = battery_cost
58
  battery_efficiency = 0.9
59
 
60
- demand = demand_cf * yearly_demand / 100 * 1000 * 1000
 
61
 
 
62
  renewable_capacity = pulp.LpVariable.dicts("renewable_capacity",
63
  [(r, g) for r in regions for g in technologies],
64
  lowBound=0, cat='Continuous')
65
  battery_capacity = pulp.LpVariable("battery_capacity", lowBound=0, cat='Continuous')
66
 
67
- model = pulp.LpProblem("EnergySystemOptimizationWithBattery", pulp.LpMinimize)
 
 
 
 
 
 
 
 
68
 
69
- # Objective: minimize total cost (renewable capacities and battery)
70
- model += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
71
- for r in regions for g in technologies]) + \
72
  battery_capacity * battery_cost_per_mwh, "TotalCost"
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  # Solve the initial model to find the optimal solution
75
  model.solve()
76
  optimal_cost = pulp.value(model.objective)
77
 
78
  # MGA: Generate alternative solutions for selected technologies only
79
  alternative_solutions = []
 
80
  for threshold in thresholds:
81
  relaxed_cost = optimal_cost * (1 + threshold)
82
- for tech in selected_tech: # Run only for selected technologies
83
- # Minimize capacity of each technology
84
- alt_model_min = pulp.LpProblem(f"AlternativeModel_Min_{tech}_{threshold}", pulp.LpMinimize)
85
- alt_model_min += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
86
- for r in regions for g in technologies]) + battery_capacity * battery_cost_per_mwh <= relaxed_cost
87
-
88
- # Copy original constraints with unique names
89
- for name, constraint in model.constraints.items():
90
- alt_model_min += constraint.copy(), f"{name}_min_{tech}_{threshold}"
91
-
92
- # Minimize the capacity of the selected technology
93
- alt_model_min += renewable_capacity[('region1', tech)], f"Minimize_{tech}_Capacity"
94
- alt_model_min.solve()
95
- if pulp.LpStatus[alt_model_min.status] == 'Optimal':
96
- alternative_solutions.append({
97
- 'threshold': threshold,
98
- 'type': 'min',
99
- 'technology': tech,
100
- 'solution': {g: renewable_capacity[('region1', g)].varValue for g in technologies},
101
- 'battery_capacity': battery_capacity.varValue,
102
- 'total_cost': pulp.value(alt_model_min.objective)
103
- })
104
-
105
- # Maximize capacity of each technology
106
- alt_model_max = pulp.LpProblem(f"AlternativeModel_Max_{tech}_{threshold}", pulp.LpMinimize)
107
- alt_model_max += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
108
- for r in regions for g in technologies]) + battery_capacity * battery_cost_per_mwh <= relaxed_cost
109
-
110
- # Copy original constraints with unique names
111
- for name, constraint in model.constraints.items():
112
- alt_model_max += constraint.copy(), f"{name}_max_{tech}_{threshold}"
113
-
114
- # Maximize the capacity of the selected technology
115
- alt_model_max += -renewable_capacity[('region1', tech)], f"Maximize_{tech}_Capacity"
116
- alt_model_max.solve()
117
- if pulp.LpStatus[alt_model_max.status] == 'Optimal':
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  alternative_solutions.append({
119
  'threshold': threshold,
120
- 'type': 'max',
121
  'technology': tech,
122
- 'solution': {g: renewable_capacity[('region1', g)].varValue for g in technologies},
123
- 'battery_capacity': battery_capacity.varValue,
124
- 'total_cost': pulp.value(alt_model_max.objective)
125
  })
126
 
127
  return alternative_solutions
@@ -149,7 +226,6 @@ def plot_capacity_distribution(alternative_solutions, selected_technologies):
149
 
150
  # Function to create cost breakdown stacked bar plot for each threshold and technology type
151
  def plot_cost_breakdown(alternative_solutions, selected_technologies, renewable_capacity_cost, battery_cost_per_mwh):
152
- # Generate a bar plot for each case based on threshold and technology type
153
  for idx, sol in enumerate(alternative_solutions):
154
  cost_data = {
155
  'Technology': selected_technologies + ['Battery'],
@@ -162,6 +238,19 @@ def plot_cost_breakdown(alternative_solutions, selected_technologies, renewable_
162
  labels={'Cost': 'Cost (¥)'})
163
  st.plotly_chart(fig_bar, use_container_width=True, key=f"cost_plot_{idx}")
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  # Streamlit UI setup
166
  st.set_page_config(page_title='Renewable Energy System Optimization with MGA', layout='wide')
167
  st.title('Modeling to Generate Alternatives (MGA) in Renewable Energy System Optimization')
@@ -188,7 +277,8 @@ with st.sidebar:
188
  selected_technologies = st.multiselect("Select Technologies to Optimize", ['solar', 'onshore_wind', 'offshore_wind', 'river'], default=['solar', 'onshore_wind', 'offshore_wind', 'river'])
189
 
190
  if st.button("Run MGA Optimization"):
191
- 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, [t / 100 for t in thresholds], selected_technologies)
 
192
 
193
  if alternative_solutions:
194
  # Display capacity distribution using violin plots
@@ -202,3 +292,7 @@ if st.button("Run MGA Optimization"):
202
  'offshore_wind': offshore_wind_cost,
203
  'river': river_cost
204
  }, battery_cost)
 
 
 
 
 
44
  river_cf = data['river hourly capacity factor']
45
  demand_cf = data['demand hourly capacity factor']
46
 
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 = {
 
59
  battery_cost_per_mwh = battery_cost
60
  battery_efficiency = 0.9
61
 
62
+ # Create the model
63
+ model = pulp.LpProblem("EnergySystemOptimizationWithBattery", pulp.LpMinimize)
64
 
65
+ # Variables
66
  renewable_capacity = pulp.LpVariable.dicts("renewable_capacity",
67
  [(r, g) for r in regions for g in technologies],
68
  lowBound=0, cat='Continuous')
69
  battery_capacity = pulp.LpVariable("battery_capacity", lowBound=0, cat='Continuous')
70
 
71
+ renewable_generation = pulp.LpVariable.dicts("renewable_generation",
72
+ [(t, g) for t in time_steps for g in technologies],
73
+ lowBound=0, cat='Continuous')
74
+ battery_charge = pulp.LpVariable.dicts("battery_charge",
75
+ time_steps, lowBound=0, cat='Continuous')
76
+ battery_discharge = pulp.LpVariable.dicts("battery_discharge",
77
+ time_steps, lowBound=0, cat='Continuous')
78
+ battery_storage = pulp.LpVariable.dicts("battery_storage",
79
+ time_steps, lowBound=0, cat='Continuous')
80
 
81
+ # Objective: minimize total cost
82
+ model += pulp.lpSum([renewable_capacity[('region1', g)] * renewable_capacity_cost[g] for g in technologies]) + \
 
83
  battery_capacity * battery_cost_per_mwh, "TotalCost"
84
 
85
+ # Constraints
86
+
87
+ # Renewable generation constraints
88
+ for t in time_steps:
89
+ for g in technologies:
90
+ model += renewable_generation[(t, g)] <= renewable_capacity[('region1', g)] * capacity_factor[g].iloc[t], f"GenCap_{t}_{g}"
91
+
92
+ # Energy balance constraints
93
+ for t in time_steps:
94
+ total_generation = pulp.lpSum([renewable_generation[(t, g)] for g in technologies])
95
+ model += total_generation + battery_discharge[t] == demand.iloc[t] + battery_charge[t], f"EnergyBalance_{t}"
96
+
97
+ # Battery storage constraints
98
+ for t in time_steps:
99
+ if t == 0:
100
+ model += battery_storage[t] == battery_capacity * 0.5 + battery_charge[t] * battery_efficiency - battery_discharge[t] / battery_efficiency, f"StorageBalance_{t}"
101
+ else:
102
+ model += battery_storage[t] == battery_storage[t - 1] + battery_charge[t] * battery_efficiency - battery_discharge[t] / battery_efficiency, f"StorageBalance_{t}"
103
+ model += battery_storage[t] <= battery_capacity, f"StorageCapacity_{t}"
104
+ model += battery_storage[t] >= 0, f"StorageNonNegative_{t}"
105
+
106
+ # Renewable capacity constraints (within specified ranges)
107
+ model += renewable_capacity[('region1', 'solar')] >= solar_range[0], "SolarCapMin"
108
+ model += renewable_capacity[('region1', 'solar')] <= solar_range[1], "SolarCapMax"
109
+
110
+ model += renewable_capacity[('region1', 'onshore_wind')] >= wind_range[0], "WindCapMin"
111
+ model += renewable_capacity[('region1', 'onshore_wind')] <= wind_range[1], "WindCapMax"
112
+
113
+ model += renewable_capacity[('region1', 'offshore_wind')] >= offshore_wind_range[0], "OffshoreWindCapMin"
114
+ model += renewable_capacity[('region1', 'offshore_wind')] <= offshore_wind_range[1], "OffshoreWindCapMax"
115
+
116
+ model += renewable_capacity[('region1', 'river')] >= river_range[0], "RiverCapMin"
117
+ model += renewable_capacity[('region1', 'river')] <= river_range[1], "RiverCapMax"
118
+
119
  # Solve the initial model to find the optimal solution
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
130
+ alt_model = pulp.LpProblem(f"AlternativeModel_{tech}_{threshold}", pulp.LpMinimize)
131
+
132
+ # Variables (need to create new variables for the new model)
133
+ alt_renewable_capacity = pulp.LpVariable.dicts("renewable_capacity",
134
+ [(r, g) for r in regions for g in technologies],
135
+ lowBound=0, cat='Continuous')
136
+ alt_battery_capacity = pulp.LpVariable("battery_capacity", lowBound=0, cat='Continuous')
137
+
138
+ alt_renewable_generation = pulp.LpVariable.dicts("renewable_generation",
139
+ [(t, g) for t in time_steps for g in technologies],
140
+ lowBound=0, cat='Continuous')
141
+ alt_battery_charge = pulp.LpVariable.dicts("battery_charge",
142
+ time_steps, lowBound=0, cat='Continuous')
143
+ alt_battery_discharge = pulp.LpVariable.dicts("battery_discharge",
144
+ time_steps, lowBound=0, cat='Continuous')
145
+ alt_battery_storage = pulp.LpVariable.dicts("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]) + \
156
+ alt_battery_capacity * battery_cost_per_mwh <= relaxed_cost, "CostConstraint"
157
+
158
+ # Constraints
159
+
160
+ # Renewable generation constraints
161
+ for t in time_steps:
162
+ for g in technologies:
163
+ alt_model += alt_renewable_generation[(t, g)] <= alt_renewable_capacity[('region1', g)] * capacity_factor[g].iloc[t], f"GenCap_{t}_{g}"
164
+
165
+ # Energy balance constraints
166
+ for t in time_steps:
167
+ total_generation = pulp.lpSum([alt_renewable_generation[(t, g)] for g in technologies])
168
+ alt_model += total_generation + alt_battery_discharge[t] == demand.iloc[t] + alt_battery_charge[t], f"EnergyBalance_{t}"
169
+
170
+ # Battery storage constraints
171
+ for t in time_steps:
172
+ if t == 0:
173
+ alt_model += alt_battery_storage[t] == alt_battery_capacity * 0.5 + alt_battery_charge[t] * battery_efficiency - alt_battery_discharge[t] / battery_efficiency, f"StorageBalance_{t}"
174
+ else:
175
+ alt_model += alt_battery_storage[t] == alt_battery_storage[t - 1] + alt_battery_charge[t] * battery_efficiency - alt_battery_discharge[t] / battery_efficiency, f"StorageBalance_{t}"
176
+ alt_model += alt_battery_storage[t] <= alt_battery_capacity, f"StorageCapacity_{t}"
177
+ alt_model += alt_battery_storage[t] >= 0, f"StorageNonNegative_{t}"
178
+
179
+ # Renewable capacity constraints (within specified ranges)
180
+ alt_model += alt_renewable_capacity[('region1', 'solar')] >= solar_range[0], "SolarCapMin"
181
+ alt_model += alt_renewable_capacity[('region1', 'solar')] <= solar_range[1], "SolarCapMax"
182
+
183
+ alt_model += alt_renewable_capacity[('region1', 'onshore_wind')] >= wind_range[0], "WindCapMin"
184
+ alt_model += alt_renewable_capacity[('region1', 'onshore_wind')] <= wind_range[1], "WindCapMax"
185
+
186
+ alt_model += alt_renewable_capacity[('region1', 'offshore_wind')] >= offshore_wind_range[0], "OffshoreWindCapMin"
187
+ alt_model += alt_renewable_capacity[('region1', 'offshore_wind')] <= offshore_wind_range[1], "OffshoreWindCapMax"
188
+
189
+ alt_model += alt_renewable_capacity[('region1', 'river')] >= river_range[0], "RiverCapMin"
190
+ alt_model += alt_renewable_capacity[('region1', 'river')] <= river_range[1], "RiverCapMax"
191
+
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
 
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):
 
229
  for idx, sol in enumerate(alternative_solutions):
230
  cost_data = {
231
  'Technology': selected_technologies + ['Battery'],
 
238
  labels={'Cost': 'Cost (¥)'})
239
  st.plotly_chart(fig_bar, use_container_width=True, key=f"cost_plot_{idx}")
240
 
241
+ # Function to plot generation and demand over time
242
+ def plot_generation_demand(data, alternative_solution, time_steps, technologies):
243
+ total_generation = np.zeros(len(time_steps))
244
+ for g in technologies:
245
+ gen = np.array(data[f'{g} hourly capacity factor']) * alternative_solution['solution'][g]
246
+ total_generation += gen
247
+ demand = data['demand hourly capacity factor'] * data['demand hourly capacity factor'].sum()
248
+ fig = px.line(x=time_steps, y=[total_generation, demand],
249
+ labels={'x': 'Time', 'value': 'Power (MW)', 'variable': 'Legend'},
250
+ title='Total Generation and Demand Over Time')
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')
 
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
 
292
  'offshore_wind': offshore_wind_cost,
293
  'river': river_cost
294
  }, battery_cost)
295
+
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)