204 lines
7.6 KiB
Python
204 lines
7.6 KiB
Python
|
import pandas as pd
|
|||
|
import math
|
|||
|
from scipy.optimize import fsolve
|
|||
|
import os
|
|||
|
import sys
|
|||
|
|
|||
|
# 获取当前文件的绝对路径
|
|||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|||
|
print(current_dir)
|
|||
|
# 添加当前目录到sys.path
|
|||
|
sys.path.append(current_dir)
|
|||
|
|
|||
|
def wind_farm_analysis(device_name, area_km2, electricity_price, file_path, velocity_avg, T_avg,
|
|||
|
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_avg (float): 全年平均风速
|
|||
|
T_path (str): 全年平均温度
|
|||
|
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]
|
|||
|
swept_area = match.iloc[0, 7] # 扫风面积
|
|||
|
blade_diameter = match.iloc[0, 6] # 叶片直径
|
|||
|
print(f"找到设备 '{device_name}',额定功率: {rated_power} kW, "
|
|||
|
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 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, velocity_avg):
|
|||
|
rho_v3 = densities * velocity_avg
|
|||
|
return 0.5 * rho_v3
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
def calculate_environmental_benefits(E_p_million_kwh):
|
|||
|
"""计算环境收益"""
|
|||
|
if E_p_million_kwh < 0:
|
|||
|
raise ValueError("年发电量需≥0")
|
|||
|
return {
|
|||
|
"coal_reduction": E_p_million_kwh * 0.404 * 10,
|
|||
|
"CO2_reduction": E_p_million_kwh * 0.977 * 10,
|
|||
|
"SO2_reduction": E_p_million_kwh * 0.03 * 10,
|
|||
|
"NOX_reduction": E_p_million_kwh * 0.015 * 10
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
# 获取设备信息
|
|||
|
rated_power, swept_area, blade_diameter = get_wind_turbine_specs(device_name, file_path)
|
|||
|
|
|||
|
# 估算风机数量
|
|||
|
num_turbines = estimate_wind_turbine_count(area_km2, blade_diameter)
|
|||
|
|
|||
|
# 读取温度数据并计算空气密度
|
|||
|
avg_density = air_density(altitude, hub_height, T_avg)
|
|||
|
|
|||
|
# 计算风功率密度
|
|||
|
wpd = wind_power_density(avg_density, velocity_avg)
|
|||
|
|
|||
|
# 计算装机容量
|
|||
|
total_power = estimated_wind_power(num_turbines, rated_power)
|
|||
|
|
|||
|
# 计算初始投资成本
|
|||
|
IC = total_power * cost_per_mw * 1000000
|
|||
|
|
|||
|
# 计算年发电量 kwh
|
|||
|
P_test = calculate_power_output(swept_area, wpd, Cp, eta) * num_turbines
|
|||
|
|
|||
|
# 计算等效小时数
|
|||
|
h = calculate_equivalent_hours(P_test, rated_power)
|
|||
|
|
|||
|
# 计算 IRR
|
|||
|
P_test_IRR = P_test/1000
|
|||
|
irr = calculate_reference_yield(P_test_IRR, electricity_price, IC, q)
|
|||
|
|
|||
|
env_benefits = calculate_environmental_benefits((P_test / 10000000))
|
|||
|
|
|||
|
# 返回结果
|
|||
|
out = {
|
|||
|
"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
|
|||
|
}
|
|||
|
out.update(env_benefits)
|
|||
|
return out
|
|||
|
|
|||
|
# 主程序
|
|||
|
if __name__ == "__main__":
|
|||
|
file_path = f"{current_dir}/wind_product.xlsx"
|
|||
|
v_avg = 4.2
|
|||
|
tavg = 15
|
|||
|
|
|||
|
device_name = "GW165-5.2"
|
|||
|
area_km2 = 23.2
|
|||
|
electricity_price = 0.45
|
|||
|
|
|||
|
result = wind_farm_analysis(
|
|||
|
device_name=device_name,
|
|||
|
area_km2=area_km2,
|
|||
|
electricity_price=electricity_price,
|
|||
|
file_path=file_path,
|
|||
|
velocity_avg=v_avg,
|
|||
|
T_avg=tavg
|
|||
|
)
|
|||
|
print(result)
|
|||
|
"""
|
|||
|
{
|
|||
|
"code": 200,
|
|||
|
"data": {
|
|||
|
"device": "GW165-5.2",
|
|||
|
"rated_power": 5.2,
|
|||
|
"swept_area": 21382,
|
|||
|
"blade_diameter": 165,
|
|||
|
"num_turbines": 23,
|
|||
|
"avg_density": 1.2118668826686871,
|
|||
|
"wpd": 1.9995803564033336,
|
|||
|
"total_power": 119.60000000000001,
|
|||
|
"annual_power_output": 310.11418354861905,
|
|||
|
"equivalent_hours": 596.3734299011904,
|
|||
|
"IRR": 9.985793133871693,
|
|||
|
"coal_reduction": 12528.61301536421,
|
|||
|
"CO2_reduction": 30298.155732700077,
|
|||
|
"SO2_reduction": 930.342550645857,
|
|||
|
"NOX_reduction": 465.1712753229285
|
|||
|
}
|
|||
|
}
|
|||
|
"""
|