2025-12-23 17:09:38 +08:00
|
|
|
|
|
|
|
|
|
|
[TOC]
|
|
|
|
|
|
<div style="page-break-after: always;"></div>
|
|
|
|
|
|
|
|
|
|
|
|
# 0. 更新日志
|
|
|
|
|
|
|
|
|
|
|
|
2024 v0.4版本,介绍耦合求解器基本框架,包含时间推进方法,多体动力学模块与气动、水动模块耦合方法。
|
|
|
|
|
|
2025 v0.6版本,耦合求解器新增公共lib模块,yaml解析模块,控制模块,时间推进过程中增加向控制模块输入参数,控制器返回指令,指令结果向多体动力学模块传递。对照Bladed新增变桨二阶传递函数、电机转矩一阶传递函数。新增Steady Operational Loads, Steady Parked Loads两个稳态工作流,新增Normal Stop, Emergency Stop, Start, Idling, Parked五个Simulation功能。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 1. 耦合求解器简介
|
|
|
|
|
|
正常发电工况需要进行气动模块、多体模块、控制模块、漂浮式机组还有水动模块的耦合计算,耦合求解器模块处理在瞬态仿真中所有模块的时间推进,以及在时间推进中模块间的数据传递。
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 耦合求解器程序介绍
|
|
|
|
|
|
## 2.1. 耦合求解器程序结构
|
|
|
|
|
|
```
|
|
|
|
|
|
herolib/ # 公共lib模块
|
|
|
|
|
|
aerodyn/ # 气动模块
|
|
|
|
|
|
controller/ # 控制模块
|
|
|
|
|
|
hydrosim/ # 水动模块
|
|
|
|
|
|
multidyn/ # 多体动力学模块
|
|
|
|
|
|
yaml_herowind # yaml配置文件、模型文件解析模块
|
|
|
|
|
|
drivers/ # 耦合求解器模块
|
|
|
|
|
|
├── coupled_solver_sub.rs # 耦合求解器所用子函数
|
|
|
|
|
|
├── steady_operational_loads.rs # 稳态运行载荷计算函数
|
|
|
|
|
|
├── steady_parked_loads.rs # 稳态停机载荷计算函数
|
|
|
|
|
|
├── power_production_loading.rs # 正常发电工况计算函数
|
|
|
|
|
|
├── normal_stop.rs # 正常停机工况计算函数
|
|
|
|
|
|
├── emergency_stop.rs # 紧急停机工况计算函数
|
|
|
|
|
|
├── start.rs # 启机工况计算函数
|
|
|
|
|
|
├── idling.rs # 空转工况计算函数
|
|
|
|
|
|
├── parked.rs # 停机工况计算函数
|
|
|
|
|
|
└── main.rs # 耦合求解器模块主程序
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
耦合求解器作为一个完整的rust项目,气动、水动、多体动力学、控制模块作为库引入,耦合求解器模块作为主程序,在耦合求解器控制的初始化、时间推进、数据传递中,调用气动、水动、多体模块函数。
|
|
|
|
|
|
|
|
|
|
|
|
## 2.2. 主要子模块的功能介绍
|
|
|
|
|
|
|
2025-12-24 17:07:57 +08:00
|
|
|
|
### 2.2.1 yaml_herowind模块
|
|
|
|
|
|
`yaml_herowind`模块专门用来解析yaml格式配置文件及模型文件。
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
yaml_herowind/ # 耦合求解器模块
|
|
|
|
|
|
├── calc_config.rs # yaml配置文件对应结构体
|
|
|
|
|
|
├── lib.rs # 封装解析功能函数
|
|
|
|
|
|
└── turbine_model.rs # yaml模型文件对应结构体
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.2.1.1 calc_config.rs
|
|
|
|
|
|
在配置文件中,定义当前计算求解器选择,来流条件,气动模型选择,机组初始条件,控制模块输入参数等,在`calc_config.rs`中对上述参数单独创建结构体,实现从配置文件到软件结构体的解析。部分结构体展示如下。
|
|
|
|
|
|
|
|
|
|
|
|
`InitialConditions`结构体定义了风电机组初始状态,包括初始桨距角,初始转速,初始叶片、塔架位移,漂浮式风电机组初始浮式平台位移、角度等。
|
|
|
|
|
|
``` rust
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
pub struct InitialConditions {
|
|
|
|
|
|
pub out_of_plane_def: f64,
|
|
|
|
|
|
pub in_plane_def: f64,
|
|
|
|
|
|
pub blade_1_pitch_degs: f64,
|
|
|
|
|
|
pub blade_2_pitch_degs: f64,
|
|
|
|
|
|
pub blade_3_pitch_degs: f64,
|
|
|
|
|
|
pub azimuth_degs: f64,
|
|
|
|
|
|
pub rotor_speed_rpm: f64,
|
|
|
|
|
|
pub nacelle_yaw_degs: f64,
|
|
|
|
|
|
pub tower_top_fore_aft_disp: f64,
|
|
|
|
|
|
pub tower_top_side_to_side_disp: f64,
|
|
|
|
|
|
pub ptfm_surge_disp: f64,
|
|
|
|
|
|
pub ptfm_sway_disp: f64,
|
|
|
|
|
|
pub ptfm_heave_disp: f64,
|
|
|
|
|
|
pub ptfm_roll_degs: f64,
|
|
|
|
|
|
pub ptfm_pitch_degs: f64,
|
|
|
|
|
|
pub ptfm_yaw_degs: f64,
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`ADGeneralOptions`结构体定义了湍流发展模型,尾流模型等。
|
|
|
|
|
|
``` rust
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
|
pub struct ADGeneralOptions {
|
|
|
|
|
|
pub echo: bool, // Echo (flag)
|
|
|
|
|
|
pub dt_aero: MaybeDefault<f64>, // DTAero (s or "default")
|
|
|
|
|
|
pub wakemod: i32, // WakeMod (switch)
|
|
|
|
|
|
pub afaeromod: i32, // AFAeroMod (switch)
|
|
|
|
|
|
pub twrpotent: i32, // TwrPotent (switch)
|
|
|
|
|
|
pub twrshadow: i32, // TwrShadow (switch)
|
|
|
|
|
|
pub twraero: bool, // TwrAero (flag)
|
|
|
|
|
|
pub frozen_wake: bool, // FrozenWake (flag)
|
|
|
|
|
|
pub cavit_check: bool, // CavitCheck (flag)
|
|
|
|
|
|
pub buoyancy: bool, // Buoyancy (flag)
|
|
|
|
|
|
pub comp_aa: bool, // CompAA (flag)
|
|
|
|
|
|
pub aa_input_file: String, // AA_InputFile (string)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`InflowConfigSection`结构体定义了来流风的类型,此处可选稳态风、阵风、湍流风等。
|
|
|
|
|
|
``` rust
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
|
pub struct InflowConfigSection {
|
|
|
|
|
|
pub echo: bool,
|
|
|
|
|
|
pub wind_type: i32,
|
|
|
|
|
|
pub propagation_dir: f64,
|
|
|
|
|
|
pub vflow_ang: f64,
|
|
|
|
|
|
pub vel_interp_cubic: bool,
|
|
|
|
|
|
pub n_wind_vel: usize,
|
|
|
|
|
|
pub wind_vxi_list: Vec<f64>,
|
|
|
|
|
|
pub wind_vyi_list: Vec<f64>,
|
|
|
|
|
|
pub wind_vzi_list: Vec<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`ControllerInput`结构体定义了控制器模块的输入参数,包括dll文件路径,discon.in文件路径,dll文件是32位还是64位,以及一些桨距、转矩等必要参数。
|
|
|
|
|
|
```rust
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
|
pub struct ControllerInput {
|
|
|
|
|
|
pub dll_path: String, // dll文件路径
|
|
|
|
|
|
pub acc_infile: String, // discon.in文件路径
|
|
|
|
|
|
pub dll_bit: i32,
|
|
|
|
|
|
pub pitch_min: f64, // 最小桨距角: 0度
|
|
|
|
|
|
pub pitch_max: f64, // 最大桨距角: 90度
|
|
|
|
|
|
pub pitch_rate_min: f64, // 最小收桨速率 单位:弧度/秒
|
|
|
|
|
|
pub pitch_rate_max: f64,
|
|
|
|
|
|
pub pitch_actuator_type: i32, // 变桨控制方式 0:位置 1:速率
|
|
|
|
|
|
pub gen_power_dem: f64, // 风机发电功率需求 单位:W
|
|
|
|
|
|
pub gen_speed_dem: f64, // 风机发电转速需求 单位:rpm
|
|
|
|
|
|
pub gen_torque_dem: f64, // 风机发电转矩需求 单位:N·m
|
|
|
|
|
|
pub gain_optimal: f64, // 最优模型增益
|
|
|
|
|
|
pub gen_speed_min: f64, // 切入转速 单位:rpm
|
|
|
|
|
|
pub gen_speed_max: f64, // 最优追踪最大转速 单位:rpm
|
|
|
|
|
|
pub pitch_control: i32, // 变桨响应方式 0:同步 1:独立
|
|
|
|
|
|
pub yaw_control: i32, // 偏航控制方式 0:速率 1:转矩
|
|
|
|
|
|
pub gen_speed: f64, //
|
|
|
|
|
|
pub generator_efficiency: f64, // 发电机效率
|
|
|
|
|
|
pub freq_pitch_actuator: f64,
|
|
|
|
|
|
pub damping_factor_pitch_actuator: f64,
|
|
|
|
|
|
pub tau_torque_demand: f64,
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`Task`结构体定义了求解器选择,当前从main.rs作为入口可选择5种稳态求解器,6种瞬态求解器,`Task`结构体定义了本配置文件计算类型及对应计算的配置参数。
|
|
|
|
|
|
```rust
|
|
|
|
|
|
// Task 结构体,包含自定义反序列化逻辑
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
|
pub struct Task {
|
|
|
|
|
|
pub task_type: TaskType,
|
|
|
|
|
|
pub actived: bool,
|
|
|
|
|
|
pub params: TaskParams,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone, PartialEq)]
|
|
|
|
|
|
#[serde(rename_all = "PascalCase")] // 匹配 "Aerodynamic Information" 等
|
|
|
|
|
|
pub enum TaskType {
|
|
|
|
|
|
#[serde(rename = "Aerodynamic Information")]
|
|
|
|
|
|
AerodynamicInformation,
|
|
|
|
|
|
#[serde(rename = "Performance Coefficients")]
|
|
|
|
|
|
PerformanceCoefficients,
|
|
|
|
|
|
#[serde(rename = "Steady Power Curve")]
|
|
|
|
|
|
SteadyPowerCurve,
|
|
|
|
|
|
#[serde(rename = "Steady Operational Loads")]
|
|
|
|
|
|
SteadyOperationalLoads,
|
|
|
|
|
|
#[serde(rename = "Steady Parked Loads")]
|
|
|
|
|
|
SteadyParkedLoads,
|
|
|
|
|
|
#[serde(rename = "Power Production Loading")]
|
|
|
|
|
|
PowerProductionLoading,
|
|
|
|
|
|
Start,
|
|
|
|
|
|
#[serde(rename = "Emergency Stop")]
|
|
|
|
|
|
EmergencyStop,
|
|
|
|
|
|
#[serde(rename = "Normal Stop")]
|
|
|
|
|
|
NormalStop,
|
|
|
|
|
|
Idling,
|
|
|
|
|
|
Parked,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
|
pub enum TaskParams {
|
|
|
|
|
|
AerodynamicInformation { data: AerodynamicInformationParams },
|
|
|
|
|
|
PerformanceCoefficients { data: PerformanceCoefficientsParams },
|
|
|
|
|
|
SteadyPowerCurve { data: SteadyPowerCurveParams },
|
|
|
|
|
|
SteadyOperationalLoads { data: SteadyOperationalLoadsParams },
|
|
|
|
|
|
SteadyParkedLoads { data: SteadyParkedLoadsParams },
|
|
|
|
|
|
PowerProductionLoading { data: SimulationControlParams },
|
|
|
|
|
|
Start { data: SimulationControlParams },
|
|
|
|
|
|
EmergencyStop { data: StopSimulationParams },
|
|
|
|
|
|
NormalStop { data: StopSimulationParams },
|
|
|
|
|
|
Idling { data: SimulationControlParams },
|
|
|
|
|
|
Parked { data: SimulationControlParams },
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
|
pub struct AerodynamicInformationParams {
|
|
|
|
|
|
pub wind_speed: f64,
|
|
|
|
|
|
pub pitch: f64,
|
|
|
|
|
|
pub omega: f64,
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`ForSaveConfig`结构体定义了dlc计算中此配置文件对应的dlc工况名,以及结果保存路径。计算过程中会在`save_path`保存计算结果,并且输出的结果文件会用`dlc_name`来命名。
|
|
|
|
|
|
```rust
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
|
pub struct ForSaveConfig {
|
|
|
|
|
|
pub dlc_name: String,
|
|
|
|
|
|
pub save_path: String,
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.2.1.2 turbine_model.rs
|
|
|
|
|
|
|
|
|
|
|
|
`turbine_model`基于WindIO定义风电机组模型主要参数,包括叶片、翼型、轮毂、机舱、塔架等。
|
|
|
|
|
|
|
|
|
|
|
|
`Components`结构体集中包含叶片、轮毂等部件,每个部件又有自己对应的结构体类型,如叶片结构体包含外形、弹性参数定义结构体,轮毂部件包含外形、弹性参数结构体,共同定义了轮毂的尺寸,预锥角,质量和惯性等参数。
|
|
|
|
|
|
```rust
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
pub struct Components {
|
|
|
|
|
|
pub blade: Blade,
|
|
|
|
|
|
pub hub: Hub,
|
|
|
|
|
|
pub nacelle: Nacelle,
|
|
|
|
|
|
pub tower: Tower,
|
|
|
|
|
|
pub floating_platform: FloatingPlatform,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
pub struct Blade {
|
|
|
|
|
|
pub outer_shape_bem: OuterShapeBEMBlade,
|
|
|
|
|
|
pub elastic_properties_mb: ElasticPropertiesMBBlade,
|
|
|
|
|
|
pub elastodyn_blade: ElastodynBlade,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
pub struct Hub {
|
|
|
|
|
|
pub outer_shape_bem: OuterShapeBEMHub,
|
|
|
|
|
|
pub elastic_properties_mb: ElasticPropertiesMBHub,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
pub struct OuterShapeBEMHub {
|
|
|
|
|
|
pub root_length: f64,
|
|
|
|
|
|
pub pre_cone_1_deg: f64,
|
|
|
|
|
|
pub pre_cone_2_deg: f64,
|
|
|
|
|
|
pub pre_cone_3_deg: f64,
|
|
|
|
|
|
pub drag_coefficient: f64,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
pub struct ElasticPropertiesMBHub {
|
|
|
|
|
|
pub hub_mass: f64,
|
|
|
|
|
|
pub hub_inertia: f64,
|
|
|
|
|
|
pub hub_center_mass: f64,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.2.1.3 lib.rs
|
|
|
|
|
|
|
|
|
|
|
|
`lib.rs`引用`calc_config.rs`和`turbine_model.rs`,使用`serde_yaml`包实现yaml文件的一行代码解析,同时封装出`parse_model`和`parse_calc_config`两个函数供main函数使用,两个函数成果解析文件,会返回`turbine_model`和`calc_config`两个包含完整配置参数的结构体,供main函数后续使用。`lib.rs`代码较少,完整展示如下。
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
mod turbine_model;
|
|
|
|
|
|
pub mod calc_config;
|
|
|
|
|
|
use serde_yaml;
|
|
|
|
|
|
use std::fs;
|
|
|
|
|
|
pub use turbine_model::TurbineModel;
|
|
|
|
|
|
pub use calc_config::CalcConfigrations;
|
|
|
|
|
|
|
|
|
|
|
|
pub fn parse_model(file: &str) -> TurbineModel {
|
|
|
|
|
|
let file_content =
|
|
|
|
|
|
fs::read_to_string(file).expect("Failed to read YAML file");
|
|
|
|
|
|
|
|
|
|
|
|
match serde_yaml::from_str::<TurbineModel>(&file_content) {
|
|
|
|
|
|
Ok(turbine_model) => turbine_model,
|
|
|
|
|
|
Err(e) => panic!("Error parsing YAML: {}", e),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn parse_calc_config(file: &str) -> CalcConfigrations {
|
|
|
|
|
|
let file_content =
|
|
|
|
|
|
fs::read_to_string(file).expect("Failed to read YAML file");
|
|
|
|
|
|
|
|
|
|
|
|
match serde_yaml::from_str::<CalcConfigrations>(&file_content) {
|
|
|
|
|
|
Ok(calc_config) => calc_config,
|
|
|
|
|
|
Err(e) => panic!("Error parsing YAML: {}", e),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-12-23 17:09:38 +08:00
|
|
|
|
### 2.2.1. main.rs
|
|
|
|
|
|
|
|
|
|
|
|
- `main`:耦合求解器主函数,执行气动、水动、多体模块数据结构体的初始化,模块初始化,时间迭代过程。
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2.2. coupled_solver_sub.rs
|
|
|
|
|
|
|
|
|
|
|
|
- `fast_init`:初始化函数,按照参与模块初始化,包括气动模块、水动模块、多体模块的初始化。
|
|
|
|
|
|
- `fast_solution_0`:耦合求解器t0时刻计算。
|
|
|
|
|
|
- `calc_outputs_and_solve_for_inputs`:计算多模块的输出,模块间交互数据。
|
|
|
|
|
|
- `solve_option_2a_inp2_bd`:多体模块执行计算,气动模块接收多体计算数据。
|
|
|
|
|
|
- `solve_option_2`:气动模块计算,多体模块接收气动计算数据。
|
|
|
|
|
|
- `fast_solution_t`:耦合求解器时间推进计算。
|
|
|
|
|
|
- `fast_extrap_interp_mods`:多体动力学模块输入外推。
|
|
|
|
|
|
- `fast_advance_states`:多体动力学模块状态推进,使用四阶Adams-Bashforth-Moulton预估矫正方法。
|
|
|
|
|
|
- `transfer_platform_motion_to_hd`:多体动力学模块输出平台运动传递给水动模块。
|
|
|
|
|
|
- `transfer_hd_forces_moments_to_ed`:水动模块输出力和力矩传递给多体动力学模块。
|
|
|
|
|
|
- `calc_ed_hd_residual`:计算多体与水动模块传递结果残差。
|
|
|
|
|
|
|
|
|
|
|
|
## 2.3. 耦合求解器流程图
|
|
|
|
|
|
<figure style="text-align: center;">
|
|
|
|
|
|
<img src="pics/耦合求解器流程图.png" alt="图片描述">
|
|
|
|
|
|
<figcaption style="text-align: center;">图1: 耦合求解器流程图</figcaption>
|
|
|
|
|
|
</figure>
|
|
|
|
|
|
|
|
|
|
|
|
耦合求解器在时间推进计算中,首先初始化气动、水动、多体模块,然后进行t0时刻计算,之后进行时间推进计算。t0时刻,调用`calc_outputs_and_solve_for_inputs`函数,多体动力学模块根据输入参数计算该时刻各自由度响应,如果是多体与气动耦合,多体将响应传递给气动模块,如叶片节点的变形量,变形速度等,气动模块接收响应,执行自身模块计算,计算完成后将叶片节点上的力和力矩回传给多体动力学模块。如果是多体模块和水动模块联合,为了计算稳定性,在传递中需要额外加入雅可比矩阵计算,结合残差函数`calc_ed_hd_residual`计算得到的delta_u,计算从新的delta_u给多体动力学模块赋值。
|
|
|
|
|
|
|
|
|
|
|
|
时间推进过程中多体动力学模块需要调用`fast_extrap_interp_mods`函数将输入外推至下一时刻,然后调用`fast_advance_states`函数进行状态推进,推进过程中需要使用四阶龙格库塔方法或Adams-Bashforth-Moulton预估矫正方法。推进完成后调用`calc_outputs_and_solve_for_inputs`函数,计算流程与t0时刻相同。持续开展时间迭代,直到达到仿真结束时间步,计算结束。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 2.4 steady operational loads
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 2.5 Steady parked loads
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 2.6 Simulations
|
|
|
|
|
|
|