TowerChain平台开发日志
- 模型文件的修正以及初始计算文件的获得
针对定制化项目,在选定机型之后,机组成本主要的区分点在于风资源的不同。风力发电机组在不同的风资源下的气动特性存在一定的差异性,其中,空气密度是影响较大的几个因素之一。
- 空气密度提取
风资源提供的定制化风电场风资源数据时应按照标准模板生成,其中首页Site Condition第7列应为各机位点空气密度,项目空气密度取其中最大值进行计算。
风资源文件需要进行格式筛查,检查是否存在留空以及分组信息缺失。
如果流程中包含自动格式筛查(),则风文件不需要手动对上述信息进行处理。
空气密度模块同时应提供标准开发接口,即提供含有空气密度的txt文件。
风资源文件将自动被平台分配至计算目录下的WindFile文件夹,文件夹下未检索到风资源文件时或风文件数量异常时,应报错,并终止程序。
# Function 空气密度信息提取 # Done
def get_airdensity(root_dir):
wind_dir = os.path.join(root_dir, 'WindFile')
windfile_dir = get_typefile(wind_dir, '.xlsx')
isxlsx = 1
if not windfile_dir:
windfile_dir = get_typefile(wind_dir, 'txt')
isxlsx = 0
if len(windfile_dir) > 1:
logging(root_dir, ' ERROR : 风文件过多!')
raise Exception('风文件过多!')
elif not windfile_dir:
logging(root_dir, ' ERROR : 没有风文件数据!')
raise Exception('没有风文件数据')
if isxlsx:
wind = xlrd.open_workbook(windfile_dir[0])
site_condition = wind.sheet_by_name('Site Condition')
airdensity = site_condition.col_values(6)
airdensity = [i for i in airdensity if isinstance(i, float)]
else:
with open(windfile_dir[0], 'r') as wind:
lines = wind.readlines()
airdensity = float(lines[0])
return max(airdensity)
- 初始IN文件生成
风力发电机组的仿真通常利用Bladed(@DNV GL)进行。TowerChain平台使用版本为 Bladed 4.6。Bladed的标准模型文件格式为*.prj(后文称为prj文件),计算模型文件格式为*.$PJ(后文称为PJ文件), 标准计算文件格式为*.IN(后文称为IN文件)。三种文件数据存储格式均为xml格式,记录机组模型数据及相关仿真设置。关于文件的详细格式与相关含义,将在后面的文章中详细说明,这里仅讲解计算前的准备工作。
通常传递的机组模型为prj或PJ文件。由于平台需要进行大量的后台计算,因此需要将得到的prj或PJ文件转化成求解器可以直接调用的IN文件。关于Bladed的求解器将同计算文件的格式一同说明。当前,在选择机组模型时,上传的模型文件应统一为prj文件。
prj文件需要经过格式筛查,主要检查模型是否存在模块缺失。此外,由于后期需要迭代机组塔架模型,如果机组模态信息固定则会导致计算出错,应选择在仿真开始时依据模型自行计算模态信息。因此要求上传的prj文件中不得包含机组模态信息,处理方式为使用文本格式打开prj文件后,手动删除如下字段:
0RMODE
以及
MSTART RMODE
...
...
MEND
如果流程中包含自动格式筛查(),则prj文件不需要手动对上述信息进行处理
在生成IN文件之前应使用获得的空气密度修正模型
在生成IN文件之前,prj文件中所引用的绝对路径,如计算目录及控制器路径,应进行修正。
prj文件生成IN文件使用bat命令调用Bladed_m72.exe求解器执行
@echo off
cd %~dp0
setlocal EnableDelayedExpansion
for /f "delims=" %%i in ('"dir /aa/s/b/on *.prj"') do (
set file=%%~fi
set file=!file:/=/!
)
set apath=%~dp0
"D:\Program Files (x86)\DNV GL\Bladed 4.6\Bladed_m72.exe" -Prj !file! -RunDir !apath! -ResultPath !apath!
prj文件将自动被平台分配至计算目录下的Model文件夹,文件夹下未检索到模型文件时或模型文件数量异常时,应报错,并终止程序。
# Function 基础in文件生成 # Done
# 修正空气密度 #
# 修改控制器路径 #
def gen_originalin(root_dir):
global logfile
model_dir = os.path.join(root_dir, 'Model')
project_dir = get_typefile(model_dir, '.prj')
if not project_dir:
logging(root_dir, ' ERROR : 未找到模型文件!')
raise Exception('未找到模型文件')
control_dir = os.path.join(root_dir, 'Exctrl')
dll_file_path = get_typefile(control_dir, '.dll')
xml_file_path = get_typefile(control_dir, '.xml')
change_xml(project_dir[0], 'ExternalController', 'Filepath', dll_file_path[0])
change_xml(project_dir[0], 'ExternalController', 'AdditionalParameters', 'READ ' + xml_file_path[0])
change_info(project_dir[0], 'CALCULATION', '2')
run_bat(root_dir, 'Model')
in_dir = get_typefile(model_dir, '.in')[0]
eigen_b = catch_block(in_dir, 'EIGENB')
eigen_b.append('\n')
eigen_t = catch_block(in_dir, 'EIGENT')
eigen_t.append('\n')
change_info(project_dir[0], 'CALCULATION', '10')
add_info(project_dir[0], '0RMASS', '0RMODE')
change_block(project_dir[0], 'CONSTANTS', 'RHO', str(get_airdensity(root_dir)))
run_bat(root_dir, 'Model')
add_block(in_dir, 'RCON', eigen_b)
add_block(in_dir, 'RCON', eigen_t)
logging(root_dir, ' 初始in文件生成成功')
print('初始in文件生成成功')
return
- 功率系数与最小桨距角
风力发电机组的功率系数是表征机组发电性能的主要因素,机组在不同桨距角下叶尖速比与功率系数的曲线不同,通常我们取功率系数最大时的桨距角作为最优桨距角,并记录对应的叶尖速比,用于下节的Kopt计算。通常我们会让机组的叶片一直保持在最优桨距角,以保证发电性能,直到风速上升至机组需要变桨(收桨,即桨距角增大)降载,因此最优桨距角通常也称作最小桨距角。
依据叶片设计,通常我们寻找最优桨距角,需要从-2度到2度,以0.5度为一个间隔建立工作点分别进行计算(Bladed 4.4及以前版本),平台采用的Bladed 4.6版本将多个计算整合成单个计算,可以只设置起止点及步长即可得到结果,简化了计算步骤。
功率系数的计算在Bladed中的内部编号CALCN为5,主要参数模块为
MSTART PCOEFF
...
PITCH -0.03490660
PITCH_END 0.03490660
PITCH_STEP 0.00872665
...
MEND
主要设置参数为桨距角起点(PITCH),终点(PITCH_END)以及步长(PITCH_STEP)。
功率系数的计算路径将自动分配至当前目录下的Performance文件夹,计算使用的IN文件为从Model文件夹中复制的上步中生成的初始IN文件。
功率系数的计算使用bat命令调用dtblade.exe求解器执行。
需要注意的地方是,功率系数计算需要将计算选项OPTN设置为0。
功率系数计算后,主要的计算结果存储在*.%37文件中。
# subFunction Cp计算in文件生成并执行计算 # Done
# 修正桨距角为-2至2度,步长0.5度 #
def gen_performance(root_dir):
global logfile
gen_originalin(root_dir)
ori_in_dir = os.path.join(root_dir, 'Model')
ori_in_file_path = get_typefile(ori_in_dir, '.in')
current_in_dir = os.path.join(root_dir, 'Performance')
current_in_file_path = ori_in_file_path[0].replace(ori_in_dir, current_in_dir)
shutil.copyfile(ori_in_file_path[0], current_in_file_path)
change_info(current_in_file_path, 'CALCN', '5')
change_info(current_in_file_path, 'PATH', current_in_dir)
change_info(current_in_file_path, 'RUNNAME', 'pcoeffs')
change_info(current_in_file_path, 'OPTNS', '0')
change_block(current_in_file_path, 'PCOEFF', 'PITCH', '-0.03490660')
change_block(current_in_file_path, 'PCOEFF', 'PITCH_END', '0.03490660')
change_block(current_in_file_path, 'PCOEFF', 'PITCH_STEP', '0.00872665')
print('开始计算最小桨距角')
run_bat(root_dir, 'Performance')
logging(root_dir, ' 最小桨距角计算完成')
print('最小桨距角计算完成')
return
- 最优增益计算
风力发电机组的最优增益通常用于扭矩控制环节,即机组满发前,的扭矩设定值计算,使得机组一直保持在最优的功率系数附近运转,保证机组能够最大出力,发电性能最优。
最优增益通常使用符号Kopt进行代指。相同机型的情况下,Kopt通常与空气密度直接相关,计算公式如下:
Kopt = π* ρ * R^5 * Cpmax / (2 * λ^3)
其中ρ为提取的空气密度,R为机组叶轮半径,Cpmax为上步中计算得出最优功率系数,λ为最优功率系数对应的叶尖速比。
为了计算Kopt,需要从上步中生成的*.%37中提取最优的功率系数,以及对应的最小桨距角以及叶尖速比(其中最优桨距角为生成模板IN文件时使用)。
# subFunction 提取最优Cp及对应的叶尖速比与最小桨距角 # Done
def get_cpinfo(root_dir):
cpinfo = []
cp_path = os.path.join(root_dir, 'Performance')
data_path = get_typefile(cp_path, '.%37')
with open(data_path[0], 'r') as msg:
lines = msg.readlines()
for j in range(len(lines)):
if 'ULOADS' in lines[j]:
cpinfo.append(do_split(lines[j], ' ', 1)) # 提取Cp
cpinfo.append(do_split(lines[j], ' ', 2)) # 提取λ
elif 'MAXTIME'in lines[j]:
cpinfo.append(do_split(lines[j], ' ', 1)) # 提取最小桨距角
return cpinfo
除了从功率系数结果文件中提取的数据外,机组的叶轮半径需要从prj文件中读取叶轮直径(DIAM)数据除二后使用。需要注意的是,提取的数据均为字符串形式,需要转换成浮点数后方可使用。
# subFunction Kopt计算 # Done
def get_optmodegain(root_dir):
global logfile
cpinfo = get_cpinfo(root_dir)
cp_max = float(cpinfo[0].strip())
lamda = float(cpinfo[1].strip())
model_dir = os.path.join(root_dir, 'Model')
project_dir = get_typefile(model_dir, '.prj')
radius = 0.5 * get_block(project_dir[0], 'RCON', 'DIAM')
pho = get_airdensity(root_dir)
k_opt = math.pi * pho * math.pow(radius, 5) * cp_max / (2 * math.pow(lamda, 3))
logging(root_dir, ' Kopt计算完成')
print('Kopt计算完成')
return int(k_opt)
- 生成模板IN文件
在依据项目风参,得到基本的风机参数后,应对初始的IN文件进行修正,得到的IN文件将作为标准的IN文件模板向后面的计算传递。后续的线性化计算以及载荷计算都将以该文件作为模板进行对应的修正。
在从初始IN文件生成模板IN文件时,主要进行修正的模块为CONTROL。
MSTART CONTROL
...
GAIN_TSR 1365796
...
PITMIN 0
...
MEND
主要进行修正的参数为最优增益(GAIN_TSR)与最小桨距角(PITMIN)。
# Function 模板In文件生成 # Done
# 修改最小桨距角及Kopt #
# 不执行计算 #
def gen_standard(root_dir):
global logfile
gen_performance(root_dir)
ori_in_dir = os.path.join(root_dir, 'Model')
ori_in_file_path = get_typefile(ori_in_dir, '.in')
change_block(ori_in_file_path[0], 'CONTROL', 'GAIN_TSR', str(get_optmodegain(root_dir)))
change_block(ori_in_file_path[0], 'CONTROL', 'PITMIN', get_cpinfo(root_dir)[2])
logging(root_dir, ' 修正in文件完成')
print('修正in文件完成')
return
到这里为止,计算的准备工作就完成了,然后就可以对机组进行线性化计算,从而得到机组的线性化模型,进行控制器整定。
那么在下一篇文章,就会详细的介绍如何实现机组的线性化,じゃね~