diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a93d29e --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +/.idea/ diff --git a/models/env.py b/models/env.py index ebb826c..93b3db3 100644 --- a/models/env.py +++ b/models/env.py @@ -9,11 +9,8 @@ from parameters import * class WgzGym(gym.Env): def __init__(self, **kwargs): super(WgzGym, self).__init__() - self.excess = None - self.shedding = None self.unbalance = None - self.real_unbalance = None - self.operation_cost = None + self.reward = None self.current_output = None self.final_step_outputs = None self.data_manager = DataManager() @@ -24,7 +21,7 @@ class WgzGym(gym.Env): self.current_time = None self.episode_length = 24 self.penalty_coefficient = 50 # 约束惩罚系数 - self.sell_coefficient = 0.1 # 售出利润系数 + self.sell_coefficient = 0.5 # 售出利润系数 self.EC_parameters = kwargs.get('EC_parameters', EC_parameters) # 电解水制氢器 self.HST_parameters = kwargs.get('dg_parameters', dg_parameters) # 储氢罐 @@ -35,7 +32,7 @@ class WgzGym(gym.Env): self.action_space = gym.spaces.Box(low=-1, high=1, shape=(3,), dtype=np.float32) ''' 时间 光伏 温度(湿度暂未考虑) 电需 热需(转化为对应热水所需瓦数) 人数 电价 7 - 电解水制氢功率 市电功率 储氢罐容量占比 3 + 电解水制氢功率 储氢罐容量占比 市电功率(注意标准化) 3 ''' self.state_space = gym.spaces.Box(low=0, high=1, shape=(10,), dtype=np.float32) @@ -51,8 +48,8 @@ class WgzGym(gym.Env): return self._build_state() def _build_state(self): - soc = self.HST.SOC() - ec_output = self.EC.current_output + hst_soc = self.HST.current_soc + ec_out = self.EC.get_hydrogen() time_step = self.current_time price = self.data_manager.get_price_data(self.month, self.day, self.current_time) @@ -62,63 +59,42 @@ class WgzGym(gym.Env): heat = self.data_manager.get_heat_data(self.month, self.day, self.current_time) people = self.data_manager.get_people_data(self.month, self.day, self.current_time) - obs = np.concatenate((np.float32(time_step), np.float32(soc), np.float32(price), np.float32(netload), - np.float32(dg1_output), np.float32(dg2_output), np.float32(dg3_output), - np.float32(temperature), np.float32(irradiance), np.float32(windspeed)), axis=None) + obs = np.concatenate((np.float32(time_step), np.float32(price), np.float32(temper), + np.float32(solar), np.float32(load), np.float32(heat), + np.float32(people), np.float32(ec_out), np.float32(hst_soc), np.float32(wind)), axis=None) return obs - def step(self, action): # state transition: current_obs->take_action->get_reward->get_finish->next_obs + def step(self, action): # 在每个组件中添加动作 current_obs = self._build_state() - temperature = current_obs[7] - irradiance = current_obs[8] - self.wind.current_power = current_obs[9] - self.battery.step(action[0]) # 执行状态转换,电池当前容量也改变 - self.dg1.step(action[1]) + self.EC.step(action[0]) # 执行状态转换,电池当前容量也改变 + self.HST.step(action[1]) self.dg2.step(action[2]) - self.dg3.step(action[3]) - self.solar.step(temperature, irradiance, action[4]) - self.current_output = np.array((self.dg1.current_output, self.dg2.current_output, self.dg3.current_output, - -self.battery.energy_change, self.solar.current_power, self.wind.current_power)) - actual_production = sum(self.current_output) price = current_obs[1] - netload = current_obs[3] - self.solar.output_change - unbalance = actual_production - netload + temper = current_obs[2] + solar = current_obs[3] + load = current_obs[4] + heat = current_obs[5] + gym_to_grid = solar + self.EC.get_hydrogen() - load # reward = 0.0 - excess_penalty = 0 - deficient_penalty = 0 sell_benefit, buy_cost = 0, 0 - self.excess, self.shedding = 0, 0 - if unbalance >= 0: # 过剩 - if unbalance <= self.grid.exchange_ability: - sell_benefit = self.grid.get_cost(price, unbalance) * self.sell_coefficient - else: - sell_benefit = self.grid.get_cost(price, self.grid.exchange_ability) * self.sell_coefficient - # real unbalance:超电网限值 - self.excess = unbalance - self.grid.exchange_ability - excess_penalty = self.excess * self.penalty_coefficient - else: # unbalance <0, 缺少惩罚 - if abs(unbalance) <= self.grid.exchange_ability: - buy_cost = self.grid.get_cost(price, abs(unbalance)) - else: - buy_cost = self.grid.get_cost(price, self.grid.exchange_ability) - self.shedding = abs(unbalance) - self.grid.exchange_ability - deficient_penalty = self.shedding * self.penalty_coefficient - battery_cost = self.battery.get_cost(self.battery.energy_change) - dg1_cost = self.dg1.get_cost(self.dg1.current_output) - dg2_cost = self.dg2.get_cost(self.dg2.current_output) - dg3_cost = self.dg3.get_cost(self.dg3.current_output) - solar_cost = self.solar.get_cost(self.solar.current_power) - wind_cost = self.wind.gen_cost(self.wind.current_power) + excess_penalty, deficient_penalty = 0, 0 + if gym_to_grid >= 0: # 过剩 + sell_benefit = self.grid.get_cost(price, gym_to_grid) * self.sell_coefficient + excess_penalty = gym_to_grid * self.penalty_coefficient + else: # 缺少 + buy_cost = self.grid.get_cost(price, abs(gym_to_grid)) + deficient_penalty = abs(gym_to_grid) * self.penalty_coefficient - self.operation_cost = (battery_cost + dg1_cost + dg2_cost + dg3_cost + solar_cost + wind_cost - + excess_penalty + deficient_penalty - sell_benefit + buy_cost) - reward = - self.operation_cost / 1e3 - self.unbalance = unbalance - self.real_unbalance = self.shedding + self.excess - final_step_outputs = [self.dg1.current_output, self.dg2.current_output, self.dg3.current_output, - self.battery.current_capacity, self.solar.current_power, self.wind.current_power] + hst_cost = self.HST.get_cost() + ec_cost = self.EC.get_cost(price) + solar_cost = solar # 待补充 + reward = - (hst_cost + ec_cost + solar_cost + + excess_penalty + deficient_penalty - sell_benefit + buy_cost) + + self.unbalance = gym_to_grid + final_step_outputs = [self.HST.current_soc, self.EC.current_power, self.grid.current_power] self.current_time += 1 finish = (self.current_time == self.episode_length) if finish: diff --git a/models/module.py b/models/module.py index 3154fe4..03a6f00 100644 --- a/models/module.py +++ b/models/module.py @@ -1,61 +1,63 @@ class EC: def __init__(self, params): - self.current_output = None - self.electricity_efficiency = params['electricity_efficiency'] + self.current_power = None self.hydrogen_produce = params['hydrogen_produce'] self.power_max = params['power_max'] self.power_min = params['power_min'] self.ramp = params['ramp'] self.lifetime = params['lifetime'] self.equipment_cost = params['equipment_cost'] + self.electricity_efficiency = params['electricity_efficiency'] self.carbon_reduce = params['carbon_reduce'] def step(self, action_ec): - output = self.current_output + action_ec * self.ramp + output = self.current_power + action_ec * self.ramp output = max(self.power_min, min(self.power_max, output)) if output > 0 else 0 - self.current_output = output + self.current_power = output def get_cost(self, price): - return self.equipment_cost / self.lifetime + price * self.current_output + # 成本 = 设备费用 / 生命周期 * 电价 * (用电量 / 最大用电量) + return self.equipment_cost / self.lifetime * price * self.current_power / self.power_max def get_hydrogen(self): - return self.current_output * self.electricity_efficiency * self.hydrogen_produce + return self.current_power * self.electricity_efficiency * self.hydrogen_produce + + def get_carbon(self): + return self.current_power * self.carbon_reduce def reset(self): - self.current_output = 0 + self.current_power = 0 class HST: def __init__(self, params): - self.current_capacity = None + self.current_soc = None self.hydrogen_change = None self.capacity = params['capacity'] self.min_soc = params['min_soc'] self.max_soc = params['max_soc'] - self.degradation = params['degradation'] - self.holding = params['holding'] self.ramp = params['ramp'] + self.lifetime = params['lifetime'] + self.equipment_cost = params['equipment_cost'] self.efficiency = params['efficiency'] ''' - 储氢罐的充气速率 = 电解水制氢速率 (电解水制氢会满足热水需求?) + 储氢罐的充气速率 = 电解水制氢速率 (电解水制氢放的热会满足热水需求?) + + 储氢罐的放气速率 = 供电 (电价低时多电解,电价高时释放) ''' def step(self, action_hst): energy = action_hst * self.ramp - current_energy = self.current_capacity * self.capacity - updated_capacity = max(self.min_soc, min(self.max_soc, (current_energy + energy) / self.capacity)) - self.hydrogen_change = (updated_capacity - self.current_capacity) * self.capacity - self.current_capacity = updated_capacity # update capacity to current state + updated_soc = max(self.min_soc, min(self.max_soc, (self.current_soc * self.capacity + energy) / self.capacity)) + self.hydrogen_change = (updated_capacity - self.current_soc) * self.capacity + self.current_soc = updated_soc - def get_cost(self, energy_change): - cost = abs(energy_change) * self.degradation + def get_cost(self): + cost = self.equipment_cost / self.lifetime * abs(self.hydrogen_change) return cost - def SOC(self): - return self.current_capacity - def reset(self): - self.current_capacity = 0.2 + self.current_soc = 0.1 class Grid: diff --git a/models/parameters.py b/models/parameters.py index 9ab1cc8..e715a3b 100644 --- a/models/parameters.py +++ b/models/parameters.py @@ -1,11 +1,11 @@ EC_parameters = { - 'electrolysis_efficiency': 0.8, 'hydrogen_produce': 0.5, 'power_max': 200, 'power_min': 0, 'ramp': 100, 'lifetime': 6000, # hour 'equipment_cost': 10000, # yuan + 'electrolysis_efficiency': 0.8, 'carbon_reduce': 1, } @@ -13,5 +13,7 @@ HST_parameters = { 'capacity': 1000, 'min_soc': 0.1, 'max_soc': 0.9, + 'lifetime': 6000, # hour + 'equipment_cost': 10000, # yuan 'efficiency': 0.95, } diff --git a/models/tools.py b/models/tools.py index 1432d1f..7440af6 100644 --- a/models/tools.py +++ b/models/tools.py @@ -11,8 +11,8 @@ def test_one_episode(env, act, device): record_init_info = [] # include month,day,time,intial soc env.TRAIN = False state = env.reset() - record_init_info.append([env.month, env.day, env.current_time, env.battery.current_capacity]) - print(f'current testing month is {env.month}, day is {env.day},initial_soc is {env.battery.current_capacity}') + record_init_info.append([env.month, env.day, env.current_time, env.battery.current_soc]) + print(f'current testing month is {env.month}, day is {env.day},initial_soc is {env.battery.current_soc}') for i in range(24): s_tensor = torch.as_tensor((state,), device=device) a_tensor = act(s_tensor)