From bdfabd7eba384bdb9c3407cabdc2fc0aa7d459e0 Mon Sep 17 00:00:00 2001 From: dmy Date: Thu, 25 Dec 2025 21:14:11 +0800 Subject: [PATCH] =?UTF-8?q?=E8=80=83=E8=99=91=E4=BA=86=E5=82=A8=E8=83=BD?= =?UTF-8?q?=E4=B8=8A=E9=99=90=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example_usage.py | 85 +++++++++++++++++++++++++++++++++++------ storage_optimization.py | 34 +++++++++++++++-- 2 files changed, 103 insertions(+), 16 deletions(-) diff --git a/example_usage.py b/example_usage.py index e68f208..96ba5cb 100644 --- a/example_usage.py +++ b/example_usage.py @@ -230,46 +230,104 @@ def plot_results(result, title, solar_output, wind_output, thermal_output, load_ plt.show() +def example_4_capacity_limited_scenario(): + """示例4: 储能容量限制场景""" + print("\n=== 示例4: 储能容量限制场景 ===") + + # 使用基础场景的数据 + solar_output = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 2.0, 4.0, 6.0, 8.0, 9.0, + 8.0, 6.0, 4.0, 2.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + + wind_output = [4.0, 4.5, 5.0, 5.5, 5.0, 4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, + 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 5.0, 4.5, 4.0] + + thermal_output = [8.0] * 24 + + load_demand = [6.0, 5.5, 5.0, 5.0, 5.5, 7.0, 9.0, 12.0, 15.0, 18.0, 20.0, 19.0, + 18.0, 17.0, 16.0, 15.0, 14.0, 13.0, 12.0, 10.0, 8.0, 7.0, 6.0, 6.0] + + # 系统参数 - 设置储能容量上限为10 MWh + params = SystemParameters( + max_curtailment_wind=0.1, + max_curtailment_solar=0.05, + max_grid_ratio=0.15, + storage_efficiency=0.9, + discharge_rate=1.0, + charge_rate=1.0, + max_storage_capacity=10.0 # 限制储能容量上限为10 MWh + ) + + result = optimize_storage_capacity(solar_output, wind_output, thermal_output, load_demand, params) + + print(f"所需储能容量: {result['required_storage_capacity']:.2f} MWh") + print(f"储能容量上限: {result['max_storage_limit']:.2f} MWh") + print(f"是否达到容量上限: {'是' if result['capacity_limit_reached'] else '否'}") + print(f"实际弃风率: {result['total_curtailment_wind_ratio']:.3f} (约束: {params.max_curtailment_wind})") + print(f"实际弃光率: {result['total_curtailment_solar_ratio']:.3f} (约束: {params.max_curtailment_solar})") + print(f"实际上网电量比例: {result['total_grid_feed_in_ratio']:.3f} (约束: {params.max_grid_ratio})") + print(f"能量平衡校验: {'通过' if result['energy_balance_check'] else '未通过'}") + + return { + 'result': result, + 'solar_output': solar_output, + 'wind_output': wind_output, + 'thermal_output': thermal_output, + 'load_demand': load_demand + } + + def compare_scenarios(): """比较不同场景的结果""" print("\n=== 场景比较 ===") - # 运行三个场景 + # 运行四个场景 data1 = example_1_basic_scenario() data2 = example_2_high_renewable_scenario() data3 = example_3_winter_scenario() + data4 = example_4_capacity_limited_scenario() # 比较结果 - scenarios = ['基础场景', '高可再生能源场景', '冬季场景'] + scenarios = ['基础场景', '高可再生能源场景', '冬季场景', '容量限制场景'] storage_capacities = [ data1['result']['required_storage_capacity'], data2['result']['required_storage_capacity'], - data3['result']['required_storage_capacity'] + data3['result']['required_storage_capacity'], + data4['result']['required_storage_capacity'] ] curtailment_wind = [ data1['result']['total_curtailment_wind_ratio'], data2['result']['total_curtailment_wind_ratio'], - data3['result']['total_curtailment_wind_ratio'] + data3['result']['total_curtailment_wind_ratio'], + data4['result']['total_curtailment_wind_ratio'] ] curtailment_solar = [ data1['result']['total_curtailment_solar_ratio'], data2['result']['total_curtailment_solar_ratio'], - data3['result']['total_curtailment_solar_ratio'] + data3['result']['total_curtailment_solar_ratio'], + data4['result']['total_curtailment_solar_ratio'] ] grid_feed_in = [ data1['result']['total_grid_feed_in_ratio'], data2['result']['total_grid_feed_in_ratio'], - data3['result']['total_grid_feed_in_ratio'] + data3['result']['total_grid_feed_in_ratio'], + data4['result']['total_grid_feed_in_ratio'] + ] + capacity_limit = [ + '无', + '无', + '无', + f"{data4['result']['max_storage_limit']:.1f}MWh" ] print("\n场景比较结果:") - print(f"{'场景':<15} {'储能容量(MWh)':<12} {'弃风率':<8} {'弃光率':<8} {'上网比例':<8}") - print("-" * 55) + print(f"{'场景':<15} {'储能容量(MWh)':<12} {'容量限制':<10} {'弃风率':<8} {'弃光率':<8} {'上网比例':<8}") + print("-" * 75) for i, scenario in enumerate(scenarios): - print(f"{scenario:<15} {storage_capacities[i]:<12.2f} {curtailment_wind[i]:<8.3f} " - f"{curtailment_solar[i]:<8.3f} {grid_feed_in[i]:<8.3f}") + limit_reached = "✓" if data4['result']['capacity_limit_reached'] and i == 3 else "" + print(f"{scenario:<15} {storage_capacities[i]:<12.2f} {capacity_limit[i]:<10} {curtailment_wind[i]:<8.3f} " + f"{curtailment_solar[i]:<8.3f} {grid_feed_in[i]:<8.3f} {limit_reached}") - return data1, data2, data3 + return data1, data2, data3, data4 if __name__ == "__main__": @@ -277,7 +335,7 @@ if __name__ == "__main__": print("=" * 50) # 运行示例 - data1, data2, data3 = compare_scenarios() + data1, data2, data3, data4 = compare_scenarios() # 绘制图表(如果matplotlib可用) try: @@ -290,6 +348,9 @@ if __name__ == "__main__": plot_results(data3['result'], "冬季场景储能运行情况", data3['solar_output'], data3['wind_output'], data3['thermal_output'], data3['load_demand']) + plot_results(data4['result'], "容量限制场景储能运行情况", + data4['solar_output'], data4['wind_output'], + data4['thermal_output'], data4['load_demand']) except ImportError: print("\n注意: matplotlib未安装,无法绘制图表") print("要安装matplotlib,请运行: pip install matplotlib") diff --git a/storage_optimization.py b/storage_optimization.py index 1e286d3..d4d9f9e 100644 --- a/storage_optimization.py +++ b/storage_optimization.py @@ -22,6 +22,7 @@ class SystemParameters: storage_efficiency: float = 0.9 # 储能充放电效率 (0.0-1.0) discharge_rate: float = 1.0 # 储能放电倍率 (C-rate) charge_rate: float = 1.0 # 储能充电倍率 (C-rate) + max_storage_capacity: Optional[float] = None # 储能容量上限 (MWh),None表示无限制 def validate_inputs( @@ -75,6 +76,8 @@ def validate_inputs( raise ValueError("储能效率必须在0.0-1.0之间") if params.discharge_rate <= 0 or params.charge_rate <= 0: raise ValueError("充放电倍率必须大于0") + if params.max_storage_capacity is not None and params.max_storage_capacity <= 0: + raise ValueError("储能容量上限必须大于0") def calculate_energy_balance( @@ -293,11 +296,18 @@ def optimize_storage_capacity( # 初始化搜索范围 lower_bound = 0.0 - upper_bound = max(sum(solar_output) + sum(wind_output) + sum(thermal_output), sum(load_demand)) + theoretical_max = max(sum(solar_output) + sum(wind_output) + sum(thermal_output), sum(load_demand)) + + # 应用储能容量上限限制 + if params.max_storage_capacity is not None: + upper_bound = min(theoretical_max, params.max_storage_capacity) + else: + upper_bound = theoretical_max # 二分搜索寻找最小储能容量 best_capacity = upper_bound best_result = None + solution_found = False # 标记是否找到可行解 for iteration in range(max_iterations): mid_capacity = (lower_bound + upper_bound) / 2 @@ -326,6 +336,7 @@ def optimize_storage_capacity( # 满足条件,尝试减小容量 best_capacity = mid_capacity best_result = {**balance_result, **constraint_results} + solution_found = True upper_bound = mid_capacity else: # 不满足条件,增大容量 @@ -335,8 +346,20 @@ def optimize_storage_capacity( if upper_bound - lower_bound < tolerance: break - # 如果没有找到可行解,使用最大容量 - if best_result is None: + # 处理储能容量上限限制的情况 + if not solution_found and params.max_storage_capacity is not None: + print(f"警告:在储能容量上限 {params.max_storage_capacity:.2f} MWh 内无法找到满足所有约束的解") + print("使用最大允许容量进行计算,但某些约束条件可能无法满足") + + # 使用最大允许容量计算结果 + balance_result = calculate_energy_balance( + solar_output, wind_output, thermal_output, load_demand, params, params.max_storage_capacity + ) + constraint_results = check_constraints(solar_output, wind_output, thermal_output, balance_result, params) + best_result = {**balance_result, **constraint_results} + best_capacity = params.max_storage_capacity + elif best_result is None: + # 如果没有找到可行解(且没有容量上限限制),使用最大容量 balance_result = calculate_energy_balance( solar_output, wind_output, thermal_output, load_demand, params, upper_bound ) @@ -380,7 +403,10 @@ def optimize_storage_capacity( 'total_curtailment_wind_ratio': best_result['total_curtailment_wind_ratio'], 'total_curtailment_solar_ratio': best_result['total_curtailment_solar_ratio'], 'total_grid_feed_in_ratio': best_result['total_grid_feed_in_ratio'], - 'energy_balance_check': energy_balance_check + 'energy_balance_check': energy_balance_check, + 'capacity_limit_reached': params.max_storage_capacity is not None and best_capacity >= params.max_storage_capacity, + 'theoretical_optimal_capacity': best_capacity if solution_found else None, + 'max_storage_limit': params.max_storage_capacity }