use std::time::Instant;
use stormath::type_aliases::Float;
use stormath::consts::TAU;
use crate::lifting_line::prelude::*;
use crate::lifting_line::simulation_builder::{
SimulationBuilder,
SimulationSettings,
QuasiSteadySettings,
DynamicSettings,
};
use crate::line_force_model::corrections::circulation::{
CirculationCorrectionBuilder,
prescribed::PrescribedCirculation
};
use super::test_setup::RectangularWing;
use super::elliptic_wing_theory::EllipticWingTheory;
#[test]
fn steady_lift() {
let aspect_ratio = 5.0;
let cl_zero_angle = 1.2;
let angle_of_attack = Float::from(2.0).to_radians();
let theory = EllipticWingTheory {
cl_2d: cl_zero_angle + TAU * angle_of_attack,
aspect_ratio
};
let cl_theory = theory.cl();
let cd_theory = theory.cd();
let wing_builder = RectangularWing {
aspect_ratio,
cl_zero_angle,
angle_of_attack,
nr_strips: 64,
..Default::default()
}.build();
let mut prescribed_wing_builder = wing_builder.clone();
let mut prescribed_circulation = PrescribedCirculation::default();
prescribed_circulation.curve_fit_shape_parameters = true;
prescribed_wing_builder.circulation_correction = CirculationCorrectionBuilder::Prescribed(
prescribed_circulation
);
let steady_settings = QuasiSteadySettings::default();
let dynamic_settings = DynamicSettings::default();
let nr_time_steps = 200;
let velocity = SpatialVector::from([1.2, 0.0, 0.0]);
let time_step = 0.25 / velocity.length();
let mut steady_sim = SimulationBuilder::new(
wing_builder.clone(),
SimulationSettings::QuasiSteady(steady_settings.clone())
).build();
let mut prescribed_sim = SimulationBuilder::new(
prescribed_wing_builder.clone(),
SimulationSettings::QuasiSteady(steady_settings)
).build();
let mut dynamic_sim = SimulationBuilder::new(
wing_builder.clone(),
SimulationSettings::Dynamic(dynamic_settings)
).build();
let force_factor = steady_sim.line_force_model.total_force_factor(velocity.length());
let dynamic_velocity_points = dynamic_sim.get_freestream_velocity_points();
let static_velocity_points = steady_sim.get_freestream_velocity_points();
let dynamic_velocity_freestream: Vec<SpatialVector> = vec![velocity; dynamic_velocity_points.len()];
let static_velocity_freestream: Vec<SpatialVector> = vec![velocity; static_velocity_points.len()];
let start = Instant::now();
let result_steady = steady_sim.do_step(
0.0,
time_step,
&static_velocity_freestream
);
println!("Time to run steady simulation: {} secs", start.elapsed().as_secs_f64());
println!("Number of steady iterations: {}", result_steady.iterations);
println!("Residual for steady simulation: {}", result_steady.residual);
let cd_steady = result_steady.integrated_forces_sum()[0] / force_factor;
let cl_steady = result_steady.integrated_forces_sum()[1] / force_factor;
let start = Instant::now();
let result_prescribed = prescribed_sim.do_step(
0.0,
time_step,
&static_velocity_freestream
);
println!("Time to run prescribed simulation: {} secs", start.elapsed().as_secs_f64());
println!("Number of prescribed iterations: {}", result_prescribed.iterations);
println!("Residual for prescribed simulation: {}", result_prescribed.residual);
let cd_prescribed = result_prescribed.integrated_forces_sum()[0] / force_factor;
let cl_prescribed = result_prescribed.integrated_forces_sum()[1] / force_factor;
let mut cd_dynamic = 0.0;
let mut cl_dynamic = 0.0;
let mut result_dynamic = SimulationResult::default();
let start = Instant::now();
for i in 0..nr_time_steps {
let time = (i as Float) * time_step;
result_dynamic = dynamic_sim.do_step(
time,
time_step,
&dynamic_velocity_freestream
);
cd_dynamic = result_dynamic.integrated_forces_sum()[0] / force_factor;
cl_dynamic = result_dynamic.integrated_forces_sum()[1] / force_factor;
}
println!("Time to run dynamic simulation: {} secs", start.elapsed().as_secs_f64());
println!("Number of dynamic iterations on last time step: {}", result_dynamic.iterations);
println!("Residual for dynamic simulation: {}", result_dynamic.residual);
println!("Theory");
dbg!(cd_theory, cl_theory);
println!("Steady");
dbg!(cd_steady, cl_steady);
println!("Prescribed");
dbg!(cd_prescribed, cl_prescribed);
println!("Dynamic");
dbg!(cd_dynamic, cl_dynamic);
let steady_cl_error = (cl_theory - cl_steady).abs() / cl_theory.abs();
let steady_cd_error = (cd_theory - cd_steady).abs() / cd_theory.abs();
let prescribed_cl_error = (cl_theory - cl_prescribed).abs() / cl_theory.abs();
let prescribed_cd_error = (cd_theory - cd_prescribed).abs() / cd_theory.abs();
let dynamic_cl_error = (cl_theory - cl_dynamic).abs() / cl_theory.abs();
let dynamic_cd_error = (cd_theory - cd_dynamic).abs() / cd_theory.abs();
let allowable_cd_error = 0.06;
let allowable_cl_error = 0.07;
assert!(steady_cl_error < allowable_cl_error, "Steady cl error: {}", steady_cl_error);
assert!(steady_cd_error < allowable_cd_error, "Steady cd error: {}", steady_cd_error);
assert!(prescribed_cl_error < allowable_cl_error, "Prescribed cl error: {}", prescribed_cl_error);
assert!(prescribed_cd_error < allowable_cd_error, "Prescribed cd error: {}", prescribed_cd_error);
assert!(dynamic_cl_error < allowable_cl_error, "Dynamic cl error: {}", dynamic_cl_error);
assert!(dynamic_cd_error < allowable_cd_error, "Dynamic cd error: {}", dynamic_cd_error);
}