From e0ca8398ad82a2a8a164cc0d33a759046335a21e Mon Sep 17 00:00:00 2001 From: liujia Date: Thu, 27 Mar 2025 13:51:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20Wind?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Wind/temperature.txt | 12 +++ Wind/wind_product.xlsx | Bin 0 -> 12965 bytes Wind/wind_speed.txt | 12 +++ Wind/wind_total.py | 192 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 216 insertions(+) create mode 100644 Wind/temperature.txt create mode 100644 Wind/wind_product.xlsx create mode 100644 Wind/wind_speed.txt create mode 100644 Wind/wind_total.py diff --git a/Wind/temperature.txt b/Wind/temperature.txt new file mode 100644 index 0000000..62e82ed --- /dev/null +++ b/Wind/temperature.txt @@ -0,0 +1,12 @@ +10 +12 +15 +18 +20 +22 +25 +24 +20 +15 +12 +10 \ No newline at end of file diff --git a/Wind/wind_product.xlsx b/Wind/wind_product.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5d5b94bb1b7ef1a0ec196411f65652aa495b7744 GIT binary patch literal 12965 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 literal 0 HcmV?d00001 diff --git a/Wind/wind_speed.txt b/Wind/wind_speed.txt new file mode 100644 index 0000000..3370b0f --- /dev/null +++ b/Wind/wind_speed.txt @@ -0,0 +1,12 @@ +3.5 +4.0 +4.2 +3.8 +5.0 +5.5 +6.0 +5.8 +5.2 +4.5 +4.0 +3.7 \ No newline at end of file diff --git a/Wind/wind_total.py b/Wind/wind_total.py new file mode 100644 index 0000000..4e3c087 --- /dev/null +++ b/Wind/wind_total.py @@ -0,0 +1,192 @@ +import pandas as pd +import math +from scipy.optimize import fsolve + +def wind_farm_analysis(device_name, area_km2, electricity_price, file_path, velocity_path, T_path, + lateral_spacing_factor=5, longitudinal_spacing_factor=10, q=0.02, altitude=11, + hub_height=100, Cp=0.45, eta=0.8, cost_per_mw=5000): + """ + 封装函数:分析风电场的风机数量及各项经济和技术指标 + + 参数: + device_name (str): 设备名称 + area_km2 (float): 风电场面积(平方公里) + electricity_price (float): 电价(元/kWh) + file_path (str): 风机参数 Excel 文件路径 + velocity_path (str): 风速数据文件路径(12 个月平均风速) + T_path (str): 温度数据文件路径(12 个月平均温度) + lateral_spacing_factor (float): 横向间距因子(默认为 5D) + longitudinal_spacing_factor (float): 纵向间距因子(默认为 10D) + q (float): 运维成本占初始投资成本的比例(默认 0.02 表示 2%) + altitude (float): 海拔高度(m),默认 11m + hub_height (float): 轮毂高度(m),默认 100m + Cp (float): 风能利用系数,默认 0.45 + eta (float): 总系统效率,默认 0.8 + cost_per_mw (float): 每 MW 投资成本(万元/MW),默认 5000 万元/MW + + 返回: + dict: 包含风电场分析结果的字典 + """ + def estimate_wind_turbine_count(area_km2, blade_diameter): + area_m2 = area_km2 * 1_000_000 + lateral_spacing = lateral_spacing_factor * blade_diameter + longitudinal_spacing = longitudinal_spacing_factor * blade_diameter + turbine_area = lateral_spacing * longitudinal_spacing + turbine_count = int(area_m2 / turbine_area) + print(f"单台风机占地面积: {turbine_area:,} 平方米 " + f"(横向间距: {lateral_spacing} 米, 纵向间距: {longitudinal_spacing} 米)") + print(f"估算风机数量: {turbine_count} 台") + return turbine_count + + def get_wind_turbine_specs(device_name, file_path): + try: + df = pd.read_excel(file_path) + match = df[df.iloc[:, 0] == device_name] + if not match.empty: + rated_power = match.iloc[0, 1] / 1000 # kW 转换为 MW + swept_area = match.iloc[0, 7] # 扫风面积 + blade_diameter = match.iloc[0, 6] # 叶片直径 + print(f"找到设备 '{device_name}',额定功率: {rated_power} MW, " + f"扫风面积: {swept_area} m², 叶片直径: {blade_diameter} 米") + return rated_power, swept_area, blade_diameter + else: + raise ValueError(f"未找到设备名称: {device_name}") + except FileNotFoundError: + raise FileNotFoundError(f"文件未找到: {file_path}") + except Exception as e: + raise Exception(f"发生错误: {str(e)}") + + def read_monthly_temperatures(file_path): + try: + with open(file_path, 'r', encoding='utf-8') as file: + temperatures = [float(line.strip()) for line in file.readlines()] + if len(temperatures) != 12: + raise ValueError(f"温度文件应包含 12 个月的数据,但实际有 {len(temperatures)} 条") + return temperatures + except Exception as e: + raise Exception(f"读取温度文件时出错: {str(e)}") + + def air_density(altitude, hub_height, T0): + z = altitude + hub_height + LR = 0.0065 + T = T0 - LR * z + 273.15 + return (353.05 / T) * math.exp(-0.034 * (z / T)) + + def wind_power_density(densities, file_path): + try: + with open(file_path, 'r', encoding='utf-8') as file: + wind_speeds = [float(line.strip()) for line in file.readlines()] + if len(wind_speeds) != 12: + raise ValueError(f"风速文件应包含 12 个月的数据,但实际有 {len(wind_speeds)} 条") + sum_rho_v3 = sum(rho * (v ** 3) for rho, v in zip(densities, wind_speeds)) + return (1 / (2 * 12)) * sum_rho_v3 + except Exception as e: + raise Exception(f"读取风速文件时出错: {str(e)}") + + def estimated_wind_power(num_turbines, rated_power): + if not isinstance(num_turbines, int) or num_turbines < 0: + raise ValueError("风机数量必须为非负整数") + return rated_power * num_turbines + + def calculate_power_output(S, w, Cp, eta): + return w * S * Cp * 8760 * eta + + def calculate_equivalent_hours(P, P_r): + if P_r == 0: + raise ValueError("额定功率不能为 0") + return (P / 1000) / (P_r * 1000) + + def calculate_reference_yield(E_p, electricity_price, IC, q, n=20): + def npv_equation(irr, p, w, ic, q_val, n=n): + term1 = (1 + irr) ** (-1) + term2 = irr * (1 + irr) ** (-1) if irr != 0 else float('inf') + pv_revenue = p * w * (term1 / term2) * (1 - (1 + irr) ** (-n)) + pv_salvage = q_val * ic * (term1 / term2) * (1 - (1 + irr) ** (-n)) + return pv_revenue - ic + pv_salvage + + irr_guess = 0.1 + irr = float(fsolve(npv_equation, irr_guess, args=(E_p, electricity_price, IC, q))[0]) + if not 0 <= irr <= 1: + raise ValueError(f"IRR计算结果{irr:.4f}不合理") + return irr * 100 + + try: + # 获取设备信息 + rated_power, swept_area, blade_diameter = get_wind_turbine_specs(device_name, file_path) + + # 估算风机数量 + num_turbines = estimate_wind_turbine_count(area_km2, blade_diameter) + + # 读取温度数据并计算空气密度 + monthly_temps = read_monthly_temperatures(T_path) + densities = [air_density(altitude, hub_height, T0) for T0 in monthly_temps] + avg_density = sum(densities) / len(densities) + + # 计算风功率密度 + wpd = wind_power_density(densities, velocity_path) + + # 计算装机容量 + total_power = estimated_wind_power(num_turbines, rated_power) + + # 计算初始投资成本 + IC = total_power * cost_per_mw * 1000000 + + # 计算年发电量 + P_test = calculate_power_output(swept_area, wpd, Cp, eta) * num_turbines + + # 计算等效小时数 + h = calculate_equivalent_hours(P_test, rated_power) + + # 计算 IRR + irr = calculate_reference_yield(P_test, electricity_price, IC, q) + + # 返回结果 + return { + "device": device_name, + "rated_power": rated_power, + "swept_area": swept_area, + "blade_diameter": blade_diameter, + "num_turbines": num_turbines, + "avg_density": avg_density, + "wpd": wpd, + "total_power": total_power, + "annual_power_output": P_test / 10000000, # 万 kWh + "equivalent_hours": h, + "IRR": irr + } + except Exception as e: + raise Exception(f"风电场分析出错: {str(e)}") + +# 主程序 +if __name__ == "__main__": + file_path = r".\wind_product.xlsx" + velocity_path = r".\wind_speed.txt" + T_path = r".\temperature.txt" + + device_name = input("请输入设备名称: ") + area_km2 = float(input("请输入风电场面积(平方公里): ")) + electricity_price = float(input("请输入电价(元/kWh): ")) + + try: + result = wind_farm_analysis( + device_name=device_name, + area_km2=area_km2, + electricity_price=electricity_price, + file_path=file_path, + velocity_path=velocity_path, + T_path=T_path + ) + + print(f"\n设备: {result['device']}") + print(f"额定功率: {result['rated_power']:.2f} MW") + print(f"扫风面积: {result['swept_area']:.2f} m^2") + print(f"叶片直径: {result['blade_diameter']:.2f} m") + print(f"风机数量: {result['num_turbines']} 台") + print(f"平均空气密度: {result['avg_density']:.3f} kg/m^3") + print(f"风功率密度: {result['wpd']:.2f} W/m^2") + print(f"项目装机容量: {result['total_power']:.2f} MW") + print(f"年发电量: {result['annual_power_output']:.3f} 万 kWh") + print(f"等效小时数: {result['equivalent_hours']:.2f} 小时") + print(f"内部收益率 IRR: {result['IRR']:.2f}%") + except Exception as e: + print(f"错误: {str(e)}") \ No newline at end of file