From 4dbe3d50835f17cc4cc7356b88541b3911759274 Mon Sep 17 00:00:00 2001 From: dmy Date: Sat, 27 Dec 2025 16:30:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=85=88=E5=BC=83=E5=85=89=EF=BC=8C=E5=BD=93?= =?UTF-8?q?=E8=BE=BE=E5=88=B0=E6=9C=80=E5=A4=A7=E5=BC=83=E5=85=89=E6=AF=94?= =?UTF-8?q?=E4=BE=8B=E5=90=8E=EF=BC=8C=E5=86=8D=E5=BC=83=E9=A3=8E=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/storage_optimization.py | 117 +++++++++++------------------------- 1 file changed, 36 insertions(+), 81 deletions(-) diff --git a/src/storage_optimization.py b/src/storage_optimization.py index 525f7df..a52b6c6 100644 --- a/src/storage_optimization.py +++ b/src/storage_optimization.py @@ -145,28 +145,11 @@ def calculate_energy_balance( # 设置初始储能状态 storage_soc[0] = initial_soc - # 计算总发电潜力 - total_potential_wind = np.sum(wind) - total_potential_solar = np.sum(solar) - - # 判断是否只有一种可再生能源 - has_wind = total_potential_wind > 0 - has_solar = total_potential_solar > 0 - single_renewable = (has_wind and not has_solar) or (has_solar and not has_wind) - # 计算允许的最大弃风弃光量 - if single_renewable: - # 只有一种可再生能源时,弃电量不受限制 - max_curtailed_wind_total = float('inf') - max_curtailed_solar_total = float('inf') - elif params.max_grid_ratio == 0: - # 上网电量限制为0时,所有超额电力都必须被弃掉,不受弃风弃光限制 - max_curtailed_wind_total = float('inf') - max_curtailed_solar_total = float('inf') - else: - # 有多种可再生能源且上网电量限制不为0时,应用弃风弃光限制 - max_curtailed_wind_total = total_potential_wind * params.max_curtailment_wind - max_curtailed_solar_total = total_potential_solar * params.max_curtailment_solar + # 新逻辑:弃光受最大弃光比例限制,弃风不受限制 + total_solar_potential = sum(solar_output) + max_curtailed_solar_total = total_solar_potential * params.max_curtailment_solar + max_curtailed_wind_total = float('inf') # 弃风不受限制 # 初始化累计弃风弃光量 accumulated_curtailed_wind = 0.0 @@ -224,55 +207,24 @@ def calculate_energy_balance( # 剩余电力考虑弃风弃光 remaining_surplus -= grid_feed_allowed - # 计算弃风弃光(优先弃光,然后弃风) + # 计算弃风弃光(新逻辑:先弃光,当达到最大弃光比例后,再弃风,弃风不限) if remaining_surplus > 0: - # 在单一可再生能源场景下,弃风弃光不受限制 - if single_renewable: - # 优先弃光 - if solar[hour] > 0: - curtailed_solar[hour] = min(solar[hour], remaining_surplus) - remaining_surplus -= curtailed_solar[hour] - accumulated_curtailed_solar += curtailed_solar[hour] - - # 如果还有剩余,弃风 - if remaining_surplus > 0 and wind[hour] > 0: - curtailed_wind[hour] = min(wind[hour], remaining_surplus) - remaining_surplus -= curtailed_wind[hour] - accumulated_curtailed_wind += curtailed_wind[hour] - else: - # 混合可再生能源场景,弃风弃光受限制 - # 计算当前可弃光量 - if max_curtailed_solar_total == float('inf'): - # 无限制弃光 - available_solar_curtail = solar[hour] - else: - # 受限制弃光 - available_solar_curtail = min( - solar[hour], - max_curtailed_solar_total - accumulated_curtailed_solar - ) - - if available_solar_curtail > 0: - curtailed_solar[hour] = min(available_solar_curtail, remaining_surplus) - remaining_surplus -= curtailed_solar[hour] - accumulated_curtailed_solar += curtailed_solar[hour] - - # 如果还有剩余,弃风 - if remaining_surplus > 0: - if max_curtailed_wind_total == float('inf'): - # 无限制弃风 - available_wind_curtail = wind[hour] - else: - # 受限制弃风 - available_wind_curtail = min( - wind[hour], - max_curtailed_wind_total - accumulated_curtailed_wind - ) - - if available_wind_curtail > 0: - curtailed_wind[hour] = min(available_wind_curtail, remaining_surplus) - remaining_surplus -= curtailed_wind[hour] - accumulated_curtailed_wind += curtailed_wind[hour] + # 计算当前还能弃光的量 + remaining_solar_curtailment_quota = max_curtailed_solar_total - accumulated_curtailed_solar + + # 优先弃光,但不超过最大弃光比例 + if solar[hour] > 0 and remaining_solar_curtailment_quota > 0: + # 可以弃光的量取:光伏出力、剩余盈余电力、剩余弃光配额的最小值 + curtailed_solar[hour] = min(solar[hour], remaining_surplus, remaining_solar_curtailment_quota) + remaining_surplus -= curtailed_solar[hour] + accumulated_curtailed_solar += curtailed_solar[hour] + + # 如果还有剩余电力,弃风(弃风不限) + if remaining_surplus > 0 and wind[hour] > 0: + # 弃风不受限制,可以弃掉所有剩余风电 + curtailed_wind[hour] = min(wind[hour], remaining_surplus) + remaining_surplus -= curtailed_wind[hour] + accumulated_curtailed_wind += curtailed_wind[hour] # 确保电力平衡:如果仍有剩余电力,强制弃掉(安全机制) if remaining_surplus > 0: @@ -408,6 +360,7 @@ def check_constraints( solar_output: 光伏出力曲线 (MW) - 支持24小时或8760小时 wind_output: 风电出力曲线 (MW) - 支持24小时或8760小时 thermal_output: 火电出力曲线 (MW) - 支持24小时或8760小时 + load_demand: 负荷曲线 (MW) - 支持24小时或8760小时 balance_result: 电能平衡计算结果 params: 系统参数配置 @@ -456,7 +409,6 @@ def optimize_storage_capacity( Args: solar_output: 光伏出力曲线 (MW) - 支持24小时或8760小时 wind_output: 风电出力曲线 (MW) - 支持24小时或8760小时 - thermal_output: 火电出力曲线 (MW) - 支持24小时或8760小时 load_demand: 负荷曲线 (MW) - 支持24小时或8760小时 params: 系统参数配置 max_iterations: 最大迭代次数 @@ -526,19 +478,22 @@ def optimize_storage_capacity( grid_constraint_satisfied = constraint_results['total_grid_feed_in_ratio'] <= params.max_grid_ratio else: grid_constraint_satisfied = True + + # 新逻辑:弃光受最大弃光比例限制,弃风不受限制 + solar_constraint_satisfied = constraint_results['total_curtailment_solar_ratio'] <= params.max_curtailment_solar + # 弃风不受限制,始终满足 + wind_constraint_satisfied = True + + # 考虑浮点数误差,判断上网电量比例是否为0 + grid_quota_zero = abs(params.max_grid_ratio) < 1e-10 - has_wind = sum(wind_output) > 0 - has_solar = sum(solar_output) > 0 - single_renewable = (has_wind and not has_solar) or (has_solar and not has_wind) - grid_quota_zero = params.max_grid_ratio == 0 - - if single_renewable or grid_quota_zero: - constraints_satisfied = grid_constraint_satisfied + if grid_quota_zero: + constraints_satisfied = grid_constraint_satisfied and solar_constraint_satisfied else: constraints_satisfied = ( - constraint_results['total_curtailment_wind_ratio'] <= params.max_curtailment_wind and - constraint_results['total_curtailment_solar_ratio'] <= params.max_curtailment_solar and - grid_constraint_satisfied + solar_constraint_satisfied and # 弃光受限制 + wind_constraint_satisfied and # 弃风不受限制 + grid_constraint_satisfied # 上网电量受限制 ) # 检查储能日平衡(周期结束时储能状态应接近初始值) @@ -766,4 +721,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main()