Skip to main content

FlutterPanel

Struct FlutterPanel 

Source
pub struct FlutterPanel { /* private fields */ }
Expand description

The planform numbers Martin’s criterion takes from one fin.

A birch-plywood fin with a 200 mm root, a 100 mm tip, a 120 mm span and 4 mm thick has A = 0.8, λ = 0.5 and t/c = 0.02, so K = 0.8³ / (0.02³ · 2.8) = 22 857. With plywood’s 750 MPa it flutters at q_f = π · 750 MPa / (6 · 22 857 · 1.5) = 11.45 kPa: 137 m/s in sea-level air.

use hpr_design::materials;
use hpr_sim::FlutterPanel;

let panel = FlutterPanel::new(0.8, 0.5, 0.02)?;
let g = materials::shear_modulus("birch_plywood").unwrap().shear_modulus_pa;
let q_f = panel.flutter_dynamic_pressure_pa(g)?;
let v_f = panel.flutter_speed_m_s(g, 101_325.0, 340.294)?;
assert!((q_f - 11_453.7).abs() < 0.1, "{q_f}");
assert!((v_f - 136.75).abs() < 0.01, "{v_f}");
// The same speed from q_f and sea-level density, 1.225 kg/m³.
assert!(((2.0 * q_f / 1.225).sqrt() - v_f).abs() < 0.01);

Its numbers are checked when it is made, by FlutterPanel::new, and when it is read from JSON.

Implementations§

Source§

impl FlutterPanel

Source

pub fn new( aspect_ratio: f64, taper_ratio: f64, thickness_ratio: f64, ) -> Result<Self, SimError>

A panel of aspect ratio A, taper ratio λ and thickness ratio t/c.

Martin’s figure 4 covers A from 0.5 to 3 and t/c from 1% to 10%; outside those the numbers are an extrapolation, which isn’t refused.

§Errors

SimError::Domain if A or t/c isn’t positive and finite, or λ isn’t within [0, 1], the range of Martin’s taper factors (NACA TN 4197, eqs. 8 and 14).

Source

pub fn of_fins(fins: &FinSet) -> Result<Self, SimError>

The panel of one of fins: A = 2s/(c_r + c_t), λ = c_t/c_r and t/c = t/c_r.

§Errors

SimError::Unsupported for an elliptical or freeform planform, or a tip chord longer than the root, which Martin’s taper factors don’t cover; SimError::Domain for a root chord that isn’t positive, or the panel’s numbers out of range, as FlutterPanel::new.

Source

pub fn aspect_ratio(&self) -> f64

The panel aspect ratio A: the span over the chord at mid-span.

Source

pub fn taper_ratio(&self) -> f64

The taper ratio λ: the tip chord over the root chord, from 0 (pointed) to 1.

Source

pub fn thickness_ratio(&self) -> f64

The thickness ratio t/c: the thickness over the root chord.

Source

pub fn shape_factor(&self) -> f64

K = A³ / ((t/c)³ (A + 2)): Martin’s X (eq. 19) without its constant.

Source

pub fn denominator_pa(&self, pressure_pa: f64) -> Result<f64, SimError>

The denominator of eq. 18 at static pressure p, Pa: D = (24 ε γ / π) p · K · (λ + 1)/2, the ordinate of Martin’s figure 3.

§Errors

SimError::Domain if p isn’t positive and finite.

Source

pub fn figure_3_ratio( &self, shear_modulus_pa: f64, pressure_pa: f64, ) -> Result<f64, SimError>

Martin’s figure 3 reading, D/G_E = (a/V_f)², at static pressure p: above FIGURE_3_BAND lie mostly his wings that fluttered, below it wings that didn’t. Martin takes p where the wing flies; at the launch site’s, the highest a flight sees, it is the largest. Outside his axis, G_E from 0.34 to 138 GPa, it is an extrapolation.

§Errors

SimError::Domain if G_E or p isn’t positive and finite.

Source

pub fn flutter_dynamic_pressure_pa( &self, shear_modulus_pa: f64, ) -> Result<f64, SimError>

The dynamic pressure at which a fin of effective shear modulus G_E reaches eq. 18’s flutter speed, Pa: q_f = π G_E / (24 ε K (λ + 1)), the same at every height.

§Errors

SimError::Domain if G_E isn’t positive and finite.

Source

pub fn flutter_speed_m_s( &self, shear_modulus_pa: f64, pressure_pa: f64, sound_speed_m_s: f64, ) -> Result<f64, SimError>

Eq. 18’s flutter speed in air of static pressure p and speed of sound a, m/s: V_f = a √(G_E / D).

§Errors

SimError::Domain if G_E, p or a isn’t positive and finite.

Source

pub fn margin( &self, shear_modulus_pa: f64, summary: &FlightSummary, ) -> Result<Option<FlutterMargin>, SimError>

The fin’s least ratio of eq. 18’s flutter speed to its airspeed over the flight summary describes, at its peak dynamic pressure; None if the rocket never flew.

The whole flight’s peak is used for every fin set on it. A booster’s fins leave at the separation, so the peak can come after they have gone; their true ratio is then at least the one given, as long as the booster’s own dynamic pressure after the separation stays below the flight’s peak, which hpr doesn’t check.

§Errors

As FlutterPanel::flutter_dynamic_pressure_pa; SimError::Domain if the peak dynamic pressure isn’t finite.

Trait Implementations§

Source§

impl Clone for FlutterPanel

Source§

fn clone(&self) -> FlutterPanel

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for FlutterPanel

Source§

impl Debug for FlutterPanel

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for FlutterPanel

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for FlutterPanel

Source§

fn eq(&self, other: &FlutterPanel) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for FlutterPanel

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for FlutterPanel

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.