pub struct AeroModel { /* private fields */ }Expand description
A rocket’s aerodynamic model: normal force, center of pressure and drag.
Serialize-only, for inspection: a model is built from a Layout by AeroModel::new, which
checks what it builds.
Implementations§
Source§impl AeroModel
impl AeroModel
Sourcepub fn new(layout: &Layout) -> Result<Self, AeroError>
pub fn new(layout: &Layout) -> Result<Self, AeroError>
Builds the terms of every component of layout, with hpr’s current body model
(BodyModel::default).
§Errors
Sourcepub fn with_body_model(
layout: &Layout,
body_model: BodyModel,
) -> Result<Self, AeroError>
pub fn with_body_model( layout: &Layout, body_model: BodyModel, ) -> Result<Self, AeroError>
Builds the terms of every component of layout, its bodies’ lift and supersonic boattails
by body_model.
§Errors
AeroError::Domainfor a non-positive reference diameter, rocket length or body radius.AeroError::InComponentnaming the component, around:AeroError::Unsupportedfor tube fins the ring-wing model doesn’t take (fewer than three, solid, shorter than a third of their diameter, overlapping, or on a pod), canted fins on a pod, a pod’s tube of no length with a radius (a flat disc), or a part kind or fin cross-section this model doesn’t know (a nose shape the drag buildup has no data for builds, and the buildup refuses it when asked:AeroModel::drag);AeroError::Domainfor a fin set of more than eight fins, a non-finite station, a pod’s body with no fineness, or a drag input out of range (a negative fin thickness, a launch lug’s wall thicker than its radius, a rail button’s base and flange taller than the button, a negative roughness);AeroError::Layoutfor a fin set or tube fin set without the radius of its body tube, or a pod’s body component listed before its pod set;- design errors from a profile, a planform, a volume integral or a pod set’s placements.
AeroError::Unsupportedfor motor mounts in more thanMOTOR_POD_SETSpod sets, whose thrusting areasDragConditionscan’t tell apart.AeroError::Domainfor a body-liftKthat isn’t finite and non-negative.
Sourcepub fn with_drag_table(self, table: DragTable) -> Self
pub fn with_drag_table(self, table: DragTable) -> Self
This model with table replacing the drag buildup’s zero-lift drag
(crate::table), and any drag model (AeroModel::with_drag_model).
Sourcepub fn drag_table(&self) -> Option<&DragTable>
pub fn drag_table(&self) -> Option<&DragTable>
The drag override table, if any.
Sourcepub fn with_drag_model(self, model: impl DragModel + 'static) -> Self
pub fn with_drag_model(self, model: impl DragModel + 'static) -> Self
This model with model replacing the drag buildup’s zero-lift drag, and any drag table
(crate::custom). The normal force, center of pressure and roll stay this model’s.
As AeroModel::with_drag_model, with a model already shared: models that hold the same
one are equal.
Sourcepub fn drag_model(&self) -> Option<&Arc<dyn DragModel>>
pub fn drag_model(&self) -> Option<&Arc<dyn DragModel>>
The drag model in place of the buildup, if any.
Sourcepub fn with_full_base_drag_under_power(self) -> Self
pub fn with_full_base_drag_under_power(self) -> Self
This model with the aft base’s drag kept whole while a motor burns: the thrusting motors’
cross-section is not taken off the base (DragConditions::thrusting_motor_area_m2 and
the pods’ are read as zero), and a burning motor still selects a table’s power-on curve.
hpr’s own buildup takes it off, as Niskanen describes (2009, pp. 50–51: “if the base is
the same size as the motor itself, no base drag”). OpenRocket 24.12 does not: on every one
of its example designs’ flights of one branch, powered pods among them, its base-drag
column is the whole base’s coefficient while a motor burns, as after, where the motors
cover up to 94% of the reference area (validation/fixtures/ork/openrocket-base-drag.json,
ADR-097). This is how a comparison with OpenRocket sizes that difference; it is
not a better model. Neither rule has been checked against a measured flight.
Sourcepub fn full_base_drag_under_power(&self) -> bool
pub fn full_base_drag_under_power(&self) -> bool
Whether the aft base keeps its whole drag while a motor burns
(AeroModel::with_full_base_drag_under_power).
Sourcepub fn with_drag_scale(self, scale: f64) -> Result<Self, AeroError>
pub fn with_drag_scale(self, scale: f64) -> Result<Self, AeroError>
Multiplies every zero-lift drag coefficient AeroModel::drag gives by scale: the
buildup’s (each of its five parts too), an override table’s or a drag model’s. A Monte
Carlo run disperses drag this way, as RocketPy’s power_off_drag_factor and
power_on_drag_factor do (rocketpy/stochastic/stochastic_rocket.py:745-746); the angle of
attack’s factor, the normal force and the moments are not scaled. A table’s
Drag::table lookup stays the table’s own value, and AeroModel::buildup_drag, what a
drag model is given to adjust, stays unscaled.
§Errors
AeroError::Domain for a scale that is negative or not finite.
Sourcepub fn drag_scale(&self) -> f64
pub fn drag_scale(&self) -> f64
The factor on every zero-lift drag coefficient (AeroModel::with_drag_scale); 1 unless
set.
Sourcepub fn supersonic_table_built(&self) -> bool
pub fn supersonic_table_built(&self) -> bool
Whether the supersonic table (AeroModel::supersonic_body) has been built, by this
model or by one sharing it (AeroModel::share_supersonic_table). A flight builds it the
first time its flow passes Mach 1.2.
Takes other’s supersonic table (AeroModel::supersonic_body) in place of this model’s
own, when the two would build the same table: when they cover the same segments on the
same reference area, the only inputs the table is built from. Then whichever model first
needs the table builds it once for both, and for every clone of either, and the flights
they fly are unchanged, bit for bit. Building the table takes up to about 125 runs of the
shock-expansion method, a fifth of a second or more, so many flights of one airframe
share it this way: a Monte Carlo run, whose samples change masses, motors, drag scale and
weather but not the shape.
Returns true if the table is now shared. It returns false, and changes nothing, for
another shape or reference area, or for a model with no table to build: one whose body
the shock-expansion method doesn’t cover from the nose (a blunt nose, for one), which
keeps slender-body theory past Mach 1.2.
Sourcepub fn with_normal_force_table(
self,
table: NormalForceTable,
) -> Result<Self, AeroError>
pub fn with_normal_force_table( self, table: NormalForceTable, ) -> Result<Self, AeroError>
This model with table replacing the whole rocket’s normal force and center of pressure
(AeroModel::normal_force). Each component’s own terms stay hpr’s
(AeroModel::components, AeroModel::component_normal_force): a flight engine takes
its pitch and yaw damping from them, which a table doesn’t give.
§Errors
AeroError::Domain for a center of pressure in the table outside the rocket, from its
nose tip to its aft end: the sign of a length in the wrong unit or from another datum. Only
the Mach numbers a flight can use are checked, up to NORMAL_FORCE_MACH_LIMIT and the
first past it; a hypersonic row may move where it likes.
Sourcepub fn normal_force_table(&self) -> Option<&NormalForceTable>
pub fn normal_force_table(&self) -> Option<&NormalForceTable>
The normal-force override table, if any.
Sourcepub fn drag_terms(&self) -> &[ComponentDragTerms]
pub fn drag_terms(&self) -> &[ComponentDragTerms]
The components’ precomputed drag terms, in layout order.
Sourcepub fn length_m(&self) -> f64
pub fn length_m(&self) -> f64
Rocket length for the Reynolds number: nose tip to the aft end of the last body component, m.
Sourcepub fn drag(
&self,
flow: &Flow,
conditions: &DragConditions,
) -> Result<Drag, AeroError>
pub fn drag( &self, flow: &Flow, conditions: &DragConditions, ) -> Result<Drag, AeroError>
The whole rocket’s drag at flow and conditions: the zero-lift drag of the buildup, or of
the override table or drag model when there is one, and the axial coefficient at the
flow’s angle of attack.
§Errors
AeroError::Machoutside[0, 5)for the buildup (crate::drag::BUILDUP_MACH_LIMIT), and from Mach 0.8 around a tube fin set’s (crate::tube_fins::TUBE_FIN_MACH_LIMIT); with an override table or a drag model any finite Mach number from 0 is accepted (AeroError::Domainotherwise).AeroError::DragModelaround whatever a drag model returns, andAeroError::Domainfor a coefficient from it that is negative or not finite.- Without a table,
AeroError::InComponentaroundAeroError::Unsupportedfor a nose or shoulder shape the buildup has no drag data for (crate::drag::ComponentDragTerms::unsupported). AeroError::Domainfor an angle of attack outside[0, π]or a non-finite roll.- As
DragConditions::validate. AeroError::Tablefrom the table lookup, andAeroError::Domainfor a table’s coefficient that is negative at the flow’s Mach number, or a drag that isn’t finite.
Sourcepub fn buildup_drag(
&self,
flow: &Flow,
conditions: &DragConditions,
) -> Result<Drag, AeroError>
pub fn buildup_drag( &self, flow: &Flow, conditions: &DragConditions, ) -> Result<Drag, AeroError>
The drag buildup’s drag at flow and conditions, whatever override the model has: the
sum of every component’s zero-lift terms, and the axial coefficient at the flow’s angle of
attack. Without an override it is AeroModel::drag; with one, what the override
replaces, which a drag model can adjust (crate::custom::DragQuery::buildup).
§Errors
As AeroModel::drag without an override.
Sourcepub fn buildup_components(
&self,
flow: &Flow,
conditions: &DragConditions,
) -> Result<Vec<ComponentDrag>, AeroError>
pub fn buildup_components( &self, flow: &Flow, conditions: &DragConditions, ) -> Result<Vec<ComponentDrag>, AeroError>
Each component’s share of the drag buildup at flow and conditions, in layout order: its
zero-lift coefficient and parts, and its axial coefficient at the flow’s angle of attack.
These are always the buildup’s terms. With an override table or a drag model,
AeroModel::drag returns its value instead of their sum, so they don’t add up to it.
§Errors
As AeroModel::drag without a table, and DragConditions::validate.
Sourcepub fn reference_area_m2(&self) -> f64
pub fn reference_area_m2(&self) -> f64
Reference area, m².
Sourcepub fn reference_diameter_m(&self) -> f64
pub fn reference_diameter_m(&self) -> f64
Reference diameter, m: the length the rolling moment is taken on.
Sourcepub fn roll(&self, mach: f64) -> Result<Roll, AeroError>
pub fn roll(&self, mach: f64) -> Result<Roll, AeroError>
The whole rocket’s rolling moment at mach about +z_B, on the reference area and
diameter: C_l = C_l0 + C_lp (p d/2V), with p the roll rate about +z_B and V the
airspeed. Each fin set adds C_l0 = −N C_lδ k_T(B) δ and N C_lp k_R(B) (FinAero::roll,
roll_forcing_interference, roll_damping_interference); a positive cant δ turns
each fin’s leading edge toward −y_B at fin 0, so its lift rolls the rocket toward −z_B.
Fin–fin interference is not applied to roll, as in Niskanen 2009 eq. 3.66. The airframe’s
bodies of revolution add nothing. A pod’s body parts damp the roll by
C_lp = −2 C_Nα ρ²/d² per pod, ρ its distance from the axis, and a pod’s fins damp it by
the strips’ distance from the rocket’s axis (PodFins); a pod adds no forcing.
§Errors
AeroError::Mach outside [0, 5), as AeroModel::normal_force, and AeroError::Mach at Mach 0.8 and above on a rocket with tube fins
(crate::tube_fins::TUBE_FIN_MACH_LIMIT).
Sourcepub fn steady_roll_rate_rad_s(
&self,
mach: f64,
speed_m_s: f64,
) -> Result<f64, AeroError>
pub fn steady_roll_rate_rad_s( &self, mach: f64, speed_m_s: f64, ) -> Result<f64, AeroError>
The steady roll rate about +z_B, rad/s, at mach and airspeed speed_m_s in axial flow:
where the fins’ forcing and damping balance, p = −(C_l0/C_lp)(2V/d). Zero with no fins.
§Errors
As AeroModel::roll, and AeroError::Domain for a negative or non-finite airspeed.
Sourcepub fn bodies(&self) -> &[BodyAero]
pub fn bodies(&self) -> &[BodyAero]
The airframe’s body components’ terms; a pod’s are in Self::pod_sets.
Sourcepub fn supersonic_body(&self) -> Option<&SupersonicBody>
pub fn supersonic_body(&self) -> Option<&SupersonicBody>
The shock-expansion method’s shares of the nose, the cylinders and boattails behind it,
and where they join slender-body theory; None where the method can’t take the body (a nose
steeper than a blunt tip’s handover all the way to its base, a tangent cone past TN 3527’s
Fig. 2, a later body with a slope of its own such as a flare) or doesn’t hold across a
whole join below Mach 5.
The first call builds the table, which takes up to about 125 runs of the method; a flow no
faster than SUPERSONIC_JOIN_START_MACH never needs it.
Sourcepub fn supersonic_fallback(&self) -> Option<SupersonicFallback>
pub fn supersonic_fallback(&self) -> Option<SupersonicFallback>
Why the shock-expansion method doesn’t fly this body faster than sound, or None when it
does (Self::supersonic_body is Some). Like that, the first call may build the table.
A body with no run at all, such as one read back from JSON, gives Other.
Sourcepub fn body_lift_factor(&self, flow: &Flow) -> f64
pub fn body_lift_factor(&self, flow: &Flow) -> f64
The body-lift factor at flow, on (A_plan/A_ref) sin² α: Jorgensen’s η C_dn at the
body’s fineness and the crossflow Mach number M sin α, or Galejs’s K
(BodyModel::body_lift).
Sourcepub fn body_model(&self) -> BodyModel
pub fn body_model(&self) -> BodyModel
The body model: its body-lift and supersonic-boattail rules.
Sourcepub fn fineness(&self) -> f64
pub fn fineness(&self) -> f64
The body’s length over its largest diameter, which sets body lift’s η.
Sourcepub fn fin_sets(&self) -> &[FinSetAero]
pub fn fin_sets(&self) -> &[FinSetAero]
The fin sets’ terms.
Sourcepub fn rolls(&self) -> bool
pub fn rolls(&self) -> bool
Whether the normal force depends on the direction the air crosses the rocket: a fin set
of one or two fins, whose share of its force in a plane varies with the plane
(crate::roll_sum), and no normal-force table, which gives one force in every plane.
Sourcepub fn tube_fin_sets(&self) -> &[TubeFinSetAero]
pub fn tube_fin_sets(&self) -> &[TubeFinSetAero]
The tube fin sets’ terms.
Sourcepub fn pod_sets(&self) -> &[PodSetAero]
pub fn pod_sets(&self) -> &[PodSetAero]
The pod sets’ terms: those whose pods hold a body component with a size.
Sourcepub fn component_count(&self) -> usize
pub fn component_count(&self) -> usize
The number of components with a normal-force term: the airframe’s bodies, the pods’
bodies, the fin sets, then the tube fin sets, in the order of Self::components.
Sourcepub fn tube_fin_set_start(&self) -> usize
pub fn tube_fin_set_start(&self) -> usize
The index of the first tube fin set among the components (Self::components): the
bodies and the fin sets come before.
Sourcepub fn fin_set_start(&self) -> usize
pub fn fin_set_start(&self) -> usize
The index of the first fin set among the components (Self::components): the bodies,
the airframe’s and the pods’, come before. Every component from here is a lifting surface:
the fin sets, then the tube fin sets (Self::tube_fin_set_start).
Sourcepub fn component_normal_force(
&self,
index: usize,
flow: &Flow,
) -> Result<NormalForce, AeroError>
pub fn component_normal_force( &self, index: usize, flow: &Flow, ) -> Result<NormalForce, AeroError>
Component index’s normal force at flow, in the order of Self::components, without
allocating. A flight engine evaluates each component at its own local flow, which includes
the airspeed the body’s rotation adds at the component.
§Errors
As Flow::validate, AeroError::Mach at Mach 0.8 and above for a tube fin set, and
AeroError::Domain for an index past Self::component_count.
Sourcepub fn component_station_m(
&self,
index: usize,
mach: f64,
) -> Result<f64, AeroError>
pub fn component_station_m( &self, index: usize, mach: f64, ) -> Result<f64, AeroError>
The station, m aft of the nose tip, where a flight engine takes component index’s local
airspeed at mach.
It is the component’s small-angle center of pressure wherever one model carries it: a fin
set’s own, and a body’s moment_slope / slope, or its body-lift station where it has no
potential-flow slope (a cylinder). Where two models share it, it is not: faster than sound
a nose’s or cylinder’s station is joined linearly from slender-body theory’s to the
method’s as the weight rises (SupersonicBody), while the force blends slopes and
moments, so the two agree only at the ends of the join. On a lip riding half in its
boattail’s wake, which never reaches an end, the tests’ tube sits 0.114 m (about two
calibres) behind its own center of pressure
(issue #106, which measures it and holds
what a fix has to settle). A covered boattail, and a cylinder behind it, keep
slender-body theory’s station: their shares may cross zero, where a station would run off
to infinity.
§Errors
AeroError::Mach outside [0, 5), or [0, 0.8) for a tube fin set
(crate::tube_fins::TUBE_FIN_MACH_LIMIT), and AeroError::Domain for an index past
Self::component_count.
Sourcepub fn normal_force(&self, flow: &Flow) -> Result<NormalForce, AeroError>
pub fn normal_force(&self, flow: &Flow) -> Result<NormalForce, AeroError>
The whole rocket’s normal force at flow: the sum of its components, or the override
table’s when there is one (AeroModel::with_normal_force_table).
A table’s normal force acts in the plane of the flow at the table’s center of pressure,
with no side force; its coefficients are rescaled to the rocket’s reference area from the
table’s (crate::table::TableReference).
§Errors
As Flow::validate, and without a table AeroError::Mach at Mach 0.8 and above on a rocket with tube fins
(crate::tube_fins::TUBE_FIN_MACH_LIMIT). With a table, any finite
Mach number from 0 is accepted (AeroError::Domain otherwise), and table errors are
returned.
Sourcepub fn components(
&self,
flow: &Flow,
) -> Result<Vec<ComponentNormalForce>, AeroError>
pub fn components( &self, flow: &Flow, ) -> Result<Vec<ComponentNormalForce>, AeroError>
Each component’s normal force at flow: the airframe’s bodies, then the pods’ bodies (each
over all its pods), then fin sets, then tube fin sets, each in layout order. A
step in radius is part of the component aft of it.
These are always hpr’s own terms. With a normal-force table, AeroModel::normal_force
returns the table’s value instead of their sum.
§Errors
As Flow::validate, and AeroError::Mach at Mach 0.8 and above on a rocket with tube fins
(crate::tube_fins::TUBE_FIN_MACH_LIMIT).