@@ -123,6 +123,11 @@ class Parachute:
123123 Parachute.added_mass_coefficient : float
124124 Coefficient used to calculate the added-mass due to dragged air. It is
125125 calculated from the porosity of the parachute.
126+ Parachute.opening_shock_coefficient : float
127+ Dimensionless opening-force coefficient (``Cx``) used to estimate the
128+ peak opening shock force via
129+ :meth:`Parachute.evaluate_opening_shock_force`. ``None`` when the
130+ estimate is disabled.
126131 """
127132
128133 def __init__ (
@@ -137,6 +142,7 @@ def __init__(
137142 height = None ,
138143 porosity = 0.0432 ,
139144 drag_coefficient = 1.4 ,
145+ opening_shock_coefficient = None ,
140146 ):
141147 """Initializes Parachute class.
142148
@@ -217,6 +223,15 @@ def __init__(
217223 - **1.5** — extended-skirt canopy
218224
219225 Has no effect when ``radius`` is explicitly provided.
226+ opening_shock_coefficient : float, optional
227+ Dimensionless opening-force coefficient (``Cx``) used to estimate
228+ the peak parachute opening shock force via
229+ :meth:`evaluate_opening_shock_force`, following Knacke's
230+ *Parachute Recovery Systems Design Manual*. It lumps together the
231+ opening-force coefficient and the infinite-mass factor (``X1``).
232+ Typical values range from about 1.2 to 2.0 depending on canopy
233+ type. If ``None`` (default), the opening shock force is not
234+ estimated. Units are dimensionless.
220235 """
221236
222237 # Save arguments as attributes
@@ -228,6 +243,7 @@ def __init__(
228243 self .noise = noise
229244 self .drag_coefficient = drag_coefficient
230245 self .porosity = porosity
246+ self .opening_shock_coefficient = opening_shock_coefficient
231247
232248 # Initialize derived attributes
233249 self .radius = self .__resolve_radius (radius , cd_s , drag_coefficient )
@@ -259,6 +275,43 @@ def __compute_added_mass_coefficient(self, porosity):
259275 1 - 1.465 * porosity - 0.25975 * porosity ** 2 + 1.2626 * porosity ** 3
260276 )
261277
278+ def evaluate_opening_shock_force (self , air_density , velocity ):
279+ """Estimate the peak parachute opening shock force.
280+
281+ Uses the standard approximation from Knacke's *Parachute Recovery
282+ Systems Design Manual*: ``F_o = Cx * q * cd_s``, where ``q`` is the
283+ dynamic pressure ``0.5 * air_density * velocity ** 2`` at inflation and
284+ ``Cx`` is the ``opening_shock_coefficient``. This is an empirical
285+ estimate of the peak transient (inflation) load on the recovery
286+ harness, not a result of the equation-of-motion integration, and it is
287+ typically several times larger than the steady-state drag force
288+ ``q * cd_s``.
289+
290+ Parameters
291+ ----------
292+ air_density : float
293+ Air density at inflation, in kg/m^3.
294+ velocity : float
295+ Freestream speed at inflation, in m/s.
296+
297+ Returns
298+ -------
299+ float
300+ Peak opening shock force, in newtons.
301+
302+ Raises
303+ ------
304+ ValueError
305+ If ``opening_shock_coefficient`` was not set at construction.
306+ """
307+ if self .opening_shock_coefficient is None :
308+ raise ValueError (
309+ "opening_shock_coefficient must be set to estimate the "
310+ "opening shock force."
311+ )
312+ dynamic_pressure = 0.5 * air_density * velocity ** 2
313+ return self .opening_shock_coefficient * dynamic_pressure * self .cd_s
314+
262315 def __init_noise (self , noise ):
263316 """Initializes all noise-related attributes.
264317
@@ -421,6 +474,7 @@ def to_dict(self, **kwargs):
421474 "drag_coefficient" : self .drag_coefficient ,
422475 "height" : self .height ,
423476 "porosity" : self .porosity ,
477+ "opening_shock_coefficient" : self .opening_shock_coefficient ,
424478 }
425479
426480 if kwargs .get ("include_outputs" , False ):
@@ -455,6 +509,7 @@ def from_dict(cls, data):
455509 drag_coefficient = data .get ("drag_coefficient" , 1.4 ),
456510 height = data .get ("height" , None ),
457511 porosity = data .get ("porosity" , 0.0432 ),
512+ opening_shock_coefficient = data .get ("opening_shock_coefficient" , None ),
458513 )
459514
460515 return parachute
0 commit comments