Files
rustytorch/demos/rtx-aeroflow-demo/src/sample_data.rs
T
2026-03-04 00:08:42 +00:00

400 lines
11 KiB
Rust

//! Sample data and configurations for AeroFlow demo.
use aeroflow_shared::{
naca_4digit, AnalysisType, FlowConditions, GeometryType, OperatorConfig, OperatorType,
OptimizationConfig, OptimizationObjective, SimulationRequest, TrainingConfig, WingGeometry,
};
// ============================================================================
// Airfoil Simulations
// ============================================================================
/// Create a NACA 0012 cruise simulation.
#[must_use]
pub fn naca0012_cruise() -> SimulationRequest {
let airfoil = naca_4digit("0012", 100).unwrap_or_default();
SimulationRequest {
geometry: GeometryType::Airfoil2D(airfoil),
conditions: FlowConditions {
velocity: 250.0, // m/s
angle_of_attack: 2.0,
mach: 0.73,
reynolds: 9_000_000.0,
..Default::default()
},
operator: OperatorConfig::default(),
analysis: AnalysisType::SinglePoint,
compute_flow_field: true,
export_results: false,
}
}
/// Create a NACA 2412 climb simulation.
#[must_use]
pub fn naca2412_climb() -> SimulationRequest {
let airfoil = naca_4digit("2412", 100).unwrap_or_default();
SimulationRequest {
geometry: GeometryType::Airfoil2D(airfoil),
conditions: FlowConditions {
velocity: 80.0, // m/s
angle_of_attack: 5.0,
mach: 0.23,
reynolds: 4_000_000.0,
..Default::default()
},
operator: OperatorConfig::default(),
analysis: AnalysisType::SinglePoint,
compute_flow_field: true,
export_results: false,
}
}
/// Create a NACA 4412 approach simulation.
#[must_use]
pub fn naca4412_approach() -> SimulationRequest {
let airfoil = naca_4digit("4412", 100).unwrap_or_default();
SimulationRequest {
geometry: GeometryType::Airfoil2D(airfoil),
conditions: FlowConditions {
velocity: 60.0, // m/s
angle_of_attack: 8.0,
mach: 0.17,
reynolds: 3_000_000.0,
..Default::default()
},
operator: OperatorConfig::default(),
analysis: AnalysisType::SinglePoint,
compute_flow_field: true,
export_results: false,
}
}
/// Create an alpha sweep request.
#[must_use]
pub fn alpha_sweep_request() -> SimulationRequest {
let airfoil = naca_4digit("0012", 100).unwrap_or_default();
SimulationRequest {
geometry: GeometryType::Airfoil2D(airfoil),
conditions: FlowConditions::default(),
operator: OperatorConfig::default(),
analysis: AnalysisType::AlphaSweep {
alpha_start: -5.0,
alpha_end: 15.0,
alpha_step: 1.0,
},
compute_flow_field: false,
export_results: false,
}
}
/// Create a Mach sweep request.
#[must_use]
pub fn mach_sweep_request() -> SimulationRequest {
let airfoil = naca_4digit("0012", 100).unwrap_or_default();
SimulationRequest {
geometry: GeometryType::Airfoil2D(airfoil),
conditions: FlowConditions {
angle_of_attack: 2.0,
..Default::default()
},
operator: OperatorConfig::default(),
analysis: AnalysisType::MachSweep {
mach_start: 0.2,
mach_end: 0.8,
mach_step: 0.1,
},
compute_flow_field: false,
export_results: false,
}
}
/// Create a polar generation request.
#[must_use]
pub fn polar_request() -> SimulationRequest {
let airfoil = naca_4digit("2412", 100).unwrap_or_default();
SimulationRequest {
geometry: GeometryType::Airfoil2D(airfoil),
conditions: FlowConditions::default(),
operator: OperatorConfig::default(),
analysis: AnalysisType::Polar {
cl_targets: vec![0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2],
},
compute_flow_field: false,
export_results: false,
}
}
// ============================================================================
// Wing Simulations
// ============================================================================
/// Create a simple wing simulation.
#[must_use]
pub fn simple_wing() -> SimulationRequest {
let root_airfoil = naca_4digit("2412", 50).unwrap_or_default();
let wing = WingGeometry {
root_airfoil,
tip_airfoil: None,
span: 10.0,
root_chord: 2.0,
tip_chord: 1.0,
sweep_angle: 0.0,
dihedral_angle: 5.0,
twist_angle: -3.0,
};
SimulationRequest {
geometry: GeometryType::Wing3D(wing),
conditions: FlowConditions {
velocity: 50.0,
angle_of_attack: 4.0,
mach: 0.15,
reynolds: 3_000_000.0,
..Default::default()
},
operator: OperatorConfig::default(),
analysis: AnalysisType::SinglePoint,
compute_flow_field: true,
export_results: false,
}
}
/// Create a swept wing simulation.
#[must_use]
pub fn swept_wing() -> SimulationRequest {
let root_airfoil = naca_4digit("0012", 50).unwrap_or_default();
let tip_airfoil = naca_4digit("0009", 50).unwrap_or_default();
let wing = WingGeometry {
root_airfoil,
tip_airfoil: Some(tip_airfoil),
span: 15.0,
root_chord: 4.0,
tip_chord: 1.5,
sweep_angle: 25.0,
dihedral_angle: 3.0,
twist_angle: -2.0,
};
SimulationRequest {
geometry: GeometryType::Wing3D(wing),
conditions: FlowConditions {
velocity: 200.0,
angle_of_attack: 3.0,
mach: 0.6,
reynolds: 15_000_000.0,
..Default::default()
},
operator: OperatorConfig::default(),
analysis: AnalysisType::SinglePoint,
compute_flow_field: true,
export_results: false,
}
}
// ============================================================================
// Operator Configurations
// ============================================================================
/// Create FNO configuration for high-fidelity simulations.
#[must_use]
pub fn high_fidelity_fno() -> OperatorConfig {
OperatorConfig {
operator_type: OperatorType::FNO,
num_modes: 24,
hidden_dim: 128,
num_layers: 6,
physics_informed: true,
grid_resolution: (256, 128),
activation: "gelu".to_string(),
}
}
/// Create FNO configuration for fast simulations.
#[must_use]
pub fn fast_fno() -> OperatorConfig {
OperatorConfig {
operator_type: OperatorType::FNO,
num_modes: 8,
hidden_dim: 32,
num_layers: 3,
physics_informed: false,
grid_resolution: (64, 32),
activation: "relu".to_string(),
}
}
/// Create DeepONet configuration.
#[must_use]
pub fn deeponet_config() -> OperatorConfig {
OperatorConfig {
operator_type: OperatorType::DeepONet,
num_modes: 16,
hidden_dim: 64,
num_layers: 4,
physics_informed: true,
grid_resolution: (128, 64),
activation: "tanh".to_string(),
}
}
/// Create PINO configuration.
#[must_use]
pub fn pino_config() -> OperatorConfig {
OperatorConfig {
operator_type: OperatorType::PINO,
num_modes: 16,
hidden_dim: 64,
num_layers: 5,
physics_informed: true,
grid_resolution: (128, 64),
activation: "gelu".to_string(),
}
}
// ============================================================================
// Optimization Configurations
// ============================================================================
/// Create drag minimization optimization config.
#[must_use]
pub fn min_drag_optimization() -> OptimizationConfig {
OptimizationConfig {
objective: OptimizationObjective::MinDragAtCl { target_cl: 0.5 },
max_iterations: 100,
tolerance: 1e-6,
population_size: 50,
learning_rate: 0.01,
..Default::default()
}
}
/// Create max L/D optimization config.
#[must_use]
pub fn max_ld_optimization() -> OptimizationConfig {
OptimizationConfig {
objective: OptimizationObjective::MaxLiftToDrag,
max_iterations: 200,
tolerance: 1e-7,
population_size: 100,
learning_rate: 0.005,
..Default::default()
}
}
// ============================================================================
// Training Configurations
// ============================================================================
/// Create quick training config.
#[must_use]
pub fn quick_training() -> TrainingConfig {
TrainingConfig {
epochs: 50,
batch_size: 16,
learning_rate: 1e-3,
physics_weight: 0.5,
data_weight: 1.0,
bc_weight: 5.0,
num_collocation_points: 5000,
curriculum: false,
}
}
/// Create full training config.
#[must_use]
pub fn full_training() -> TrainingConfig {
TrainingConfig {
epochs: 200,
batch_size: 32,
learning_rate: 5e-4,
physics_weight: 1.0,
data_weight: 1.0,
bc_weight: 10.0,
num_collocation_points: 20000,
curriculum: true,
}
}
// ============================================================================
// Tests
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_naca0012_cruise() {
let request = naca0012_cruise();
assert!(matches!(request.geometry, GeometryType::Airfoil2D(_)));
assert!((request.conditions.mach - 0.73).abs() < 0.01);
}
#[test]
fn test_alpha_sweep() {
let request = alpha_sweep_request();
if let AnalysisType::AlphaSweep {
alpha_start,
alpha_end,
alpha_step,
} = request.analysis
{
assert_eq!(alpha_start, -5.0);
assert_eq!(alpha_end, 15.0);
assert_eq!(alpha_step, 1.0);
} else {
panic!("Expected AlphaSweep analysis type");
}
}
#[test]
fn test_wing_simulations() {
let simple = simple_wing();
let swept = swept_wing();
assert!(matches!(simple.geometry, GeometryType::Wing3D(_)));
assert!(matches!(swept.geometry, GeometryType::Wing3D(_)));
}
#[test]
fn test_operator_configs() {
let high_fi = high_fidelity_fno();
let fast = fast_fno();
assert!(high_fi.num_modes > fast.num_modes);
assert!(high_fi.hidden_dim > fast.hidden_dim);
}
#[test]
fn test_optimization_configs() {
let min_drag = min_drag_optimization();
let max_ld = max_ld_optimization();
assert!(matches!(
min_drag.objective,
OptimizationObjective::MinDragAtCl { .. }
));
assert!(matches!(
max_ld.objective,
OptimizationObjective::MaxLiftToDrag
));
}
#[test]
fn test_training_configs() {
let quick = quick_training();
let full = full_training();
assert!(quick.epochs < full.epochs);
assert!(quick.num_collocation_points < full.num_collocation_points);
}
}