use crate::line_force_model::LineForceModel;
use stormath::spatial_vector::SpatialVector;
use stormath::type_aliases::Float;
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
pub enum CoordinateSystem {
#[default]
Global,
Body,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct IntegratedValues {
pub circulatory: SpatialVector,
pub viscous_lift: SpatialVector,
pub sectional_drag: SpatialVector,
pub added_mass: SpatialVector,
pub gyroscopic: SpatialVector,
pub total: SpatialVector,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct SectionalForcesInput {
pub circulation_strength: Vec<Float>,
pub velocity: Vec<SpatialVector>,
pub angles_of_attack: Vec<Float>,
pub acceleration: Vec<SpatialVector>,
pub rotation_velocity: SpatialVector,
pub coordinate_system: CoordinateSystem,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct SectionalForces {
pub circulatory: Vec<SpatialVector>,
pub viscous_lift: Vec<SpatialVector>,
pub sectional_drag: Vec<SpatialVector>,
pub added_mass: Vec<SpatialVector>,
pub gyroscopic: Vec<SpatialVector>,
pub total: Vec<SpatialVector>,
pub coordinate_system: CoordinateSystem,
}
impl SectionalForces {
pub fn compute_total(&mut self) {
self.total = self.circulatory.clone();
for i in 0..self.total.len() {
self.total[i] += self.viscous_lift[i];
self.total[i] += self.sectional_drag[i];
self.total[i] += self.added_mass[i];
self.total[i] += self.gyroscopic[i];
}
}
pub fn sectional_moments(
line_force_model: &LineForceModel,
sectional_forces: &[SpatialVector],
coordinate_system: CoordinateSystem
) -> Vec<SpatialVector> {
let span_lines = match coordinate_system {
CoordinateSystem::Global => &line_force_model.span_lines_global,
CoordinateSystem::Body => &line_force_model.span_lines_local,
};
(0..span_lines.len()).map(
|index| {
span_lines[index].ctrl_point().cross(sectional_forces[index])
}
).collect()
}
pub fn integrate_forces(&self, line_force_model: &LineForceModel) -> Vec<IntegratedValues> {
let mut integrated_values: Vec<IntegratedValues> = Vec::new();
for wing_indices in &line_force_model.wing_indices {
let mut wing_result = IntegratedValues::default();
for i in wing_indices.start..wing_indices.end {
if !line_force_model.line_segment_is_virtual[i] {
wing_result.circulatory += self.circulatory[i];
wing_result.viscous_lift += self.viscous_lift[i];
wing_result.sectional_drag += self.sectional_drag[i];
wing_result.added_mass += self.added_mass[i];
wing_result.gyroscopic += self.gyroscopic[i];
wing_result.total += self.total[i];
}
}
integrated_values.push(wing_result);
}
integrated_values
}
pub fn integrate_moments(&self, line_force_model: &LineForceModel) -> Vec<IntegratedValues> {
let sectional_circulatory_moments = Self::sectional_moments(line_force_model, &self.circulatory, self.coordinate_system);
let sectional_viscous_lift_moments = Self::sectional_moments(line_force_model, &self.viscous_lift, self.coordinate_system);
let sectional_drag_moments = Self::sectional_moments(line_force_model, &self.sectional_drag, self.coordinate_system);
let sectional_added_mass_moments = Self::sectional_moments(line_force_model, &self.added_mass, self.coordinate_system);
let sectional_gyroscopic_moments = Self::sectional_moments(line_force_model, &self.gyroscopic, self.coordinate_system);
let sectional_total_moments = Self::sectional_moments(line_force_model, &self.total, self.coordinate_system);
let mut integrated_values: Vec<IntegratedValues> = Vec::new();
for wing_indices in &line_force_model.wing_indices {
let mut wing_result = IntegratedValues::default();
for i in wing_indices.start..wing_indices.end {
if !line_force_model.line_segment_is_virtual[i] {
wing_result.circulatory += sectional_circulatory_moments[i];
wing_result.viscous_lift += sectional_viscous_lift_moments[i];
wing_result.sectional_drag += sectional_drag_moments[i];
wing_result.added_mass += sectional_added_mass_moments[i];
wing_result.gyroscopic += sectional_gyroscopic_moments[i];
wing_result.total += sectional_total_moments[i];
}
}
integrated_values.push(wing_result);
}
integrated_values
}
}