From 269e985d836ec879ba89772dd63bd2a5d99fc840 Mon Sep 17 00:00:00 2001 From: dmy Date: Fri, 26 Dec 2025 02:28:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8F=AF=E7=94=A8=E7=94=B5?= =?UTF-8?q?=E9=87=8F=E8=AE=A1=E7=AE=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- excel_reader.py | 90 ++++++++++++++++++++++++++++++++++------- main.py | 58 +++++++++++++++++++++++--- storage_optimization.py | 82 +++++++++++++++++++++++++++---------- 3 files changed, 188 insertions(+), 42 deletions(-) diff --git a/excel_reader.py b/excel_reader.py index 8df9bde..c402d6f 100644 --- a/excel_reader.py +++ b/excel_reader.py @@ -101,16 +101,46 @@ def read_system_parameters(file_path: str) -> SystemParameters: except (ValueError, TypeError): raise ValueError(f"参数 '{param_name}' 的值 '{param_value}' 不是有效的数值") - # 创建SystemParameters对象 - return SystemParameters( - max_curtailment_wind=params_dict.get('最大弃风率', 0.1), - max_curtailment_solar=params_dict.get('最大弃光率', 0.1), - max_grid_ratio=params_dict.get('最大上网电量比例', 0.2), - storage_efficiency=params_dict.get('储能效率', 0.9), - discharge_rate=params_dict.get('放电倍率', 1.0), - charge_rate=params_dict.get('充电倍率', 1.0), - max_storage_capacity=params_dict.get('最大储能容量', None) - ) + # 读取各参数值,如果找不到则使用默认值 + get_param_value = lambda param_name: df_params.loc[df_params['参数名称'] == param_name, '参数值'].iloc[0] if param_name in df_params['参数名称'].values else None + + max_storage_capacity = get_param_value('最大储能容量') + # 处理空值或字符串"空" + if pd.isna(max_storage_capacity) or max_storage_capacity == '空': + max_storage_capacity = None + + try: + return SystemParameters( + max_curtailment_wind=get_param_value('最大弃风率') or 0.1, + max_curtailment_solar=get_param_value('最大弃光率') or 0.1, + max_grid_ratio=get_param_value('最大上网电量比例') or 0.2, + storage_efficiency=get_param_value('储能效率') or 0.9, + discharge_rate=get_param_value('放电倍率') or 1.0, + charge_rate=get_param_value('充电倍率') or 1.0, + max_storage_capacity=max_storage_capacity, + rated_thermal_capacity=get_param_value('额定火电装机容量') or 100.0, + rated_solar_capacity=get_param_value('额定光伏装机容量') or 100.0, + rated_wind_capacity=get_param_value('额定风电装机容量') or 100.0, + available_thermal_energy=get_param_value('火电可用发电量') or 2400.0, + available_solar_energy=get_param_value('光伏可用发电量') or 600.0, + available_wind_energy=get_param_value('风电可用发电量') or 1200.0 + ) + except (KeyError, IndexError, Exception) as e: + print(f"读取参数失败:{str(e)},使用默认参数") + return SystemParameters( + max_curtailment_wind=0.1, + max_curtailment_solar=0.1, + max_grid_ratio=0.2, + storage_efficiency=0.9, + discharge_rate=1.0, + charge_rate=1.0, + rated_thermal_capacity=100.0, + rated_solar_capacity=100.0, + rated_wind_capacity=100.0, + available_thermal_energy=2400.0, + available_solar_energy=600.0, + available_wind_energy=1200.0 + ) except Exception as e: print(f"读取参数工作表失败,使用默认参数:{str(e)}") @@ -261,7 +291,13 @@ def create_excel_template(file_path: str, data_type: str = "8760"): '储能效率', '放电倍率', '充电倍率', - '最大储能容量' + '最大储能容量', + '额定火电装机容量', + '额定光伏装机容量', + '额定风电装机容量', + '火电可用发电量', + '光伏可用发电量', + '风电可用发电量' ], '参数值': [ 0.1, # 最大弃风率 @@ -270,7 +306,13 @@ def create_excel_template(file_path: str, data_type: str = "8760"): 0.9, # 储能效率 1.0, # 放电倍率 1.0, # 充电倍率 - '' # 最大储能容量(空表示无限制) + '', # 最大储能容量(空表示无限制) + 100.0, # 额定火电装机容量 + 100.0, # 额定光伏装机容量 + 100.0, # 额定风电装机容量 + 2400.0, # 火电可用发电量 + 600.0, # 光伏可用发电量 + 1200.0 # 风电可用发电量 ], '参数说明': [ '允许的最大弃风率(0.0-1.0)', @@ -279,7 +321,13 @@ def create_excel_template(file_path: str, data_type: str = "8760"): '储能充放电效率(0.0-1.0)', '储能放电倍率(C-rate,>0)', '储能充电倍率(C-rate,>0)', - '储能容量上限(MWh,空表示无限制)' + '储能容量上限(MWh,空表示无限制)', + '额定火电装机容量(MW)', + '额定光伏装机容量(MW)', + '额定风电装机容量(MW)', + '火电可用发电量(MWh)', + '光伏可用发电量(MWh)', + '风电可用发电量(MWh)' ], '取值范围': [ '0.0-1.0', @@ -288,7 +336,13 @@ def create_excel_template(file_path: str, data_type: str = "8760"): '0.0-1.0', '>0', '>0', - '>0或空' + '>0或空', + '>0', + '>0', + '>0', + '≥0', + '≥0', + '≥0' ], '默认值': [ '0.1', @@ -297,7 +351,13 @@ def create_excel_template(file_path: str, data_type: str = "8760"): '0.9', '1.0', '1.0', - '无限制' + '无限制', + '100.0', + '100.0', + '100.0', + '2400.0', + '600.0', + '1200.0' ] }) parameters_df.to_excel(writer, sheet_name='参数', index=False) diff --git a/main.py b/main.py index 861198c..79718dd 100644 --- a/main.py +++ b/main.py @@ -287,7 +287,13 @@ def export_results_to_excel(solar_output, wind_output, thermal_output, load_dema '储能效率', '放电倍率', '充电倍率', - '最大储能容量' + '最大储能容量', + '额定火电装机容量', + '额定光伏装机容量', + '额定风电装机容量', + '火电可用发电量', + '光伏可用发电量', + '风电可用发电量' ], '参数值': [ params.max_curtailment_wind, @@ -296,7 +302,13 @@ def export_results_to_excel(solar_output, wind_output, thermal_output, load_dema params.storage_efficiency, params.discharge_rate, params.charge_rate, - params.max_storage_capacity if params.max_storage_capacity is not None else "无限制" + params.max_storage_capacity if params.max_storage_capacity is not None else "无限制", + params.rated_thermal_capacity, + params.rated_solar_capacity, + params.rated_wind_capacity, + params.available_thermal_energy, + params.available_solar_energy, + params.available_wind_energy ], '单位': [ "比例", @@ -305,6 +317,12 @@ def export_results_to_excel(solar_output, wind_output, thermal_output, load_dema "效率", "C-rate", "C-rate", + "MWh", + "MW", + "MW", + "MW", + "MWh", + "MWh", "MWh" ] }) @@ -427,6 +445,12 @@ def main(): print(f" 放电倍率: {params.discharge_rate}") print(f" 充电倍率: {params.charge_rate}") print(f" 最大储能容量: {params.max_storage_capacity}") + print(f" 额定火电装机容量: {params.rated_thermal_capacity} MW") + print(f" 额定光伏装机容量: {params.rated_solar_capacity} MW") + print(f" 额定风电装机容量: {params.rated_wind_capacity} MW") + print(f" 火电可用发电量: {params.available_thermal_energy} MWh") + print(f" 光伏可用发电量: {params.available_solar_energy} MWh") + print(f" 风电可用发电量: {params.available_wind_energy} MWh") else: print("\n警告:未找到系统参数,使用默认参数") params = SystemParameters( @@ -435,7 +459,13 @@ def main(): max_grid_ratio=0.2, storage_efficiency=0.9, discharge_rate=1.0, - charge_rate=1.0 + charge_rate=1.0, + rated_thermal_capacity=100.0, + rated_solar_capacity=100.0, + rated_wind_capacity=100.0, + available_thermal_energy=2400.0, + available_solar_energy=600.0, + available_wind_energy=1200.0 ) # 显示数据统计 @@ -474,7 +504,13 @@ def main(): max_grid_ratio=0.2, storage_efficiency=0.9, discharge_rate=1.0, - charge_rate=1.0 + charge_rate=1.0, + rated_thermal_capacity=100.0, + rated_solar_capacity=100.0, + rated_wind_capacity=100.0, + available_thermal_energy=2400.0, + available_solar_energy=600.0, + available_wind_energy=1200.0 ) # 对于 --yearly 参数,也需要设置默认参数 @@ -485,7 +521,13 @@ def main(): max_grid_ratio=0.2, storage_efficiency=0.9, discharge_rate=1.0, - charge_rate=1.0 + charge_rate=1.0, + rated_thermal_capacity=100.0, + rated_solar_capacity=100.0, + rated_wind_capacity=100.0, + available_thermal_energy=2400.0, + available_solar_energy=600.0, + available_wind_energy=1200.0 ) # 显示当前使用的系统参数 @@ -497,6 +539,12 @@ def main(): print(f"放电倍率: {params.discharge_rate}") print(f"充电倍率: {params.charge_rate}") print(f"最大储能容量: {params.max_storage_capacity if params.max_storage_capacity is not None else '无限制'}") + print(f"额定火电装机容量: {params.rated_thermal_capacity} MW") + print(f"额定光伏装机容量: {params.rated_solar_capacity} MW") + print(f"额定风电装机容量: {params.rated_wind_capacity} MW") + print(f"火电可用发电量: {params.available_thermal_energy} MWh") + print(f"光伏可用发电量: {params.available_solar_energy} MWh") + print(f"风电可用发电量: {params.available_wind_energy} MWh") print("=" * 40) # 计算最优储能容量 diff --git a/storage_optimization.py b/storage_optimization.py index d0f6899..7dde301 100644 --- a/storage_optimization.py +++ b/storage_optimization.py @@ -23,6 +23,14 @@ class SystemParameters: discharge_rate: float = 1.0 # 储能放电倍率 (C-rate) charge_rate: float = 1.0 # 储能充电倍率 (C-rate) max_storage_capacity: Optional[float] = None # 储能容量上限 (MWh),None表示无限制 + # 新增额定装机容量参数 + rated_thermal_capacity: float = 100.0 # 额定火电装机容量 (MW) + rated_solar_capacity: float = 100.0 # 额定光伏装机容量 (MW) + rated_wind_capacity: float = 100.0 # 额定风电装机容量 (MW) + # 新增可用发电量参数 + available_thermal_energy: float = 2400.0 # 火电可用发电量 (MWh) + available_solar_energy: float = 600.0 # 光伏可用发电量 (MWh) + available_wind_energy: float = 1200.0 # 风电可用发电量 (MWh) def validate_inputs( @@ -79,6 +87,20 @@ def validate_inputs( raise ValueError("充放电倍率必须大于0") if params.max_storage_capacity is not None and params.max_storage_capacity <= 0: raise ValueError("储能容量上限必须大于0") + # 验证新增的额定装机容量参数 + if params.rated_thermal_capacity <= 0: + raise ValueError("额定火电装机容量必须大于0") + if params.rated_solar_capacity <= 0: + raise ValueError("额定光伏装机容量必须大于0") + if params.rated_wind_capacity <= 0: + raise ValueError("额定风电装机容量必须大于0") + # 验证新增的可用发电量参数 + if params.available_thermal_energy < 0: + raise ValueError("火电可用发电量必须为非负值") + if params.available_solar_energy < 0: + raise ValueError("光伏可用发电量必须为非负值") + if params.available_wind_energy < 0: + raise ValueError("风电可用发电量必须为非负值") def calculate_energy_balance( @@ -130,6 +152,13 @@ def calculate_energy_balance( accumulated_curtailed_wind = 0.0 accumulated_curtailed_solar = 0.0 + # 计算总可用发电量上限(不考虑火电) + total_available_energy = params.available_solar_energy + params.available_wind_energy + max_total_grid_feed_in = total_available_energy * params.max_grid_ratio + + # 初始化累计上网电量 + cumulative_grid_feed_in = 0.0 + # 逐小时计算 for hour in range(hours): # 确保储能状态不为负 @@ -145,7 +174,7 @@ def calculate_energy_balance( power_surplus = available_generation - demand if power_surplus > 0: - # 有盈余电力,优先储能,然后上网 + # 有盈余电力,优先储能 max_charge = min( storage_capacity - storage_soc[hour], # 储能空间限制 storage_capacity * params.charge_rate, # 充电功率限制 @@ -160,36 +189,45 @@ def calculate_energy_balance( if hour < hours - 1: storage_soc[hour + 1] = storage_soc[hour] + actual_charge * params.storage_efficiency - # 剩余电力考虑弃风弃光和上网 + # 剩余电力优先上网,超出上网电量比例限制时才弃风弃光 remaining_surplus = power_surplus - actual_charge - # 计算弃风弃光(优先弃风,然后弃光) + # 计算当前允许的最大上网电量 + # 基于总可用发电量和已累计上网电量 + remaining_grid_quota = max_total_grid_feed_in - cumulative_grid_feed_in + + # 优先上网,但不超过剩余配额 + grid_feed_allowed = min(remaining_surplus, max(0, remaining_grid_quota)) + grid_feed_in[hour] = grid_feed_allowed + cumulative_grid_feed_in += grid_feed_allowed + + # 剩余电力考虑弃风弃光 + remaining_surplus -= grid_feed_allowed + + # 计算弃风弃光(优先弃光,然后弃风) if remaining_surplus > 0: - # 计算当前可弃风量 - available_wind_curtail = min( - wind[hour], - max_curtailed_wind_total - accumulated_curtailed_wind + # 计算当前可弃光量 + available_solar_curtail = min( + solar[hour], + max_curtailed_solar_total - accumulated_curtailed_solar ) - 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] + 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: - available_solar_curtail = min( - solar[hour], - max_curtailed_solar_total - accumulated_curtailed_solar + available_wind_curtail = min( + wind[hour], + max_curtailed_wind_total - accumulated_curtailed_wind ) - 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] - - # 最终剩余电力上网 - grid_feed_in[hour] = max(0, remaining_surplus) + 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] else: # 电力不足,优先放电