@@ -44,82 +44,180 @@ def __init__(
4444 self ._airfoil = airfoil
4545 self ._cant_angle = cant_angle
4646 self ._cant_angle_rad = math .radians (cant_angle )
47+ self .geometry = None
4748
4849 self .d = 2 * rocket_radius
4950 self .ref_area = np .pi * rocket_radius ** 2
5051
5152 super ().__init__ (name , self .ref_area , self .d )
5253
54+ def _run_geometry_update_chain (self ):
55+ """Recompute all dependent aerodynamic properties after a geometry change."""
56+ self .evaluate_geometrical_parameters ()
57+ self .evaluate_center_of_pressure ()
58+ self .evaluate_lift_coefficient ()
59+ self .evaluate_roll_parameters ()
60+
5361 @property
5462 def rocket_radius (self ):
63+ """Rocket radius in meters.
64+
65+ Returns
66+ -------
67+ float
68+ Rocket radius in meters.
69+ """
5570 return self ._rocket_radius
5671
5772 @rocket_radius .setter
5873 def rocket_radius (self , value ):
74+ """Set rocket radius and update dependent properties.
75+
76+ Parameters
77+ ----------
78+ value : float
79+ Rocket radius in meters.
80+ """
5981 self ._rocket_radius = value
60- self .evaluate_geometrical_parameters ()
61- self .evaluate_center_of_pressure ()
62- self .evaluate_lift_coefficient ()
63- self .evaluate_roll_parameters ()
82+ self ._run_geometry_update_chain ()
6483
6584 @property
6685 def root_chord (self ):
86+ """Root chord length in meters.
87+
88+ Returns
89+ -------
90+ float
91+ Root chord length in meters.
92+ """
6793 return self ._root_chord
6894
6995 @root_chord .setter
7096 def root_chord (self , value ):
97+ """Set root chord and update dependent properties.
98+
99+ Parameters
100+ ----------
101+ value : float
102+ Root chord length in meters.
103+ """
71104 self ._root_chord = value
72- self .evaluate_geometrical_parameters ()
73- self .evaluate_center_of_pressure ()
74- self .evaluate_lift_coefficient ()
75- self .evaluate_roll_parameters ()
105+ self ._run_geometry_update_chain ()
76106
77107 @property
78108 def span (self ):
109+ """Fin span in meters.
110+
111+ Returns
112+ -------
113+ float
114+ Fin span in meters.
115+ """
79116 return self ._span
80117
81118 @span .setter
82119 def span (self , value ):
120+ """Set fin span and update dependent properties.
121+
122+ Parameters
123+ ----------
124+ value : float
125+ Fin span in meters.
126+ """
83127 self ._span = value
84- self .evaluate_geometrical_parameters ()
85- self .evaluate_center_of_pressure ()
86- self .evaluate_lift_coefficient ()
87- self .evaluate_roll_parameters ()
128+ self ._run_geometry_update_chain ()
88129
89130 @property
90131 def cant_angle (self ):
132+ """Cant angle in degrees.
133+
134+ Returns
135+ -------
136+ float
137+ Cant angle in degrees.
138+ """
91139 return self ._cant_angle
92140
93141 @cant_angle .setter
94142 def cant_angle (self , value ):
143+ """Set cant angle and update radian representation.
144+
145+ Parameters
146+ ----------
147+ value : float
148+ Cant angle in degrees.
149+ """
95150 self ._cant_angle = value
96151 self .cant_angle_rad = math .radians (value )
97152
98153 @property
99154 def cant_angle_rad (self ):
155+ """Cant angle in radians.
156+
157+ Returns
158+ -------
159+ float
160+ Cant angle in radians.
161+ """
100162 return self ._cant_angle_rad
101163
102164 @cant_angle_rad .setter
103165 def cant_angle_rad (self , value ):
166+ """Set cant angle in radians and update dependent properties.
167+
168+ Parameters
169+ ----------
170+ value : float
171+ Cant angle in radians.
172+ """
104173 self ._cant_angle_rad = value
105- self .evaluate_geometrical_parameters ()
106- self .evaluate_center_of_pressure ()
107- self .evaluate_lift_coefficient ()
108- self .evaluate_roll_parameters ()
174+ self ._run_geometry_update_chain ()
109175
110176 @property
111177 def airfoil (self ):
178+ """Airfoil data for the fin.
179+
180+ Returns
181+ -------
182+ tuple or None
183+ Tuple containing airfoil data and unit ('degrees' or 'radians'),
184+ or None if using planar fin.
185+ """
112186 return self ._airfoil
113187
114188 @airfoil .setter
115189 def airfoil (self , value ):
190+ """Set airfoil data and update dependent properties.
191+
192+ Parameters
193+ ----------
194+ value : tuple or None
195+ Tuple containing airfoil data and unit ('degrees' or 'radians'),
196+ or None for planar fin.
197+ """
116198 self ._airfoil = value
117- self .evaluate_geometrical_parameters ()
118- self .evaluate_center_of_pressure ()
119- self .evaluate_lift_coefficient ()
120- self .evaluate_roll_parameters ()
199+ self ._run_geometry_update_chain ()
200+
201+ def info (self ):
202+ """Print fin geometry and lift information."""
203+ self .prints .geometry ()
204+ self .prints .lift ()
205+
206+ def all_info (self ):
207+ """Print all available fin information and show all fin plots."""
208+ self .prints .all ()
209+ self .plots .all ()
121210
122211 def evaluate_single_fin_lift_coefficient (self ):
212+ """Evaluate the lift coefficient derivative for a single fin.
213+
214+ Computes the lift coefficient derivative (clalpha) considering the
215+ fin's geometry, airfoil characteristics (if provided), and Mach number
216+ effects using Prandtl-Glauert compressibility correction and
217+ Diederich's planform correlation.
218+
219+ Sets the `clalpha_single_fin` attribute as a Function of Mach number.
220+ """
123221 if not self .airfoil :
124222 # Defines clalpha2D as 2*pi for planar fins
125223 clalpha2D_incompressible = 2 * np .pi
@@ -133,9 +231,7 @@ def evaluate_single_fin_lift_coefficient(self):
133231 )
134232
135233 # Differentiating at alpha = 0 to get cl_alpha
136- clalpha2D_incompressible = self .airfoil_cl .differentiate_complex_step (
137- x = 1e-3 , dx = 1e-3
138- )
234+ clalpha2D_incompressible = self .airfoil_cl .differentiate (x = 1e-3 , dx = 1e-3 )
139235
140236 # Convert to radians if needed
141237 if self .airfoil [1 ] == "degrees" :
@@ -170,24 +266,30 @@ def lift_source(mach):
170266
171267 @abstractmethod
172268 def evaluate_lift_coefficient (self ):
173- pass
269+ """Evaluate the lift coefficient for the fin."""
174270
175271 @abstractmethod
176272 def evaluate_roll_parameters (self ):
177- pass
273+ """Evaluate roll-related parameters for the fin."""
178274
179275 @abstractmethod
180276 def evaluate_center_of_pressure (self ):
181- pass
277+ """Evaluate the center of pressure for the fin."""
182278
183- @abstractmethod
184279 def evaluate_geometrical_parameters (self ):
185- pass
280+ """Evaluate geometric parameters of the fin.
281+
282+ This method delegates to the configured geometry strategy.
283+ """
284+ self .geometry .evaluate_geometrical_parameters ()
186285
187- @abstractmethod
188286 def evaluate_shape (self ):
189- pass
287+ """Evaluate the shape representation of the fin.
288+
289+ This method delegates to the configured geometry strategy.
290+ """
291+ self .geometry .evaluate_shape ()
190292
191293 @abstractmethod
192294 def draw (self ):
193- pass
295+ """Draw or render the fin."""
0 commit comments