Compare commits
	
		
			21 Commits
		
	
	
		
			cb0bd2c3e0
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f1b2959143 | ||
|  | df2f953678 | ||
|  | 3740136d7c | ||
|  | e04e01e943 | ||
|  | 9f472b4bf4 | ||
|  | 127f005dcd | ||
|  | c5edf456c5 | ||
|  | d8ece46e14 | ||
|  | 566ebca6cd | ||
|  | c8c37b756c | ||
|  | 4f1a47d505 | ||
|  | ad9b5e6a19 | ||
|  | 33871fba77 | ||
|  | 9d143399ed | ||
|  | 72d4ce811e | ||
|  | 060fa5bff1 | ||
|  | ebebd2d481 | ||
|  | a330946f71 | ||
|  | 32e8e59c82 | ||
|  | c4ec4590c2 | ||
|  | 4364411485 | 
							
								
								
									
										184
									
								
								EnergySystem.py
									
									
									
									
									
								
							
							
						
						
									
										184
									
								
								EnergySystem.py
									
									
									
									
									
								
							| @@ -21,6 +21,13 @@ class EnergySystem: | ||||
|         self.summer_week_soc = [] | ||||
|         self.autumn_week_soc = [] | ||||
|         self.winter_week_soc = [] | ||||
|         self.factory_demand = [] | ||||
|         self.buy_price_kWh = [] | ||||
|         self.sell_price_kWh = [] | ||||
|         self.pv_generated_kWh = [] | ||||
|         self.grid_need_power_kW = [] | ||||
|         self.time = [] | ||||
|         self.ess_rest = 0 | ||||
|         self.granularity = 4 | ||||
|         self.season_step = self.granularity * 24 * 7 * 12 | ||||
|         self.season_start= self.granularity * 24 * 7 * 2 | ||||
| @@ -30,110 +37,155 @@ class EnergySystem: | ||||
|     def get_cost(self): | ||||
|         return self.ess.get_cost()+self.pv.get_cost() | ||||
|  | ||||
|     # 优先使用PV供电给工厂 - 如果PV输出能满足工厂的需求,则直接供电,多余的电能用来给ESS充电。 | ||||
|     # PV不足时使用ESS补充 - 如果PV输出不足以满足工厂需求,首先从ESS获取所需电量。 | ||||
|     # 如果ESS也不足以满足需求,再从电网获取 - 当ESS中的存储电量也不足以补充时,再从电网购买剩余所需电量。 | ||||
|     def simulate(self, data, time_interval): | ||||
|         """ | ||||
|         The program will use the PV to supply the factory first. If the PV output can meet the factory's demand, it will be directly powered, and the excess electrical energy will be used to charge the ESS. Program will use the PV to supply the Ess. | ||||
|  | ||||
|         When the PV is insufficient, the ESS is used to supplement. If the PV output is not enough to meet the factory's demand, the required power is first obtained from the ESS. | ||||
|  | ||||
|         If the ESS is also insufficient to meet the demand, it will be obtained from the grid. When the stored power in the ESS is also insufficient to supplement, the remaining required power will be purchased from the grid. | ||||
|  | ||||
|         Args: | ||||
|             data: pandas.DataFrame | ||||
|                 The data that contains the factory's demand, PV output, and electricity price. | ||||
|             time_interval: float | ||||
|                 The time interval of the data in hours. | ||||
|  | ||||
|         Returns: | ||||
|             tuple | ||||
|                 The total benefit, total netto benefit, and total generated energy. | ||||
|  | ||||
|         """ | ||||
|         total_benefit = 0 | ||||
|         total_netto_benefit = 0 | ||||
|         total_gen = 0 | ||||
|         net_grid = 0. | ||||
|         for index, row in data.iterrows(): | ||||
|             time = row['time'] | ||||
|             sunlight_intensity = row['sunlight'] | ||||
|             self.time.append(time) | ||||
|             # sunlight_intensity = row['sunlight'] | ||||
|             pv_yield = row['PV yield[kW/kWp]'] | ||||
|             factory_demand = row['demand'] | ||||
|             electricity_price = row['price'] | ||||
|             electricity_price = row['buy'] | ||||
|             sell_price = row['sell'] | ||||
|             # electricity_price = self.grid.get_price_for_time(time) | ||||
|  | ||||
|             if time == '00:00': | ||||
|                 self.day_generated.append(self.generated) | ||||
|                 self.generated = 0 | ||||
|             if time.endswith('14:00'): | ||||
|                 soc = self.ess.storage / self.ess.capacity | ||||
|                 self.hour_stored.append(soc) | ||||
|             if time.endswith('08:00'): | ||||
|                 soc = self.ess.storage / self.ess.capacity | ||||
|                 self.hour_stored_2.append(soc) | ||||
|             # if time == '00:00': | ||||
|             #     self.day_generated.append(self.generated) | ||||
|             #     self.generated = 0 | ||||
|             # if time.endswith('14:00'): | ||||
|             #     soc = self.ess.storage / self.ess.capacity | ||||
|             #     self.hour_stored.append(soc) | ||||
|             # if time.endswith('08:00'): | ||||
|             #     soc = self.ess.storage / self.ess.capacity | ||||
|             #     self.hour_stored_2.append(soc) | ||||
|  | ||||
|             # `generated_pv_power`: the power generated by the PV in kW | ||||
|             # `generated_pv_energy`:  the energy generated by the PV in kWh | ||||
|             generated_pv_power = self.pv.capacity * pv_yield | ||||
|             generated_pv_energy = generated_pv_power * time_interval * self.pv.loss | ||||
|  | ||||
|             self.pv_generated_kWh.append(generated_pv_energy) | ||||
|             self.factory_demand.append(factory_demand) | ||||
|             self.buy_price_kWh.append(electricity_price) | ||||
|             self.sell_price_kWh.append(sell_price) | ||||
|  | ||||
|             generated_pv_power = self.pv.capacity * sunlight_intensity  # 生成的功率,单位 kW | ||||
|             generated_pv_energy = generated_pv_power * time_interval * self.pv.loss  # 生成的能量,单位 kWh | ||||
|             self.generated += generated_pv_energy | ||||
|             # pv生成的能量如果比工厂的需求要大 | ||||
|             # generated_pv_energy is larger than factory_demand energy | ||||
|             if generated_pv_energy >= factory_demand * time_interval: | ||||
|                 # 剩余的能量(kwh) = pv生成的能量 - 工厂需求的功率 * 时间间隔  | ||||
|                 """ | ||||
|                 That means the generated energy is enough to power the factory. | ||||
|                 The surplus energy will be used to charge the ESS. | ||||
|  | ||||
|                 surplus_energy: The energy that is left after powering the factory.  | ||||
|                     formula: generated_pv_energy - factory_demand * time_interval | ||||
|  | ||||
|                 charge_to_ess: The energy that will be charged to the ESS.  | ||||
|                     formula: min(surplus_energy, ess.charge_power * time_interval, ess.capacity - ess.storage) | ||||
|  | ||||
|                 surplus_after_ess: The energy that is left after charging the ESS. | ||||
|                 """ | ||||
|                 surplus_energy = generated_pv_energy - factory_demand * time_interval | ||||
|                 # 要充到ess中的能量 = min(剩余的能量,ess的充电功率*时间间隔(ess在时间间隔内能充进的电量),ess的容量-ess储存的能量(ess中能冲进去的电量)) | ||||
|                 charge_to_ess = min(surplus_energy, self.ess.charge_power * time_interval, self.ess.capacity - self.ess.storage) | ||||
|                 self.ess.storage += charge_to_ess | ||||
|                 surplus_after_ess = surplus_energy - charge_to_ess | ||||
|                 # 如果还有电量盈余,且pv功率大于ess的充电功率+工厂的需求功率则准备卖电 | ||||
|                 """ | ||||
|                 If there is still surplus energy after charging the ESS, and the generated PV power is greater than the sum of the ESS's charge power and the factory's demand power, the surplus energy will be sold to the grid. | ||||
|                 """ | ||||
|                 if surplus_after_ess > 0 and generated_pv_power > self.ess.charge_power + factory_demand: | ||||
|                     sold_to_grid = surplus_after_ess | ||||
|                     sell_income = sold_to_grid * self.grid.sell_price | ||||
|                     sell_income = sold_to_grid * sell_price | ||||
|                     total_benefit += sell_income | ||||
|                 # 节省的能量 = 工厂需求的能量 * 时间段 | ||||
|                 # total_energy = factory_demand * time_interval | ||||
|                 """ | ||||
|                 Saved energy is the energy that is saved by using the PV to power the factory. | ||||
|                 """ | ||||
|                 saved_energy = factory_demand * time_interval | ||||
|             # pv比工厂的需求小 | ||||
|                 self.grid_need_power_kW.append(0) | ||||
|             else: | ||||
|                 # 从ess中需要的电量 = 工厂需要的电量 - pv中的电量 | ||||
|                 """ | ||||
|                 If the generated energy is not enough to power the factory, the ESS will be used to supplement the energy. | ||||
|  | ||||
|                 needed_from_ess: The energy that is needed from the ESS to power the factory. | ||||
|                     formula: factory_demand * time_interval - generated_pv_energy | ||||
|                 """ | ||||
|                 needed_from_ess = factory_demand * time_interval - generated_pv_energy | ||||
|                 # 如果ess中存的电量比需要的多 | ||||
|                 """ | ||||
|                 If the ESS has enough stored energy to power the factory, the energy will be taken from the ESS. | ||||
|                 """ | ||||
|                 if self.ess.storage * self.ess.loss >= needed_from_ess: | ||||
|                     # 取出电量 | ||||
|                     if self.ess.discharge_power * time_interval * self.ess.loss < needed_from_ess: | ||||
|                         discharging_power = self.ess.discharge_power * time_interval  | ||||
|                     else: | ||||
|                         discharging_power = needed_from_ess / self.ess.loss | ||||
|  | ||||
|                     self.ess.storage -= discharging_power | ||||
|                     # 节省下来的能量 = pv的能量 + 放出来的能量 | ||||
|                     """ | ||||
|                     In this case, the energy that is needed from the grid is 0. | ||||
|                     """ | ||||
|                     saved_energy = generated_pv_energy + discharging_power * self.ess.loss | ||||
|                     self.grid_need_power_kW.append(0) | ||||
|                 else: | ||||
|                     # 如果存的电量不够 | ||||
|                     # 需要把ess中的所有电量释放出来 | ||||
|                     """ | ||||
|                     If the ESS does not have enough stored energy to power the factory, the energy will be taken from the grid. | ||||
|                     """ | ||||
|                     if self.grid.capacity * time_interval + generated_pv_energy + self.ess.storage * self.ess.loss < factory_demand * time_interval: | ||||
|                         self.afford = False | ||||
|                         self.overload_cnt+=1 | ||||
|                         log = f"index: {index}, time: {time}, SoC:{self.ess.storage / self.ess.capacity}%, storage: {self.ess.storage}, pv_gen:{generated_pv_power}, power_demand: {factory_demand}, overload_cnt:{self.overload_cnt}, day:{int(index/96) + 1}" | ||||
|                         self.unmet.append((index,time,factory_demand,generated_pv_power)) | ||||
|                         # with open(f'plots/summary/ess-{self.ess.capacity}-pv-{self.pv.capacity}', 'a') as f: | ||||
|                             # f.write(log) | ||||
|                         # print(log) | ||||
|                         # self.unmet.append(log) | ||||
|                     saved_energy = generated_pv_energy + self.ess.storage * self.ess.loss | ||||
|                     self.ess.storage = 0 | ||||
|                     needed_from_grid = factory_demand * time_interval - saved_energy | ||||
|                     net_grid = min(self.grid.capacity * time_interval, needed_from_grid) * self.grid.loss | ||||
|                     # grid_energy += net_grid | ||||
|                     # total_energy += net_grid | ||||
|             # print(total_energy) | ||||
|             # 工厂需求量-总能量 | ||||
|             # unmet_demand = max(0, factory_demand * time_interval - total_energy) | ||||
|             # benefit = (total_energy - unmet_demand) * electricity_price | ||||
|                     self.grid_need_power_kW.append(needed_from_grid * 4) | ||||
|             total_gen += saved_energy | ||||
|             benefit = (saved_energy) * electricity_price | ||||
|             cost = net_grid * electricity_price | ||||
|             # print(f"time:{time} benefit: {benefit}, cost: {cost}") | ||||
|             total_netto_benefit += benefit | ||||
|             total_benefit += benefit - cost | ||||
|             # # spring | ||||
|             week_start = self.season_start | ||||
|             week_end = self.week_length + week_start | ||||
|             if index in range(week_start, week_end): | ||||
|                 self.spring_week_gen.append(generated_pv_power) | ||||
|                 self.spring_week_soc.append(self.ess.storage / self.ess.capacity) | ||||
|             # summer | ||||
|             # week_start += self.season_step | ||||
|             # week_end += self.season_step | ||||
|             # if index in range(week_start, week_end): | ||||
|             #     self.summer_week_gen.append(generated_pv_power) | ||||
|             #     self.summer_week_soc.append(self.ess.storage / self.ess.capacity) | ||||
|             # # autumn | ||||
|             # week_start += self.season_step | ||||
|             # week_end += self.season_step | ||||
|             # if index in range(week_start, week_end): | ||||
|             #     self.autumn_week_gen.append(generated_pv_power) | ||||
|             #     self.autumn_week_soc.append(self.ess.storage / self.ess.capacity) | ||||
|             # week_start += self.season_step | ||||
|             # week_end += self.season_step | ||||
|             # if index in range(week_start, week_end): | ||||
|             #     self.winter_week_gen.append(generated_pv_power) | ||||
|             #     self.winter_week_soc.append(self.ess.storage / self.ess.capacity) | ||||
|             print_season_flag = False | ||||
|             if print_season_flag == True: | ||||
|                 week_start = self.season_start | ||||
|                 week_end = self.week_length + week_start | ||||
|                 if index in range(week_start, week_end): | ||||
|                     self.spring_week_gen.append(generated_pv_power) | ||||
|                     self.spring_week_soc.append(self.ess.storage / self.ess.capacity) | ||||
|                 self.ess_rest = self.ess.storage | ||||
|                 # summer | ||||
|                 week_start += self.season_step | ||||
|                 week_end += self.season_step | ||||
|                 if index in range(week_start, week_end): | ||||
|                     self.summer_week_gen.append(generated_pv_power) | ||||
|                     self.summer_week_soc.append(self.ess.storage / self.ess.capacity) | ||||
|                 # # autumn | ||||
|                 week_start += self.season_step | ||||
|                 week_end += self.season_step | ||||
|                 if index in range(week_start, week_end): | ||||
|                     self.autumn_week_gen.append(generated_pv_power) | ||||
|                     self.autumn_week_soc.append(self.ess.storage / self.ess.capacity) | ||||
|                 week_start += self.season_step | ||||
|                 week_end += self.season_step | ||||
|                 if index in range(week_start, week_end): | ||||
|                     self.winter_week_gen.append(generated_pv_power) | ||||
|                     self.winter_week_soc.append(self.ess.storage / self.ess.capacity) | ||||
|  | ||||
|         return total_benefit | ||||
|         return (total_benefit, total_netto_benefit, total_gen) | ||||
							
								
								
									
										70079
									
								
								combined_data.csv
									
									
									
									
									
								
							
							
						
						
									
										70079
									
								
								combined_data.csv
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										16
									
								
								config.json
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								config.json
									
									
									
									
									
								
							| @@ -17,12 +17,12 @@ | ||||
|     "pv_capacities":{ | ||||
|         "begin": 0, | ||||
|         "end": 50000, | ||||
|         "groups": 5  | ||||
|         "groups":  3 | ||||
|     }, | ||||
|     "ess_capacities":{ | ||||
|         "begin": 0, | ||||
|         "end": 100000, | ||||
|         "groups": 10  | ||||
|         "groups":  3 | ||||
|     }, | ||||
|     "time_interval":{ | ||||
|         "numerator": 15, | ||||
| @@ -31,7 +31,8 @@ | ||||
|     "annotated": { | ||||
|         "unmet_prob": false, | ||||
|         "benefit": false, | ||||
|         "cost": false  | ||||
|         "cost": false, | ||||
|         "roi": false  | ||||
|     }, | ||||
|     "figure_size":{ | ||||
|         "height": 9, | ||||
| @@ -40,6 +41,13 @@ | ||||
|     "plot_title":{ | ||||
|         "unmet_prob": "Coverage Rate of Factory Electrical Demands", | ||||
|         "cost": "Costs of Microgrid system [m-EUR]", | ||||
|         "benefit": "Financial Profit Based on Py & Ess Configuration (k-EUR / year)" | ||||
|         "benefit": "Financial Profit Based on Py & Ess Configuration (k-EUR / year)", | ||||
|         "roi": "ROI" | ||||
|     }, | ||||
|     "data_path": { | ||||
|         "pv_yield": "read_data/Serbia.csv", | ||||
|         "demand": "read_data/factory_power1.csv", | ||||
|         "sell": "read_data/electricity_price_data_sell.csv", | ||||
|         "buy": "read_data/electricity_price_data.csv" | ||||
|     } | ||||
| } | ||||
| @@ -10,12 +10,12 @@ class pv_config: | ||||
|     def get_cost_per_year(self): | ||||
|         return self.capacity * self.cost_per_kW / self.lifetime | ||||
| class ess_config: | ||||
|     def __init__(self, capacity, cost_per_kW, lifetime, loss, charge_power, discharge_power): | ||||
|     def __init__(self, capacity, cost_per_kW, lifetime, loss, charge_power, discharge_power, storage=0): | ||||
|         self.capacity = capacity | ||||
|         self.cost_per_kW = cost_per_kW | ||||
|         self.lifetime = lifetime | ||||
|         self.loss = loss | ||||
|         self.storage = 100 | ||||
|         self.storage = storage | ||||
|         self.charge_power = charge_power | ||||
|         self.discharge_power = discharge_power | ||||
|     def get_cost(self): | ||||
|   | ||||
							
								
								
									
										56
									
								
								draw.py
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								draw.py
									
									
									
									
									
								
							| @@ -35,7 +35,6 @@ def draw_results(results, filename, title_benefit, annot_benefit=False, figure_s | ||||
|     new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns) | ||||
|     for i in df.columns: | ||||
|         new_Data[i] = df[i].iloc[-1] | ||||
|     # print(new_Data) | ||||
|     df = pd.concat([df, new_Data]) | ||||
|  | ||||
|     X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0])) | ||||
| @@ -68,7 +67,6 @@ def draw_cost(costs, filename, title_cost, annot_cost=False, figure_size=(10, 10 | ||||
|     new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns) | ||||
|     for i in df.columns: | ||||
|         new_Data[i] = df[i].iloc[-1] | ||||
|     # print(new_Data) | ||||
|     df = pd.concat([df, new_Data]) | ||||
|     X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0])) | ||||
|  | ||||
| @@ -98,7 +96,6 @@ def draw_overload(overload_cnt, filename, title_unmet, annot_unmet=False, figure | ||||
|     df.columns = df.columns.map(int) | ||||
|     min_value = df.min().min() | ||||
|     max_value = df.max().max() | ||||
|     # max_scale = max(abs(min_value/1000), abs(max_value/1000)) | ||||
|  | ||||
|  | ||||
|     df[df.columns[-1] + 1] = df.iloc[:, -1]  | ||||
| @@ -132,6 +129,41 @@ def draw_overload(overload_cnt, filename, title_unmet, annot_unmet=False, figure | ||||
|     plt.ylabel('PV Capacity (MW)') | ||||
|     plt.savefig(filename) | ||||
|  | ||||
| with open('config.json', 'r') as f: | ||||
|     js_data = json.load(f) | ||||
|  | ||||
| data = pd.read_csv('combined_data.csv') | ||||
| time_interval = js_data["time_interval"]["numerator"] / js_data["time_interval"]["denominator"] | ||||
|  | ||||
| pv_loss = js_data["pv"]["loss"] | ||||
| pv_cost_per_kW = js_data["pv"]["cost_per_kW"] | ||||
| pv_lifetime = js_data["pv"]["lifetime"] | ||||
|  | ||||
| ess_loss = js_data["ess"]["loss"] | ||||
| ess_cost_per_kW = js_data["ess"]["cost_per_kW"] | ||||
| ess_lifetime = js_data["ess"]["lifetime"] | ||||
|  | ||||
| grid_loss = js_data["grid"]["loss"] | ||||
| sell_price = js_data["grid"]["sell_price"] | ||||
| grid_capacity = js_data["grid"]["capacity"] | ||||
|  | ||||
| pv_begin = js_data["pv_capacities"]["begin"] | ||||
| pv_end = js_data["pv_capacities"]["end"] | ||||
| pv_groups = js_data["pv_capacities"]["groups"] | ||||
|  | ||||
| ess_begin = js_data["ess_capacities"]["begin"] | ||||
| ess_end = js_data["ess_capacities"]["end"] | ||||
| ess_groups = js_data["ess_capacities"]["groups"] | ||||
|  | ||||
| annot_unmet = js_data["annotated"]["unmet_prob"] | ||||
| annot_benefit = js_data["annotated"]["benefit"] | ||||
| annot_cost = js_data["annotated"]["cost"] | ||||
|  | ||||
| title_unmet = js_data["plot_title"]["unmet_prob"] | ||||
| title_cost = js_data["plot_title"]["cost"] | ||||
| title_benefit = js_data["plot_title"]["benefit"] | ||||
|  | ||||
| figure_size = (js_data["figure_size"]["length"], js_data["figure_size"]["height"]) | ||||
|  | ||||
| directory = 'data/' | ||||
|  | ||||
| @@ -143,9 +175,9 @@ split_files = [f.split('-') for f in file_list] | ||||
| costs_files = [f for f in split_files if f[-1].endswith('costs.json')] | ||||
| print(f'find costs files: {costs_files}') | ||||
| overload_files = [f for f in split_files if f[-1].endswith('overload_cnt.json')] | ||||
| print(f'find overload files: {overload_files}') | ||||
| print(f'find coverage/unmet files: {overload_files}') | ||||
| results_files = [f for f in split_files if f[-1].endswith('results.json')] | ||||
| print(f'find results files: {results_files}') | ||||
| print(f'find profit/benefit files: {results_files}') | ||||
|  | ||||
| costs_dfs = [read_data(directory + '-'.join(f)) for f in costs_files] | ||||
| overload_dfs = [read_data(directory + '-'.join(f)) for f in overload_files] | ||||
| @@ -154,17 +186,19 @@ results_dfs = [read_data(directory + '-'.join(f)) for f in results_files] | ||||
| for costs_df, overload_df, results_df in zip(costs_dfs, overload_dfs, results_dfs): | ||||
|  | ||||
|     draw_cost(costs_df,  | ||||
|               f'plots/costs-{int(costs_df.columns[-1])}-pv-{int(costs_df.index[-1])}.png',  | ||||
|               f'Costs for ESS-{int(costs_df.columns[-1])}-pv-{int(costs_df.index[-1])}MWh', annot_cost=False) | ||||
|               f'plots/costs-ess-{int(costs_df.columns[0])}-{int(costs_df.columns[-1])}-pv-{int(costs_df.index[0])}-{int(costs_df.index[-1])}.png',  | ||||
|               title_cost=title_cost,  | ||||
|               annot_cost=annot_cost) | ||||
|  | ||||
|     draw_overload(overload_df,  | ||||
|                   f'plots/overload-ess-{overload_df.columns[-1]}-pv-{overload_df.index[-1]}.png',  | ||||
|                   f'Overload for ess-{overload_df.columns[-1]}MW pv-{overload_df.index[-1]}MWh',  | ||||
|                   f'plots/overload-ess-{overload_df.columns[0]}-{overload_df.columns[-1]}-pv-{overload_df.index[0]}-{overload_df.index[-1]}.png',  | ||||
|                   title_unmet=title_unmet,  | ||||
|                   annot_unmet=False) | ||||
|  | ||||
|     draw_results(results_df,  | ||||
|                  f'plots/results-{results_df.columns[-1]}-pv-{results_df.index[-1]}.png',  | ||||
|                  f'Results for ess-{results_df.columns[-1]}MW pv-{results_df.index[-1]}MWh', annot_benefit=False) | ||||
|                  f'plots/results-ess-{results_df.columns[0]}-{results_df.columns[-1]}-pv-{results_df.index[0]}-{results_df.index[-1]}.png',  | ||||
|                  title_benefit=title_benefit, | ||||
|                  annot_benefit=False) | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1036
									
								
								main.ipynb
									
									
									
									
									
								
							
							
						
						
									
										1036
									
								
								main.ipynb
									
									
									
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										663
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										663
									
								
								main.py
									
									
									
									
									
								
							| @@ -1,12 +1,21 @@ | ||||
| #!/usr/bin/env python | ||||
| # coding: utf-8 | ||||
|  | ||||
| # In[14]: | ||||
| # In[83]: | ||||
|  | ||||
|  | ||||
| import os | ||||
| import glob | ||||
| import shutil | ||||
| import matplotlib.pyplot as plt | ||||
| import matplotlib.ticker as ticker | ||||
| from matplotlib.ticker import FuncFormatter | ||||
| import numpy as np | ||||
| import pandas as pd | ||||
| import os | ||||
| import seaborn as sns | ||||
| import json | ||||
| from matplotlib.colors import LinearSegmentedColormap | ||||
|  | ||||
| def clear_folder_make_ess_pv(folder_path): | ||||
|     if os.path.isdir(folder_path): | ||||
| @@ -19,7 +28,7 @@ folder_path = 'plots' | ||||
| clear_folder_make_ess_pv(folder_path) | ||||
|  | ||||
|  | ||||
| # In[15]: | ||||
| # In[84]: | ||||
|  | ||||
|  | ||||
| import matplotlib.pyplot as plt | ||||
| @@ -30,18 +39,21 @@ from EnergySystem import EnergySystem | ||||
| from config import pv_config, grid_config, ess_config | ||||
|  | ||||
|  | ||||
| # In[16]: | ||||
| # In[85]: | ||||
|  | ||||
|  | ||||
| import json | ||||
|  | ||||
| print("Version 0.0.2") | ||||
| print("Version 0.0.7\n") | ||||
|  | ||||
| with open('config.json', 'r') as f: | ||||
|     js_data = json.load(f) | ||||
|  | ||||
| data = pd.read_csv('combined_data.csv') | ||||
|  | ||||
|      | ||||
|  | ||||
| time_interval = js_data["time_interval"]["numerator"] / js_data["time_interval"]["denominator"] | ||||
| # print(time_interval) | ||||
|  | ||||
| pv_loss = js_data["pv"]["loss"] | ||||
| pv_cost_per_kW = js_data["pv"]["cost_per_kW"] | ||||
| @@ -66,22 +78,45 @@ ess_groups = js_data["ess_capacities"]["groups"] | ||||
| annot_unmet = js_data["annotated"]["unmet_prob"] | ||||
| annot_benefit = js_data["annotated"]["benefit"] | ||||
| annot_cost = js_data["annotated"]["cost"] | ||||
| annot_roi = js_data["annotated"]["roi"] | ||||
|  | ||||
| title_unmet = js_data["plot_title"]["unmet_prob"] | ||||
| title_cost = js_data["plot_title"]["cost"] | ||||
| title_benefit = js_data["plot_title"]["benefit"] | ||||
| title_roi = js_data["plot_title"]["roi"] | ||||
|  | ||||
|  | ||||
| figure_size = (js_data["figure_size"]["length"], js_data["figure_size"]["height"]) | ||||
|  | ||||
| data = pd.read_csv('combined_data.csv') | ||||
|  | ||||
| granularity = js_data["time_interval"]["numerator"] | ||||
|  | ||||
| months_days = [31,28,31,30,31,30,31,31,30,31,30,31] | ||||
| def get_month_coe(num, granularity): | ||||
|     return 60 / granularity * 24 * months_days[num] | ||||
|  | ||||
| months_index = [get_month_coe(num, granularity) for num in range(12)] | ||||
| months_data = [] | ||||
| for i in range(1,12): | ||||
|     months_index[i] += months_index[i-1] | ||||
| for i in range(12): | ||||
|     start = 0 if i == 0 else months_index[i-1] | ||||
|     end = months_index[i] | ||||
|     months_data.append(data.iloc[int(start):int(end)]) | ||||
|      | ||||
|  | ||||
|  | ||||
|  | ||||
| pv_capacities = np.linspace(pv_begin, pv_end, pv_groups) | ||||
| ess_capacities = np.linspace(ess_begin, ess_end, ess_groups) | ||||
| results = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| affords = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| overload_cnt = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| # results = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| # affords = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| # costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| # overload_cnt = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
|  | ||||
|  | ||||
| # In[17]: | ||||
| # In[86]: | ||||
|  | ||||
|  | ||||
| hour_demand = [] | ||||
| @@ -97,164 +132,414 @@ plt.savefig('plots/demand.png') | ||||
| plt.close() | ||||
|  | ||||
|  | ||||
| # In[18]: | ||||
| # In[87]: | ||||
|  | ||||
|  | ||||
| def cal_profit(es: EnergySystem, saved_money): | ||||
|     profit = saved_money - es.ess.get_cost_per_year() - es.pv.get_cost_per_year() | ||||
| def draw_results(results, filename, title_benefit, annot_benefit=False, figure_size=(10, 10)): | ||||
|     df=results | ||||
|     df = df.astype(float) | ||||
|     df.index = df.index / 1000 | ||||
|     df.index = df.index.map(int) | ||||
|     df.columns = df.columns / 1000 | ||||
|     df.columns = df.columns.map(int) | ||||
|     min_value = df.min().min() | ||||
|     max_value = df.max().max() | ||||
|     max_scale = max(abs(min_value/1000), abs(max_value/1000)) | ||||
|  | ||||
|     df[df.columns[-1] + 1] = df.iloc[:, -1]  | ||||
|     new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns) | ||||
|     for i in df.columns: | ||||
|         new_Data[i] = df[i].iloc[-1] | ||||
|     df = pd.concat([df, new_Data]) | ||||
|  | ||||
|     X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0])) | ||||
|  | ||||
|     def fmt(x,pos): | ||||
|         return '{:.0f}'.format(x/1000) | ||||
|  | ||||
|     cmap = sns.color_palette("coolwarm", as_cmap=True) | ||||
|     plt.figure(figsize=figure_size) | ||||
|     ax = sns.heatmap(df/1000, fmt=".1f", cmap=cmap, vmin=-max_scale, vmax=max_scale, annot=annot_benefit) | ||||
|     CS = ax.contour(X, Y, df,  colors='black', alpha=0.5) | ||||
|     ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt)) | ||||
|     plt.title(title_benefit) | ||||
|     plt.gca().invert_yaxis() | ||||
|     plt.xlim(0, df.shape[1] - 1) | ||||
|     plt.ylim(0, df.shape[0] - 1) | ||||
|     plt.xlabel('ESS Capacity (MWh)') | ||||
|     plt.ylabel('PV Capacity (MW)') | ||||
|     plt.savefig(filename) | ||||
|  | ||||
|  | ||||
| # In[88]: | ||||
|  | ||||
|  | ||||
| def draw_roi(costs, results, filename, title_roi, days=365, annot_roi=False, figure_size=(10, 10)): | ||||
|     costs = costs.astype(float) | ||||
|     costs = costs / 365  | ||||
|     costs = costs * days | ||||
|  | ||||
|     df = results | ||||
|     df = costs / df | ||||
|     if 0 in df.index and 0 in df.columns: | ||||
|         df.loc[0,0] = 100 | ||||
|     df[df > 80] = 100 | ||||
|     # print(df) | ||||
|  | ||||
|     df = df.astype(float) | ||||
|     df.index = df.index / 1000 | ||||
|     df.index = df.index.map(int) | ||||
|     df.columns = df.columns / 1000 | ||||
|     df.columns = df.columns.map(int) | ||||
|     min_value = df.min().min() | ||||
|     max_value = df.max().max() | ||||
|     # print(max_value) | ||||
|     max_scale = max(abs(min_value), abs(max_value)) | ||||
|  | ||||
|     df[df.columns[-1] + 1] = df.iloc[:, -1]  | ||||
|     new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns) | ||||
|     for i in df.columns: | ||||
|         new_Data[i] = df[i].iloc[-1] | ||||
|     df = pd.concat([df, new_Data]) | ||||
|  | ||||
|     X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0])) | ||||
|  | ||||
|     def fmt(x,pos): | ||||
|         return '{:.0f}'.format(x) | ||||
|  | ||||
|     cmap = sns.color_palette("Greys", as_cmap=True) | ||||
|     plt.figure(figsize=figure_size) | ||||
|     ax = sns.heatmap(df, fmt=".1f", cmap=cmap, vmin=0, vmax=100, annot=annot_benefit) | ||||
|     CS = ax.contour(X, Y, df,  colors='black', alpha=0.5) | ||||
|     ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt)) | ||||
|     plt.title(title_roi) | ||||
|     plt.gca().invert_yaxis() | ||||
|     plt.xlim(0, df.shape[1] - 1) | ||||
|     plt.ylim(0, df.shape[0] - 1) | ||||
|     plt.xlabel('ESS Capacity (MWh)') | ||||
|     plt.ylabel('PV Capacity (MW)') | ||||
|     plt.savefig(filename) | ||||
|     plt.close() | ||||
|  | ||||
|  | ||||
| # In[89]: | ||||
|  | ||||
|  | ||||
| def draw_cost(costs, filename, title_cost, annot_cost=False, figure_size=(10, 10)): | ||||
|     df = costs | ||||
|     df = df.astype(int) | ||||
|     df.index = df.index / 1000 | ||||
|     df.index = df.index.map(int) | ||||
|     df.columns = df.columns / 1000 | ||||
|     df.columns = df.columns.map(int) | ||||
|  | ||||
|     df[df.columns[-1] + 1] = df.iloc[:, -1]  | ||||
|     new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns) | ||||
|     for i in df.columns: | ||||
|         new_Data[i] = df[i].iloc[-1] | ||||
|     df = pd.concat([df, new_Data]) | ||||
|     X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0])) | ||||
|  | ||||
|     def fmt(x, pos): | ||||
|         return '{:.0f}'.format(x / 1000000) | ||||
|  | ||||
|     plt.figure(figsize=figure_size) | ||||
|     ax = sns.heatmap(df/1000000,  fmt=".1f", cmap='viridis', annot=annot_cost) | ||||
|     CS = ax.contour(X, Y, df,  colors='black', alpha=0.5) | ||||
|     ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt)) | ||||
|     plt.title(title_cost) | ||||
|     plt.gca().invert_yaxis() | ||||
|     plt.xlim(0, df.shape[1] - 1) | ||||
|     plt.ylim(0, df.shape[0] - 1) | ||||
|     plt.xlabel('ESS Capacity (MWh)') | ||||
|     plt.ylabel('PV Capacity (MW)') | ||||
|     plt.savefig(filename) | ||||
|     plt.close() | ||||
|  | ||||
|  | ||||
| # In[90]: | ||||
|  | ||||
|  | ||||
| def draw_overload(overload_cnt, filename, title_unmet, annot_unmet=False, figure_size=(10, 10), days=365, granularity=15): | ||||
|     df = overload_cnt | ||||
|     # print(days, granularity) | ||||
|     coef = 60 / granularity * days * 24 | ||||
|     # print(coef) | ||||
|     # print(df) | ||||
|     df = ( coef - df) / coef | ||||
|     # print(df) | ||||
|  | ||||
|     df = df.astype(float) | ||||
|     df.index = df.index / 1000 | ||||
|     df.index = df.index.map(int) | ||||
|     df.columns = df.columns / 1000 | ||||
|     df.columns = df.columns.map(int) | ||||
|  | ||||
|  | ||||
|     df[df.columns[-1] + 1] = df.iloc[:, -1]  | ||||
|     new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns) | ||||
|     for i in df.columns: | ||||
|         new_Data[i] = df[i].iloc[-1] | ||||
|     # print(new_Data) | ||||
|     df = pd.concat([df, new_Data]) | ||||
|  | ||||
|  | ||||
|     plt.figure(figsize=figure_size) | ||||
|     cmap = LinearSegmentedColormap.from_list("", ["white", "blue"]) | ||||
|     ax = sns.heatmap(df, fmt=".00%", cmap=cmap, vmin=0, vmax=1, annot=annot_unmet) | ||||
|  | ||||
|     cbar = ax.collections[0].colorbar | ||||
|     cbar.set_ticks([0, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1]) | ||||
|     cbar.set_ticklabels(['0%', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%']) | ||||
|     cbar.ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: f'{x:.0%}')) | ||||
|     X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0])) | ||||
|  | ||||
|     def fmt(x, pos): | ||||
|         return '{:.0f}%'.format(x * 100) | ||||
|     CS = ax.contour(X, Y, df,  colors='black', alpha=0.5) | ||||
|  | ||||
|     ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt)) | ||||
|  | ||||
|     plt.xlim(0, df.shape[1] - 1) | ||||
|     plt.ylim(0, df.shape[0] - 1) | ||||
|     plt.title(title_unmet) | ||||
|     plt.xlabel('ESS Capacity (MWh)') | ||||
|     plt.ylabel('PV Capacity (MW)') | ||||
|     plt.savefig(filename) | ||||
|     plt.close() | ||||
|  | ||||
|  | ||||
| # In[91]: | ||||
|  | ||||
|  | ||||
| def cal_profit(es: EnergySystem, saved_money, days): | ||||
|     profit = saved_money - es.ess.get_cost_per_year() / 365 * days - es.pv.get_cost_per_year() / 365 * days | ||||
|     return profit | ||||
|  | ||||
|  | ||||
| # In[24]: | ||||
| # In[92]: | ||||
|  | ||||
|  | ||||
| for ess_capacity in ess_capacities: | ||||
|     print(f"ess_capacity:{ess_capacity}") | ||||
| def generate_data(pv_capacity, pv_cost_per_kW, pv_lifetime, pv_loss, ess_capacity, ess_cost_per_kW, ess_lifetime, ess_loss, grid_capacity, grid_loss, sell_price, time_interval, data, days, storage=0): | ||||
|     pv = pv_config(capacity=pv_capacity,  | ||||
|                     cost_per_kW=pv_cost_per_kW, | ||||
|                     lifetime=pv_lifetime,  | ||||
|                     loss=pv_loss) | ||||
|     ess = ess_config(capacity=ess_capacity,  | ||||
|                         cost_per_kW=ess_cost_per_kW,  | ||||
|                         lifetime=ess_lifetime,  | ||||
|                         loss=ess_loss, | ||||
|                         charge_power=ess_capacity, | ||||
|                         discharge_power=ess_capacity, | ||||
|                         storage=storage) | ||||
|     grid = grid_config(capacity=grid_capacity,  | ||||
|                         grid_loss=grid_loss, | ||||
|                         sell_price= sell_price) | ||||
|     energySystem = EnergySystem(pv_type=pv,  | ||||
|                                 ess_type=ess,  | ||||
|                                 grid_type= grid) | ||||
|     (benefit, netto_benefit, gen_energy) = energySystem.simulate(data, time_interval) | ||||
|     results = cal_profit(energySystem, benefit, days) | ||||
|     overload_cnt = energySystem.overload_cnt | ||||
|     costs = energySystem.ess.capacity * energySystem.ess.cost_per_kW + energySystem.pv.capacity * energySystem.pv.cost_per_kW | ||||
|     return (results,  | ||||
|             overload_cnt, | ||||
|             costs,  | ||||
|             netto_benefit,  | ||||
|             gen_energy,  | ||||
|             energySystem.generated, | ||||
|             energySystem.ess_rest, | ||||
|             energySystem.factory_demand, | ||||
|             energySystem.buy_price_kWh, | ||||
|             energySystem.sell_price_kWh, | ||||
|             energySystem.pv_generated_kWh, | ||||
|             energySystem.grid_need_power_kW, | ||||
|             energySystem.time) | ||||
|  | ||||
|  | ||||
|  | ||||
| # In[93]: | ||||
|  | ||||
|  | ||||
| from tqdm import tqdm | ||||
| months_results = [] | ||||
| months_costs = [] | ||||
| months_overload = [] | ||||
| months_nettos = [] | ||||
| months_gen_energy = [] | ||||
| months_gen_energy2 = [] | ||||
| months_ess_rest = pd.DataFrame(30, index=pv_capacities, columns= ess_capacities) | ||||
| months_csv_data = {} | ||||
| for index, month_data in tqdm(enumerate(months_data), total=len(months_data), position=0, leave= True): | ||||
|     results = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
|     costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
|     overload_cnt = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
|     nettos = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
|     gen_energies = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
|     gen_energies2 = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
|     factory_demands = {} | ||||
|     buy_prices= {} | ||||
|     sell_prices = {} | ||||
|     pv_generates = {} | ||||
|     grid_need_powers = {} | ||||
|     times = {} | ||||
|     for pv_capacity in tqdm(pv_capacities, total=len(pv_capacities), desc=f'generating pv for month {index + 1}',position=1, leave=False): | ||||
|         factory_demands[pv_capacity] = {} | ||||
|         buy_prices[pv_capacity] = {} | ||||
|         sell_prices[pv_capacity] = {} | ||||
|         pv_generates[pv_capacity] = {} | ||||
|         grid_need_powers[pv_capacity] = {} | ||||
|         times[pv_capacity] = {} | ||||
|         for ess_capacity in ess_capacities: | ||||
|             (result,  | ||||
|              overload,  | ||||
|              cost,  | ||||
|              netto, | ||||
|              gen_energy, | ||||
|              gen_energy2, | ||||
|              ess_rest, | ||||
|              factory_demand, | ||||
|              buy_price, | ||||
|              sell_price, | ||||
|              pv_generate, | ||||
|              grid_need_power, | ||||
|              time) = generate_data(pv_capacity=pv_capacity, | ||||
|                         pv_cost_per_kW=pv_cost_per_kW, | ||||
|                         pv_lifetime=pv_lifetime,  | ||||
|                         pv_loss=pv_loss,  | ||||
|                         ess_capacity=ess_capacity,  | ||||
|                         ess_cost_per_kW=ess_cost_per_kW,  | ||||
|                         ess_lifetime=ess_lifetime,  | ||||
|                         ess_loss=ess_loss,  | ||||
|                         grid_capacity=grid_capacity,  | ||||
|                         grid_loss=grid_loss,  | ||||
|                         sell_price=sell_price,  | ||||
|                         time_interval=time_interval,  | ||||
|                         data=month_data,  | ||||
|                         days=months_days[index], | ||||
|                         storage=months_ess_rest.loc[pv_capacity, ess_capacity]) | ||||
|             results.loc[pv_capacity,ess_capacity] = result | ||||
|             overload_cnt.loc[pv_capacity,ess_capacity] = overload | ||||
|             costs.loc[pv_capacity,ess_capacity] = cost | ||||
|             nettos.loc[pv_capacity,ess_capacity] = netto | ||||
|             gen_energies.loc[pv_capacity, ess_capacity] = gen_energy | ||||
|             gen_energies2.loc[pv_capacity, ess_capacity] = gen_energy2 | ||||
|             months_ess_rest.loc[pv_capacity, ess_capacity] = ess_rest | ||||
|             factory_demands[pv_capacity][ess_capacity] = factory_demand | ||||
|             buy_prices[pv_capacity][ess_capacity] = buy_price | ||||
|             sell_prices[pv_capacity][ess_capacity] = sell_price | ||||
|             pv_generates[pv_capacity][ess_capacity] = pv_generate | ||||
|             grid_need_powers[pv_capacity][ess_capacity] = grid_need_power | ||||
|             times[pv_capacity][ess_capacity] = time | ||||
|     months_csv_data[index] = {"factory_demand": factory_demands, "buy_price": buy_prices, "sell_price": sell_prices, "pv_generate": pv_generates, "grid_need_power": grid_need_powers, "time": times} | ||||
|     months_results.append(results) | ||||
|     months_costs.append(costs) | ||||
|     months_overload.append(overload_cnt) | ||||
|     months_nettos.append(nettos) | ||||
|     months_gen_energy.append(gen_energies) | ||||
|     months_gen_energy2.append(gen_energies2) | ||||
|     draw_results(results=results,  | ||||
|                     filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-month-{index+1}-benefit.png', | ||||
|                     title_benefit=title_benefit, | ||||
|                     annot_benefit=annot_benefit, | ||||
|                     figure_size=figure_size) | ||||
|     draw_overload(overload_cnt=overload_cnt,  | ||||
|                     filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-month-{index+1}-unmet.png', | ||||
|                     title_unmet=title_unmet, | ||||
|                     annot_unmet=annot_unmet, | ||||
|                     figure_size=figure_size, | ||||
|                     days=months_days[index], | ||||
|                     granularity=granularity) | ||||
| annual_result = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| annual_costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| annual_overload = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| annual_nettos = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| annual_gen = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
| annual_gen2 = pd.DataFrame(index=pv_capacities, columns= ess_capacities) | ||||
|  | ||||
|  | ||||
| # get the yearly results | ||||
| for pv_capacity in pv_capacities: | ||||
|     for ess_capacity in ess_capacities: | ||||
|         results = 0 | ||||
|         costs = 0 | ||||
|         overload_cnt = 0 | ||||
|         nettos = 0 | ||||
|         gen = 0 | ||||
|         gen2 = 0 | ||||
|         for index, month_data in enumerate(months_data): | ||||
|             results += months_results[index].loc[pv_capacity,ess_capacity] | ||||
|             costs += months_costs[index].loc[pv_capacity,ess_capacity] | ||||
|             overload_cnt += months_overload[index].loc[pv_capacity, ess_capacity] | ||||
|             nettos += months_nettos[index].loc[pv_capacity, ess_capacity] | ||||
|             gen += months_gen_energy[index].loc[pv_capacity, ess_capacity] | ||||
|             gen2 += months_gen_energy[index].loc[pv_capacity, ess_capacity] | ||||
|         annual_result.loc[pv_capacity, ess_capacity] = results | ||||
|         annual_costs.loc[pv_capacity, ess_capacity] = costs | ||||
|         annual_overload.loc[pv_capacity, ess_capacity] = overload_cnt | ||||
|         annual_nettos.loc[pv_capacity, ess_capacity] = nettos | ||||
|         annual_gen.loc[pv_capacity, ess_capacity] = gen | ||||
|         annual_gen2.loc[pv_capacity, ess_capacity] = gen2 | ||||
|  | ||||
| draw_cost(costs=annual_costs, | ||||
|           filename='plots/annual_cost.png', | ||||
|         title_cost=title_cost, | ||||
|         annot_cost=annot_cost, | ||||
|         figure_size=figure_size) | ||||
| draw_results(results=annual_result, | ||||
|                 filename='plots/annual_benefit.png', | ||||
|                 title_benefit=title_benefit, | ||||
|                 annot_benefit=annot_benefit, | ||||
|                 figure_size=figure_size) | ||||
| draw_overload(overload_cnt=annual_overload, | ||||
|                 filename='plots/annual_unmet.png', | ||||
|                 title_unmet=title_unmet, | ||||
|                 annot_unmet=annot_unmet, | ||||
|                 figure_size=figure_size) | ||||
|  | ||||
|  | ||||
| # In[94]: | ||||
|  | ||||
|  | ||||
| def collapse_months_csv_data(months_csv_data, column_name,pv_capacies, ess_capacities): | ||||
|     data = {} | ||||
|     for pv_capacity in pv_capacities: | ||||
|         print(f"pv_capacity:{ess_capacity}") | ||||
|         pv = pv_config(capacity=pv_capacity,  | ||||
|                         cost_per_kW=pv_cost_per_kW, | ||||
|                         lifetime=pv_lifetime,  | ||||
|                         loss=pv_loss) | ||||
|         ess = ess_config(capacity=ess_capacity,  | ||||
|                             cost_per_kW=ess_cost_per_kW,  | ||||
|                             lifetime=ess_lifetime,  | ||||
|                             loss=ess_loss, | ||||
|                             charge_power=ess_capacity, | ||||
|                             discharge_power=ess_capacity) | ||||
|         grid = grid_config(capacity=grid_capacity,  | ||||
|                             grid_loss=grid_loss, | ||||
|                             sell_price= sell_price) | ||||
|         energySystem = EnergySystem(pv_type=pv,  | ||||
|                                     ess_type=ess,  | ||||
|                                     grid_type= grid) | ||||
|         benefit = energySystem.simulate(data, time_interval) | ||||
|         results.loc[pv_capacity,ess_capacity] = cal_profit(energySystem, benefit) | ||||
|         affords.loc[pv_capacity,ess_capacity] = energySystem.afford | ||||
|         overload_cnt.loc[pv_capacity,ess_capacity] = energySystem.overload_cnt | ||||
|         costs.loc[pv_capacity,ess_capacity] = energySystem.ess.capacity * energySystem.ess.cost_per_kW + energySystem.pv.capacity * energySystem.pv.cost_per_kW | ||||
|         pv_generated = energySystem.day_generated | ||||
|         ess_generated = energySystem.hour_stored | ||||
|         ess_generated_2 = energySystem.hour_stored_2 | ||||
|     plt.figure(figsize=(10,8)); | ||||
|     plt.plot(ess_generated) | ||||
|     plt.xlabel('day #') | ||||
|     plt.ylabel('SoC %') | ||||
|     plt.title(f'14:00 ESS SoC \n PV cap:{pv_capacity}, ESS cap:{ess_capacity}') | ||||
|     plt.savefig(f'plots/ess/1400-{pv_capacity}-{ess_capacity}.png') | ||||
|     plt.close() | ||||
|     plt.figure(figsize=(10,8)); | ||||
|     plt.plot(ess_generated_2) | ||||
|     plt.xlabel('day #') | ||||
|     plt.ylabel('SoC%') | ||||
|     plt.title(f'08:00 ESS SoC \n PV cap:{pv_capacity}, ESS cap:{ess_capacity}') | ||||
|     plt.savefig(f'plots/ess/0800-{pv_capacity}-{ess_capacity}.png') | ||||
|     plt.close() | ||||
|         # print(energySystem.unmet) | ||||
|         # spring_week_start = energySystem.season_start | ||||
|         # spring_week_end = spring_week_start + energySystem.week_length | ||||
|         # summer_week_start = energySystem.season_start + 1 * energySystem.season_step | ||||
|         # summer_week_end = summer_week_start + energySystem.week_length | ||||
|         # autumn_week_start = energySystem.season_start + 2 * energySystem.season_step | ||||
|         # autumn_week_end = autumn_week_start + energySystem.week_length | ||||
|         # winter_week_start = energySystem.season_start + 3 * energySystem.season_step | ||||
|         # winter_week_end = winter_week_start+ energySystem.week_length | ||||
|         data[pv_capacity] = {} | ||||
|         for ess_capacity in ess_capacities: | ||||
|             annual_data = [] | ||||
|             for index, month_data in enumerate(months_data): | ||||
|                 annual_data.extend(months_csv_data[index][column_name][pv_capacity][ess_capacity]) | ||||
|                 # months_csv_data[index][column_name][pv_capacity][ess_capacity] = months_csv_data[index][column_name][pv_capacity][ess_capacity].tolist() | ||||
|  | ||||
|         # spring_consume_data = [] | ||||
|         # summer_consume_data = [] | ||||
|         # autumn_consume_data = [] | ||||
|         # winter_consume_data = [] | ||||
|         # for index, row in data.iterrows(): | ||||
|             # if index in range(spring_week_start, spring_week_end): | ||||
|                 # spring_consume_data.append(row['demand']) | ||||
|         #     elif index in range(summer_week_start, summer_week_end): | ||||
|         #         summer_consume_data.append(row['demand']) | ||||
|         #     elif index in range(autumn_week_start, autumn_week_end): | ||||
|         #         autumn_consume_data.append(row['demand']) | ||||
|         #     elif index in range(winter_week_start, winter_week_end): | ||||
|         #         winter_consume_data.append(row['demand']) | ||||
|  | ||||
|         # spring_week_time = list(range(spring_week_start, spring_week_end)) | ||||
|         # summer_week_time = list(range(summer_week_start, summer_week_end)) | ||||
|         # autumn_week_time = list(range(autumn_week_start, autumn_week_end)) | ||||
|         # winter_week_time = list(range(winter_week_start, winter_week_end)) | ||||
|  | ||||
|         # spring_pv_generated = energySystem.spring_week_gen | ||||
|         # summer_pv_generated = energySystem.summer_week_gen | ||||
|         # autumn_pv_generated = energySystem.autumn_week_gen | ||||
|         # winter_pv_generated = energySystem.winter_week_gen | ||||
|  | ||||
|         # spring_soc = energySystem.spring_week_soc | ||||
|         # summer_soc = energySystem.summer_week_soc | ||||
|         # autumn_soc = energySystem.autumn_week_soc | ||||
|         # winter_soc = energySystem.winter_week_soc | ||||
|             data[pv_capacity][ess_capacity] = annual_data | ||||
|     return data  | ||||
|  | ||||
|  | ||||
|         # fig, ax1 = plt.subplots() | ||||
|  | ||||
|         # plt.plot(spring_week_time, spring_pv_generated, label = 'pv generation') | ||||
|         # plt.plot(spring_week_time, spring_consume_data, label = 'factory consume') | ||||
|         # plt.ylabel('Power / kW') | ||||
|         # plt.xlabel('15 min #') | ||||
|         # plt.title(f'ess: {energySystem.ess.capacity/1000 } MWh pv: {energySystem.pv.capacity/1000 } MW spring week generate condition') | ||||
|         # plt.legend() | ||||
|         # plt.savefig(f'plots/{energySystem.ess.capacity}-{energySystem.pv.capacity}-spring.png') | ||||
|         # plt.close() | ||||
|  | ||||
|         # plt.plot(summer_week_time, summer_pv_generated, label = 'pv generation') | ||||
|         # plt.plot(summer_week_time, summer_consume_data, label = 'factory consume') | ||||
|         # plt.ylabel('Power / kW') | ||||
|         # plt.xlabel('15 min #') | ||||
|         # plt.title(f'ess: {energySystem.ess.capacity/1000 } MWh pv: {energySystem.pv.capacity/1000 } MW summer week generate condition') | ||||
|         # plt.legend() | ||||
|         # plt.savefig(f'plots/{energySystem.ess.capacity}-{energySystem.pv.capacity}-summer.png') | ||||
|         # plt.close() | ||||
|  | ||||
|         # plt.plot(autumn_week_time, autumn_pv_generated, label = 'pv generation') | ||||
|         # plt.plot(autumn_week_time, autumn_consume_data, label = 'factory consume') | ||||
|         # plt.ylabel('Power / kW') | ||||
|         # plt.xlabel('15 min #') | ||||
|         # plt.title(f'ess: {energySystem.ess.capacity/1000 } MWh pv: {energySystem.pv.capacity/1000 } MW autumn week generate condition') | ||||
|         # plt.legend() | ||||
|         # plt.savefig(f'plots/{energySystem.ess.capacity}-{energySystem.pv.capacity}-autumn.png') | ||||
|         # plt.close() | ||||
|  | ||||
|         # plt.plot(winter_week_time, winter_pv_generated, label = 'pv generation') | ||||
|         # plt.plot(winter_week_time, winter_consume_data, label = 'factory consume') | ||||
|         # plt.ylabel('Power / kW') | ||||
|         # plt.xlabel('15 min #') | ||||
|         # plt.title(f'ess: {energySystem.ess.capacity/1000 } MWh pv: {energySystem.pv.capacity/1000 } MW winter week generate condition') | ||||
|         # plt.legend() | ||||
|         # plt.savefig(f'plots/{energySystem.ess.capacity}-{energySystem.pv.capacity}-winter.png') | ||||
|         # plt.close() | ||||
|  | ||||
|     # plt.figure(); | ||||
|     # plt.plot(pv_generated) | ||||
|     # plt.xlabel('day #') | ||||
|     # plt.ylabel('Electricity kWh') | ||||
|     # plt.title(f'PV generated pv cap:{pv_capacity}, ess cap:{ess_capacity}') | ||||
|     # plt.savefig(f'plots/pv/{pv_capacity}-{ess_capacity}.png') | ||||
|     # plt.close() | ||||
| # In[102]: | ||||
|  | ||||
|  | ||||
|         # plt.show() | ||||
| annual_pv_gen = collapse_months_csv_data(months_csv_data, "pv_generate", pv_capacities, ess_capacities) | ||||
| annual_time = collapse_months_csv_data(months_csv_data, "time", pv_capacities, ess_capacities) | ||||
| annual_buy_price = collapse_months_csv_data(months_csv_data, "buy_price",pv_capacities, ess_capacities) | ||||
| annual_sell_price = collapse_months_csv_data(months_csv_data, "sell_price", pv_capacities, ess_capacities) | ||||
| annual_factory_demand = collapse_months_csv_data(months_csv_data, "factory_demand", pv_capacities, ess_capacities) | ||||
| annual_grid_need_power = collapse_months_csv_data(months_csv_data, "grid_need_power", pv_capacities, ess_capacities) | ||||
|  | ||||
| from datetime import datetime, timedelta | ||||
|  | ||||
| for pv_capacity in pv_capacities: | ||||
|     for ess_capacity in ess_capacities: | ||||
|         with open(f'data/annual_data-pv-{pv_capacity}-ess-{ess_capacity}.csv', 'w') as f: | ||||
|             f.write("date, time,pv_generate (kW),factory_demand (kW),buy_price (USD/MWh),sell_price (USD/MWh),grid_need_power (kW)\n") | ||||
|             start_date = datetime(2023, 1, 1, 0, 0, 0) | ||||
|             for i in range(len(annual_time[pv_capacity][ess_capacity])): | ||||
|                 current_date = start_date + timedelta(hours=i) | ||||
|                 formate_date = current_date.strftime("%Y-%m-%d") | ||||
|                 f.write(f"{formate_date},{annual_time[pv_capacity][ess_capacity][i]},{int(annual_pv_gen[pv_capacity][ess_capacity][i])},{int(annual_factory_demand[pv_capacity][ess_capacity][i])},{int(annual_buy_price[pv_capacity][ess_capacity][i]*1000)},{int(annual_sell_price[pv_capacity][ess_capacity][i]*1000)},{int(annual_grid_need_power[pv_capacity][ess_capacity][i])} \n") | ||||
|  | ||||
|  | ||||
|          | ||||
|  | ||||
| # results = results.astype(float) | ||||
|  | ||||
|  | ||||
| # pv = pv_config(capacity=100000,cost_per_kW=200,lifetime=25,loss=0.95) | ||||
| # ess = ess_config(capacity=100000,cost_per_kW=300,lifetime=25,loss=0.95,charge_power=100000,discharge_power=100000) | ||||
| # grid = grid_config(price_schedule=price_schedule, capacity=5000, grid_loss=0.95, sell_price=0.4) | ||||
| # grid = grid_config(capacity=50000, grid_loss=0.95, sell_price=0.4) | ||||
|  | ||||
|  | ||||
|     # print(benefit) | ||||
|  | ||||
|  | ||||
| # In[20]: | ||||
| # In[96]: | ||||
|  | ||||
|  | ||||
| def save_data(data, filename): | ||||
| @@ -262,83 +547,25 @@ def save_data(data, filename): | ||||
|     data.to_json(filename + '.json') | ||||
|  | ||||
|  | ||||
| # In[21]: | ||||
| # In[97]: | ||||
|  | ||||
|  | ||||
| import matplotlib.ticker as ticker | ||||
|  | ||||
| if not os.path.isdir('data'): | ||||
|     os.makedirs('data') | ||||
|  | ||||
| save_data(results, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-results') | ||||
| save_data(costs, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-costs') | ||||
| save_data(overload_cnt, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-overload_cnt') | ||||
| df=results | ||||
| df = df.astype(float) | ||||
| df.index = df.index / 1000 | ||||
| df.columns = df.columns / 1000 | ||||
| min_value = df.min().min() | ||||
| max_value = df.max().max() | ||||
| max_scale = max(abs(min_value/1000), abs(max_value/1000)) | ||||
| plt.figure(figsize=figure_size) | ||||
| cmap = sns.color_palette("coolwarm", as_cmap=True) | ||||
| ax = sns.heatmap(df/1000, fmt=".1f", cmap=cmap, vmin=-max_scale, vmax=max_scale, annot=annot_benefit) | ||||
| # ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f')) | ||||
| plt.title(title_benefit) | ||||
| plt.gca().invert_yaxis() | ||||
| plt.xlabel('ESS Capacity (MWh)') | ||||
| plt.ylabel('PV Capacity (MW)') | ||||
| plt.savefig('plots/benefit.png') | ||||
| save_data(annual_result, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-results') | ||||
| save_data(annual_costs, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-costs') | ||||
| save_data(annual_overload, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-overload_cnt') | ||||
|  | ||||
|  | ||||
| # In[22]: | ||||
| # In[98]: | ||||
|  | ||||
|  | ||||
| df = costs | ||||
| df = df.astype(int) | ||||
| df.index = df.index / 1000 | ||||
| df.columns = df.columns / 1000 | ||||
|  | ||||
| plt.figure(figsize=figure_size) | ||||
| sns.heatmap(df/1000000,  fmt=".1f", cmap='viridis', annot=annot_cost) | ||||
| plt.title(title_cost) | ||||
| plt.gca().invert_yaxis() | ||||
| plt.xlabel('ESS Capacity (MWh)') | ||||
| plt.ylabel('PV Capacity (MW)') | ||||
| plt.savefig('plots/costs.png') | ||||
|  | ||||
|     # pv = pv_config(capacity=100000,cost_per_kW=200,lifetime=25,loss=0.95) | ||||
|     # ess = ess_config(capacity=100000,cost_per_kW=300,lifetime=25,loss=0.95,charge_power=100000,discharge_power=100000) | ||||
|     # grid = grid_config(price_schedule=price_schedule, capacity=5000, grid_loss=0.95, sell_price=0.4) | ||||
|     # grid = grid_config(capacity=50000, grid_loss=0.95, sell_price=0.4) | ||||
| draw_results(annual_result, 'plots/test.png', 'test', False) | ||||
|  | ||||
|  | ||||
|     # print(benefit) | ||||
| # In[99]: | ||||
|  | ||||
|  | ||||
| # In[23]: | ||||
|  | ||||
|  | ||||
| from matplotlib.colors import LinearSegmentedColormap | ||||
| df = overload_cnt | ||||
| df = df.astype(int) | ||||
| df.index = df.index / 1000 | ||||
| df.columns = df.columns / 1000 | ||||
| min_value = df.min().min() | ||||
| max_value = df.max().max() | ||||
| max_scale = max(abs(min_value/1000), abs(max_value/1000)) | ||||
|  | ||||
| plt.figure(figsize=figure_size) | ||||
| cmap = LinearSegmentedColormap.from_list("", ["white", "blue"]) | ||||
| ax = sns.heatmap(df/(4*24*365), fmt=".00%", cmap=cmap, vmin=0, vmax=1, annot=annot_unmet) | ||||
| cbar = ax.collections[0].colorbar | ||||
| cbar.set_ticks([0, 0.25, 0.5, 0.75, 1]) | ||||
| cbar.set_ticklabels(['0%', '25%', '50%', '75%', '100%']) | ||||
| cbar.ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: f'{x:.0%}')) | ||||
|  | ||||
| plt.title(title_unmet) | ||||
| plt.gca().invert_yaxis() | ||||
| plt.xlabel('ESS Capacity (MWh)') | ||||
| plt.ylabel('PV Capacity (MW)') | ||||
| plt.savefig('plots/unmet.png') | ||||
| draw_roi(annual_costs, annual_nettos, 'plots/annual_roi.png',  title_roi, 365, annot_benefit, figure_size) | ||||
|  | ||||
|   | ||||
							
								
								
									
										68
									
								
								read_data.py
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								read_data.py
									
									
									
									
									
								
							| @@ -1,57 +1,47 @@ | ||||
| import pandas as pd | ||||
| import numpy as np | ||||
| import csv | ||||
| import json | ||||
|  | ||||
| sunlight_file_name = 'lightintensity.xlsx' | ||||
| factory_demand_file_name = 'factory_power1.xlsx' | ||||
| with open('config.json', 'r') as f: | ||||
|     js_data = json.load(f) | ||||
|  | ||||
| df_sunlight = pd.read_excel(sunlight_file_name, header=None, names=['SunlightIntensity']) | ||||
| pv_yield_file_name = js_data["data_path"]["pv_yield"] | ||||
| print(pv_yield_file_name) | ||||
| # factory_demand_file_name = 'factory_power1.xlsx' | ||||
| factory_demand_file_name = js_data["data_path"]["demand"] | ||||
| print(factory_demand_file_name) | ||||
| electricity_price_data = js_data["data_path"]["buy"] | ||||
| print(electricity_price_data) | ||||
| electricity_price_data_sell = js_data["data_path"]["sell"] | ||||
| print(electricity_price_data_sell) | ||||
|  | ||||
| start_date = '2023-01-01 00:00:00'  # 根据数据的实际开始日期调整 | ||||
| hours = pd.date_range(start=start_date, periods=len(df_sunlight), freq='h') | ||||
| df_sunlight['Time'] = hours | ||||
| df_sunlight.set_index('Time', inplace=True) | ||||
| pv_df = pd.read_csv(pv_yield_file_name, index_col='Time', usecols=['Time', 'PV yield[kW/kWp]']) | ||||
| pv_df.index = pd.to_datetime(pv_df.index) | ||||
|  | ||||
| df_sunlight_resampled = df_sunlight.resample('15min').interpolate() | ||||
|  | ||||
| df_power = pd.read_excel(factory_demand_file_name,  | ||||
|                          header=None,  | ||||
|                          names=['FactoryPower'],  | ||||
|                          dtype={'FactoryPower': float}) | ||||
| times = pd.date_range(start=start_date, periods=len(df_power), freq='15min') | ||||
| df_power['Time'] = times | ||||
| df_power.set_index('Time',inplace=True) | ||||
| print(df_power.head()) | ||||
|  | ||||
| df_combined = df_sunlight_resampled.join(df_power) | ||||
|  | ||||
| df_combined.to_csv('combined_data.csv', index=True, index_label='Time') | ||||
|  | ||||
| price_data = np.random.uniform(0.3, 0.3, len(times)) | ||||
|  | ||||
| # 创建DataFrame | ||||
| price_df = pd.DataFrame(data={'Time': times, 'ElectricityPrice': price_data}) | ||||
|  | ||||
| price_df.set_index('Time', inplace=True) | ||||
|  | ||||
| # 保存到CSV文件 | ||||
| price_df.to_csv('electricity_price_data.csv', index=True) | ||||
| print(price_df.head()) | ||||
| print("Electricity price data generated and saved.") | ||||
| df_power = pd.read_csv(factory_demand_file_name, index_col='Time', usecols=['Time', 'FactoryPower']) | ||||
| df_power.index = pd.to_datetime(df_power.index) | ||||
| df_combined = pv_df.join(df_power) | ||||
|  | ||||
| price_df = pd.read_csv(electricity_price_data, index_col='Time', usecols=['Time', 'ElectricityBuy']) | ||||
| price_df.index = pd.to_datetime(price_df.index) | ||||
| price_df = price_df.reindex(df_combined.index) | ||||
| df_combined2 = df_combined.join(price_df) | ||||
| print(df_combined2.head()) | ||||
| # 保存结果 | ||||
|  | ||||
| sell_df = pd.read_csv(electricity_price_data_sell, index_col='Time', usecols=['Time', 'ElectricitySell']) | ||||
| sell_df.index = pd.to_datetime(sell_df.index) | ||||
| sell_df = sell_df.reindex(df_combined.index) | ||||
| df_combined3 = df_combined2.join(sell_df) | ||||
|  | ||||
| with open('combined_data.csv', 'w', newline='') as file: | ||||
|     writer = csv.writer(file) | ||||
|     writer.writerow(['time', 'sunlight', 'demand','price']) | ||||
|     writer.writerow(['time', 'PV yield[kW/kWp]', 'demand','buy', 'sell']) | ||||
|     cnt = 0 | ||||
|     for index, row in df_combined2.iterrows(): | ||||
|     for index, row in df_combined3.iterrows(): | ||||
|         time_formatted = index.strftime('%H:%M') | ||||
|         writer.writerow([time_formatted, row['SunlightIntensity'], row['FactoryPower'],row['ElectricityPrice']]) | ||||
|         writer.writerow([time_formatted, row['PV yield[kW/kWp]'], row['FactoryPower'],row['ElectricityBuy'], row['ElectricitySell']]) | ||||
|          | ||||
|     print('The file is written to combined_data.csv') | ||||
|  | ||||
| # combined_data.to_csv('updated_simulation_with_prices.csv', index=False) | ||||
|  | ||||
| print("Simulation data with electricity prices has been updated and saved.") | ||||
							
								
								
									
										35041
									
								
								read_data/Berlin.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35041
									
								
								read_data/Berlin.csv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35041
									
								
								read_data/Cambodge.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35041
									
								
								read_data/Cambodge.csv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35041
									
								
								read_data/Marcedonia.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35041
									
								
								read_data/Marcedonia.csv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35041
									
								
								read_data/Riyahd.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35041
									
								
								read_data/Riyahd.csv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35041
									
								
								read_data/Serbia.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35041
									
								
								read_data/Serbia.csv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										372
									
								
								read_data/convert_data.ipynb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								read_data/convert_data.ipynb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,372 @@ | ||||
| { | ||||
|  "cells": [ | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 85, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import matplotlib.pyplot as plt\n", | ||||
|     "import pandas as pd\n", | ||||
|     "import numpy as np\n", | ||||
|     "import os\n", | ||||
|     "import csv" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 86, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "def read_csv(filename):\n", | ||||
|     "    skip_rows = list(range(1, 17))\n", | ||||
|     "    data = pd.read_csv(filename, sep=';', skiprows=skip_rows)\n", | ||||
|     "    return data" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 87, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stderr", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "/tmp/ipykernel_3075037/3659192646.py:3: DtypeWarning: Columns (32,33,35) have mixed types. Specify dtype option on import or set low_memory=False.\n", | ||||
|       "  data = pd.read_csv(filename, sep=';', skiprows=skip_rows)\n" | ||||
|      ] | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "Index(['Time', 'Irradiance onto horizontal plane ',\n", | ||||
|        "       'Diffuse Irradiation onto Horizontal Plane ', 'Outside Temperature ',\n", | ||||
|        "       'Module Area 1: Height of Sun ',\n", | ||||
|        "       'Module Area 1: Irradiance onto tilted surface ',\n", | ||||
|        "       'Module Area 1: Module Temperature ', 'Grid Export ',\n", | ||||
|        "       'Energy from Grid ', 'Global radiation - horizontal ',\n", | ||||
|        "       'Deviation from standard spectrum ', 'Ground Reflection (Albedo) ',\n", | ||||
|        "       'Orientation and inclination of the module surface ', 'Shading ',\n", | ||||
|        "       'Reflection on the Module Surface ',\n", | ||||
|        "       'Irradiance on the rear side of the module ',\n", | ||||
|        "       'Global Radiation at the Module ',\n", | ||||
|        "       'Module Area 1: Reflection on the Module Surface ',\n", | ||||
|        "       'Module Area 1: Global Radiation at the Module ',\n", | ||||
|        "       'Global PV Radiation ', 'Bifaciality ', 'Soiling ',\n", | ||||
|        "       'STC Conversion (Rated Efficiency of Module) ', 'Rated PV Energy ',\n", | ||||
|        "       'Low-light performance ', 'Module-specific Partial Shading ',\n", | ||||
|        "       'Deviation from the nominal module temperature ', 'Diodes ',\n", | ||||
|        "       'Mismatch (Manufacturer Information) ',\n", | ||||
|        "       'Mismatch (Configuration/Shading) ',\n", | ||||
|        "       'Power optimizer (DC conversion/clipping) ',\n", | ||||
|        "       'PV Energy (DC) without inverter clipping ',\n", | ||||
|        "       'Failing to reach the DC start output ',\n", | ||||
|        "       'Clipping on account of the MPP Voltage Range ',\n", | ||||
|        "       'Clipping on account of the max. DC Current ',\n", | ||||
|        "       'Clipping on account of the max. DC Power ',\n", | ||||
|        "       'Clipping on account of the max. AC Power/cos phi ', 'MPP Matching ',\n", | ||||
|        "       'PV energy (DC) ',\n", | ||||
|        "       'Inverter 1 - MPP 1 - to Module Area 1: PV energy (DC) ',\n", | ||||
|        "       'Inverter 1 - MPP 2 - to Module Area 1: PV energy (DC) ',\n", | ||||
|        "       'Inverter 1 - MPP 3 - to Module Area 1: PV energy (DC) ',\n", | ||||
|        "       'Inverter 1 - MPP 4 - to Module Area 1: PV energy (DC) ',\n", | ||||
|        "       'Inverter 1 - MPP 5 - to Module Area 1: PV energy (DC) ',\n", | ||||
|        "       'Inverter 1 - MPP 6 - to Module Area 1: PV energy (DC) ',\n", | ||||
|        "       'Inverter 2 - MPP 1 - to Module Area 1: PV energy (DC) ',\n", | ||||
|        "       'Inverter 2 - MPP 2 - to Module Area 1: PV energy (DC) ',\n", | ||||
|        "       'Energy at the Inverter Input ',\n", | ||||
|        "       'Input voltage deviates from rated voltage ', 'DC/AC Conversion ',\n", | ||||
|        "       'Own Consumption (Standby or Night) ', 'Total Cable Losses ',\n", | ||||
|        "       'PV energy (AC) minus standby use ', 'Feed-in energy ',\n", | ||||
|        "       'Inverter 1 to Module Area 1: Own Consumption (Standby or Night) ',\n", | ||||
|        "       'Inverter 1 to Module Area 1: PV energy (AC) minus standby use ',\n", | ||||
|        "       'Inverter 2 to Module Area 1: Own Consumption (Standby or Night) ',\n", | ||||
|        "       'Inverter 2 to Module Area 1: PV energy (AC) minus standby use ',\n", | ||||
|        "       'Unnamed: 58'],\n", | ||||
|        "      dtype='object')" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 87, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "\n", | ||||
|     "file_name = 'Riyahd_raw.csv'\n", | ||||
|     "df = read_csv(file_name)\n", | ||||
|     "df.columns" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 88, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "remain_column = ['Time','PV energy (AC) minus standby use ']\n", | ||||
|     "energy_row_name = remain_column[1]\n", | ||||
|     "\n", | ||||
|     "df = df[remain_column]\n", | ||||
|     "df[energy_row_name] = df[energy_row_name].str.replace(',','.').astype(float)\n" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 89, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "770594.226863267" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 89, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "sum_energy = df[energy_row_name].sum()\n", | ||||
|     "sum_energy" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 90, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "1975.882632982736" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 90, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "sum_energy / 390" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 91, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "group_size = 15\n", | ||||
|     "df['group_id'] = df.index // group_size\n", | ||||
|     "\n", | ||||
|     "sums = df.groupby('group_id')[energy_row_name].sum()\n", | ||||
|     "sums_df = sums.reset_index(drop=True).to_frame(name = 'Energy')" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 92, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/plain": [ | ||||
|        "<bound method NDFrame.head of        Energy\n", | ||||
|        "0         0.0\n", | ||||
|        "1         0.0\n", | ||||
|        "2         0.0\n", | ||||
|        "3         0.0\n", | ||||
|        "4         0.0\n", | ||||
|        "...       ...\n", | ||||
|        "35035     0.0\n", | ||||
|        "35036     0.0\n", | ||||
|        "35037     0.0\n", | ||||
|        "35038     0.0\n", | ||||
|        "35039     0.0\n", | ||||
|        "\n", | ||||
|        "[35040 rows x 1 columns]>" | ||||
|       ] | ||||
|      }, | ||||
|      "execution_count": 92, | ||||
|      "metadata": {}, | ||||
|      "output_type": "execute_result" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "sums_df.head" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 93, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "                 Time\n", | ||||
|       "0 2023-01-01 00:00:00\n", | ||||
|       "1 2023-01-01 00:15:00\n", | ||||
|       "2 2023-01-01 00:30:00\n", | ||||
|       "3 2023-01-01 00:45:00\n", | ||||
|       "4 2023-01-01 01:00:00\n", | ||||
|       "                     Time\n", | ||||
|       "35035 2023-12-31 22:45:00\n", | ||||
|       "35036 2023-12-31 23:00:00\n", | ||||
|       "35037 2023-12-31 23:15:00\n", | ||||
|       "35038 2023-12-31 23:30:00\n", | ||||
|       "35039 2023-12-31 23:45:00\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "\n", | ||||
|     "start_date = '2023-01-01'\n", | ||||
|     "end_date = '2023-12-31'\n", | ||||
|     "\n", | ||||
|     "# 生成每天的15分钟间隔时间\n", | ||||
|     "all_dates = pd.date_range(start=start_date, end=end_date, freq='D')\n", | ||||
|     "all_times = pd.timedelta_range(start='0 min', end='1435 min', freq='15 min')\n", | ||||
|     "\n", | ||||
|     "# 生成完整的时间标签\n", | ||||
|     "date_times = [pd.Timestamp(date) + time for date in all_dates for time in all_times]\n", | ||||
|     "\n", | ||||
|     "# 创建DataFrame\n", | ||||
|     "time_frame = pd.DataFrame({\n", | ||||
|     "    'Time': date_times\n", | ||||
|     "})\n", | ||||
|     "\n", | ||||
|     "# 查看生成的DataFrame\n", | ||||
|     "print(time_frame.head())\n", | ||||
|     "print(time_frame.tail())\n" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 94, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "(35040, 1)\n", | ||||
|       "(35040, 1)\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "print(sums_df.shape)\n", | ||||
|     "print(time_frame.shape)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 95, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "# sums_df['Time'] = time_frame['Time']\n", | ||||
|     "sums_df = pd.concat([time_frame, sums_df], axis=1)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 96, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "                     Energy\n", | ||||
|       "Time                       \n", | ||||
|       "2023-01-01 00:00:00     0.0\n", | ||||
|       "2023-01-01 00:15:00     0.0\n", | ||||
|       "2023-01-01 00:30:00     0.0\n", | ||||
|       "2023-01-01 00:45:00     0.0\n", | ||||
|       "2023-01-01 01:00:00     0.0\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "sums_df.set_index('Time', inplace=True)\n", | ||||
|     "print(sums_df.head())" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 97, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "max_value = sums_df['Energy'].max()\n", | ||||
|     "sums_df['Energy'] = sums_df['Energy'] / max_value\n" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 98, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "def save_csv(df, filename, columns):\n", | ||||
|     "    tmp_df = df.copy()\n", | ||||
|     "    tmp_df[columns[1]] = tmp_df[columns[1]].round(4)\n", | ||||
|     "    with open(filename, 'w', newline='') as file:\n", | ||||
|     "        writer = csv.writer(file)\n", | ||||
|     "        writer.writerow(columns)\n", | ||||
|     "        for index, row in tmp_df.iterrows():\n", | ||||
|     "            time_formatted = index.strftime('%H:%M')\n", | ||||
|     "            writer.writerow([time_formatted, row[columns[1]]])\n", | ||||
|     "            \n", | ||||
|     "        print(f'The file is written to {filename}')\n", | ||||
|     "        \n", | ||||
|     "\n" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 99, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "The file is written to Riyahd.csv\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "save_csv(sums_df, 'Riyahd.csv', ['Time', 'Energy'])" | ||||
|    ] | ||||
|   } | ||||
|  ], | ||||
|  "metadata": { | ||||
|   "kernelspec": { | ||||
|    "display_name": "pv", | ||||
|    "language": "python", | ||||
|    "name": "python3" | ||||
|   }, | ||||
|   "language_info": { | ||||
|    "codemirror_mode": { | ||||
|     "name": "ipython", | ||||
|     "version": 3 | ||||
|    }, | ||||
|    "file_extension": ".py", | ||||
|    "mimetype": "text/x-python", | ||||
|    "name": "python", | ||||
|    "nbconvert_exporter": "python", | ||||
|    "pygments_lexer": "ipython3", | ||||
|    "version": "3.11.9" | ||||
|   } | ||||
|  }, | ||||
|  "nbformat": 4, | ||||
|  "nbformat_minor": 2 | ||||
| } | ||||
							
								
								
									
										79
									
								
								read_data/convert_data.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								read_data/convert_data.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| #!/usr/bin/env python | ||||
| # coding: utf-8 | ||||
|  | ||||
|  | ||||
| import matplotlib.pyplot as plt | ||||
| import pandas as pd | ||||
| import numpy as np | ||||
| import os | ||||
| import csv | ||||
|  | ||||
| def generate_min_df(mins = 15): | ||||
|     end = 60/mins * 24 | ||||
|     start_date = '2023-01-01' | ||||
|     end_date = '2023-12-31' | ||||
|  | ||||
|     all_dates = pd.date_range(start=start_date, end=end_date, freq='D') | ||||
|     all_times = pd.timedelta_range(start='0 min', end=f'1435 min', freq=f'{mins} min') | ||||
|  | ||||
|     date_times = [pd.Timestamp(date) + time for date in all_dates for time in all_times] | ||||
|  | ||||
|     time_frame = pd.DataFrame({ | ||||
|         'Time': date_times | ||||
|     }) | ||||
|     return time_frame | ||||
|  | ||||
| def save_csv(df, filename, columns): | ||||
|     with open(filename, 'w', newline='') as file: | ||||
|         writer = csv.writer(file) | ||||
|         writer.writerow(['Time', 'PV yield[kW/kWp]']) | ||||
|         for index, row in df.iterrows(): | ||||
|             time_formatted = index.strftime('%H:%M') | ||||
|             writer.writerow([time_formatted, row[columns[1]]]) | ||||
|              | ||||
|         print(f'The file is written to {filename}') | ||||
|  | ||||
| def read_csv(filename): | ||||
|     skip_rows = list(range(1, 17)) | ||||
|     data = pd.read_csv(filename, sep=';', skiprows=skip_rows) | ||||
|     return data | ||||
|  | ||||
| def process(file_name): | ||||
|     df = read_csv(file_name) | ||||
|     city = file_name.split('_')[0] | ||||
|  | ||||
|     remain_column = ['Time','PV energy (AC) minus standby use '] | ||||
|     energy_row_name = remain_column[1] | ||||
|  | ||||
|     df = df[remain_column] | ||||
|     df[energy_row_name] = df[energy_row_name].str.replace(',','.').astype(float) | ||||
|  | ||||
|     sum_energy = df[energy_row_name].sum() | ||||
|     group_size = 15 | ||||
|     df['group_id'] = df.index // group_size | ||||
|  | ||||
|     sums = df.groupby('group_id')[energy_row_name].sum() | ||||
|     sums_df = sums.reset_index(drop=True).to_frame(name = 'Energy') | ||||
|  | ||||
|     pv_energy_column_name = 'PV yield[kW/kWp]' | ||||
|     sums_df = sums_df.rename(columns={'Energy': pv_energy_column_name}) | ||||
|  | ||||
|     time_frame = generate_min_df(15) | ||||
|     sums_df = pd.concat([time_frame, sums_df], axis=1) | ||||
|     # sums_df.set_index('Time', inplace=True) | ||||
|     # max_value = sums_df[pv_energy_column_name].max() | ||||
|     sums_df[pv_energy_column_name] = sums_df[pv_energy_column_name] / 390. | ||||
|     sums_df[pv_energy_column_name] = sums_df[pv_energy_column_name].round(4) | ||||
|     sums_df[pv_energy_column_name].replace(0.0, -0.0) | ||||
|  | ||||
|     sums_df.to_csv(f'{city}.csv') | ||||
|     # save_csv(sums_df, f'{city}.csv', ['Time', 'Energy']) | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     city_list = ['Riyahd', 'Cambodge', 'Berlin', 'Serbia'] | ||||
|     for city in city_list: | ||||
|         print(f'Processing {city}') | ||||
|         file_name = f'{city}_raw.csv' | ||||
|         process(file_name) | ||||
|         print(f'Processing {city} is done\n') | ||||
|  | ||||
							
								
								
									
										35041
									
								
								read_data/electricity_price_data.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35041
									
								
								read_data/electricity_price_data.csv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35041
									
								
								read_data/electricity_price_data_sell.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35041
									
								
								read_data/electricity_price_data_sell.csv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35041
									
								
								read_data/factory_power1.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35041
									
								
								read_data/factory_power1.csv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										16
									
								
								xlsx2csv.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								xlsx2csv.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| import pandas as pd | ||||
|  | ||||
| excel_file = 'factory_power1.xlsx' | ||||
| sheet_name = 'Sheet1' | ||||
|  | ||||
| df = pd.read_excel(excel_file, sheet_name=sheet_name) | ||||
|  | ||||
| start_date = '2023-01-01' | ||||
| df_power = pd.read_excel(excel_file,  | ||||
|                          header=None,  | ||||
|                          names=['FactoryPower'],  | ||||
|                          dtype={'FactoryPower': float}) | ||||
| times = pd.date_range(start=start_date, periods=len(df_power), freq='15min') | ||||
| df_power['Time'] = times | ||||
| df_power = df_power[['Time', 'FactoryPower']] | ||||
| df_power.to_csv('factory_power1.csv', index=True) | ||||
		Reference in New Issue
	
	Block a user