@@ -148,32 +148,54 @@ class BFLImplicitSolve(ImplicitComponent):
148148 def setup (self ):
149149 self .add_input ("distance_continue" , units = "m" )
150150 self .add_input ("distance_abort" , units = "m" )
151- self .add_input ("takeoff|vr" , units = "m/s" )
152- self .add_output ("takeoff|v1" , units = "m/s" , val = 20 , lower = 10 , upper = 150 )
151+ self .add_input ("takeoff|vr" , units = "m/s" , val = 30.0 )
152+ self .add_output ("takeoff|v1" , units = "m/s" , val = 20.0 , lower = 10.0 , upper = 150.0 )
153153 self .declare_partials ("takeoff|v1" , ["distance_continue" , "distance_abort" , "takeoff|v1" , "takeoff|vr" ])
154154
155+ self .speedtol = 1e-1
156+ self .disttol = 0.0
157+
158+ def useVRes (self , vr , v1 , dist_continue , dist_abort ):
159+ """Determine whether to use the dist_continue - dist_abort or the vr - v1 residual.
160+
161+ If vr < v1 + speedtol then we use the vr - v1 residual, as long as dist_abort < dist_continue + disttol.
162+
163+ Parameters
164+ ----------
165+ vr : float
166+ Rotation speed
167+ v1 : float
168+ Decision speed
169+ dist_continue : float
170+ engine-out takeoff distance
171+ dist_abort : float
172+ Rejected takeoff distance
173+
174+ Returns
175+ -------
176+ bool
177+ True if the vr - v1 residual should be used, False if the dist_continue - dist_abort residual should be used.
178+ """
179+ return vr < v1 + self .speedtol and dist_abort < dist_continue + self .disttol
180+
155181 def apply_nonlinear (self , inputs , outputs , residuals ):
156- speedtol = 1e-1
157- disttol = 0
158- # force the decision speed to zero
159- if inputs ["takeoff|vr" ] < outputs ["takeoff|v1" ] + speedtol :
160- residuals ["takeoff|v1" ] = inputs ["takeoff|vr" ] - outputs ["takeoff|v1" ]
161- else :
162- residuals ["takeoff|v1" ] = inputs ["distance_continue" ] - inputs ["distance_abort" ]
182+ vr = inputs ["takeoff|vr" ]
183+ v1 = outputs ["takeoff|v1" ]
184+ dist_continue = inputs ["distance_continue" ]
185+ dist_abort = inputs ["distance_abort" ]
163186
164- # if you are within vtol on the correct side but the stopping distance bigger, use the regular mode
165- if (
166- inputs ["takeoff|vr" ] >= outputs ["takeoff|v1" ]
167- and inputs ["takeoff|vr" ] - outputs ["takeoff|v1" ] < speedtol
168- and (inputs ["distance_abort" ] - inputs ["distance_continue" ]) > disttol
169- ):
170- residuals ["takeoff|v1" ] = inputs ["distance_continue" ] - inputs ["distance_abort" ]
187+ if self .useVRes (vr , v1 , dist_continue , dist_abort ):
188+ residuals ["takeoff|v1" ] = vr - v1
189+ else :
190+ residuals ["takeoff|v1" ] = dist_continue - dist_abort
171191
172192 def linearize (self , inputs , outputs , partials ):
173- speedtol = 1e-1
174- disttol = 0
193+ vr = inputs ["takeoff|vr" ]
194+ v1 = outputs ["takeoff|v1" ]
195+ dist_continue = inputs ["distance_continue" ]
196+ dist_abort = inputs ["distance_abort" ]
175197
176- if inputs [ "takeoff|vr" ] < outputs [ "takeoff|v1" ] + speedtol :
198+ if self . useVRes ( vr , v1 , dist_continue , dist_abort ) :
177199 partials ["takeoff|v1" , "distance_continue" ] = 0
178200 partials ["takeoff|v1" , "distance_abort" ] = 0
179201 partials ["takeoff|v1" , "takeoff|vr" ] = 1
@@ -184,16 +206,6 @@ def linearize(self, inputs, outputs, partials):
184206 partials ["takeoff|v1" , "takeoff|vr" ] = 0
185207 partials ["takeoff|v1" , "takeoff|v1" ] = 0
186208
187- if (
188- inputs ["takeoff|vr" ] >= outputs ["takeoff|v1" ]
189- and inputs ["takeoff|vr" ] - outputs ["takeoff|v1" ] < speedtol
190- and (inputs ["distance_abort" ] - inputs ["distance_continue" ]) > disttol
191- ):
192- partials ["takeoff|v1" , "distance_continue" ] = 1
193- partials ["takeoff|v1" , "distance_abort" ] = - 1
194- partials ["takeoff|v1" , "takeoff|vr" ] = 0
195- partials ["takeoff|v1" , "takeoff|v1" ] = 0
196-
197209
198210class Groundspeeds (ExplicitComponent ):
199211 """
0 commit comments