def IdealTRange(self, *args): """ Returns the total (EM+ICE)thrust range at which the powerplant can run the ICE at ideal rps""" if len(args) == 0: v = self.V() h = self.x2[self.n] else: v = args[0] h = args[1] lower = PropTFun(v, self.PP['idealICErps'], h)[0] upper = (PropTFun(v, self.PP['maxEMrps'], h) + lower)[0] return lower, upper
def FindConstraints(): """ Calculates the maximum horizontal and vertical velocities and height which the power-plant can achieve. These are stored in a global 3x30 array called limits Returns ------- None. """ global limits print(['limits' in globals()]) print(['limits' in locals()]) limits = np.zeros((3, 15**2)) # (maxv1, maxv2, maxHeight) print(['limits' in globals()]) print(['limits' in locals()]) v1Array = np.linspace(10, 50, 15) hArray = np.linspace(100, 6000, 15) s = simulate(10e7) counter = 0 for hndex, h in enumerate(hArray): for index, i in enumerate(v1Array): T = 0 maxThrust = 1 v2 = 0 while T < maxThrust: v2 += 0.5 v = math.sqrt(i**2 + v2**2) maxThrust = float( PropTFun(v, PP['ICEMaprps'][-1], h) + PropTFun(v, PP['maxEMrps'], h)) T = float(AnalyticalFindTP(s, h, i, v2)[0]) limits[0, counter] = i limits[1, counter] = v2 - 0.5 limits[2, counter] = h counter += 1 return limits
def AllocateThrust(self): """ RB controller. Determines the ICE and EM speeds and thrust by applying a set of rules around the ICE speed which produces the highest efficiency. If excess thrust is demanded, the RBOut attribute array is flagged with a 4 at the relevant n value Returns ------- None. """ v = self.V() h = self.x2[self.n] thrustRequest = self.thrust[self.n] idealICEThrust = PropTFun(v, self.PP['idealICErps'], h) maxICEThrust = PropTFun(v, self.PP['ICEMaprps'][-1], h) maxEMThrust = PropTFun(v, self.PP['maxEMrps'], h) # print('Requested Thrust =', thrustRequest) # print('Max EM thrust available=', maxEMThrust[0]) # print('Max ICE thrust available=', maxICEThrust[0]) # use a guess which would produce the ideal J for the prop eff rpsGuess = v / (self.PP['D'] * self.PP['optJ']) if rpsGuess < 10: rpsGuess = 10 # warn if thrust cannot be given, then set the rpm to the necessary value # this will be filtered out later and converted to a disproportionately high energy cost if thrustRequest > maxICEThrust + maxEMThrust: print('\nWARNING: THE THRUST REQUESTED IS NOT AVAILABLE.', thrustRequest, 'N were requested but only', maxICEThrust + maxEMThrust, 'are available') print('Current velocity:', self.V(), '\n') excess = thrustRequest - maxICEThrust - maxEMThrust ICEThrust = maxICEThrust + excess / 2 EMThrust = maxEMThrust + excess / 2 try: ICErps = brentq(lambda rps: PropTFun(v, rps, h) - ICEThrust, self.PP['ICEMaprps'][0], self.PP['ICEMaprps'][-1] * 2) except ValueError: ICErps = self.PP['ICEMaprps'][-1] try: EMrps = brentq(lambda rps: PropTFun(v, rps, h) - EMThrust, 0, self.PP['maxEMrps'] * 2) except ValueError: EMrps = self.PP['maxEMrps'] # flag to dramatically increase thrust demand self.RBOut[self.n] = 4 # use max EM thrust and lowest possible ICE thrust elif thrustRequest > idealICEThrust + maxEMThrust: EMThrust = maxEMThrust ICEThrust = thrustRequest - EMThrust EMrps = self.PP['maxEMrps'] ICErps = brentq(lambda rps: PropTFun(v, rps, h) - ICEThrust, self.PP['ICEMaprps'][0], self.PP['ICEMaprps'][-1]) self.RBOut[self.n] = 3 # use ideal ICE thrust and the rest is EM power elif thrustRequest > idealICEThrust: ICEThrust = idealICEThrust EMThrust = thrustRequest - ICEThrust ICErps = self.PP['idealICErps'] EMrps = brentq(lambda rps: PropTFun(v, rps, h) - EMThrust, 0, self.PP['maxEMrps']) self.RBOut[self.n] = 2 # use only ICE elif thrustRequest <= idealICEThrust and thrustRequest > 0: ICEThrust = thrustRequest EMThrust = 0 EMrps = 0 # if the thrust is tiny, set it to zero if PropTFun(v, 1, h) - ICEThrust > 0: ICEThrust = 0 ICErps = 0 self.RBOut[self.n] = 0 else: ICErps = brentq(lambda rps: PropTFun(v, rps, h) - ICEThrust, 1, self.PP['ICEMaprps'][-1]) self.RBOut[self.n] = 1 # plant is off elif thrustRequest == 0: ICEThrust = 0 EMThrust = 0 EMrps = 0 ICErps = 0 self.RBOut[self.n] = 0 self.EMrps[self.n] = EMrps self.ICErps[self.n] = ICErps self.EMThrust[self.n] = EMThrust self.ICEThrust[self.n] = ICEThrust
def AllocateThrust(self): v = self.V() h = self.x2[self.n] thrustRequest = self.thrust[self.n] idealICEThrust = PropTFun(v, self.PP['idealICErps'], h) maxICEThrust = PropTFun(v, self.PP['ICEMaprps'][-1], h) maxEMThrust = PropTFun(v, self.PP['maxEMrps'], h) # print('Requested Thrust =', thrustRequest) # print('Max EM thrust available=', maxEMThrust[0]) # print('Max ICE thrust available=', maxICEThrust[0]) # use a guess which would produce the ideal J for the prop eff rpsGuess = v / (self.PP['D'] * self.PP['optJ']) if rpsGuess < 10: rpsGuess = 10 # warn if thrust cannot be given, then set the rpm to the necessary value # this will be filtered out later and converted to a disproportionately high energy cost if thrustRequest > maxICEThrust + maxEMThrust: print('\nWARNING: THE THRUST REQUESTED IS NOT AVAILABLE.', thrustRequest, 'N were requested but only', maxICEThrust + maxEMThrust, 'are available') print('Current velocity:', self.V(), '\n') excess = thrustRequest - maxICEThrust - maxEMThrust ICEThrust = maxICEThrust + excess / 2 EMThrust = maxEMThrust + excess / 2 try: ICErps = brentq(lambda rps: PropTFun(v, rps, h) - ICEThrust, self.PP['ICEMaprps'][0], self.PP['ICEMaprps'][-1] * 2) except ValueError: ICErps = self.PP['ICEMaprps'][-1] try: EMrps = brentq(lambda rps: PropTFun(v, rps, h) - EMThrust, 0, self.PP['maxEMrps'] * 2) except ValueError: EMrps = self.PP['maxEMrps'] self.RBOut[self.n] = 4 # use max EM thrust and lowest possible ICE thrust elif thrustRequest > idealICEThrust + maxEMThrust: EMThrust = maxEMThrust ICEThrust = thrustRequest - EMThrust EMrps = self.PP['maxEMrps'] ICErps = brentq(lambda rps: PropTFun(v, rps, h) - ICEThrust, self.PP['ICEMaprps'][0], self.PP['ICEMaprps'][-1]) self.RBOut[self.n] = 3 # use ideal ICE thrust and the rest is EM power elif thrustRequest > idealICEThrust: ICEThrust = idealICEThrust EMThrust = thrustRequest - ICEThrust ICErps = self.PP['idealICErps'] EMrps = brentq(lambda rps: PropTFun(v, rps, h) - EMThrust, 0, self.PP['maxEMrps']) self.RBOut[self.n] = 2 # use only ICE elif thrustRequest <= idealICEThrust and thrustRequest > 0: ICEThrust = thrustRequest EMThrust = 0 EMrps = 0 # if the thrust is tiny, set it to zero if PropTFun(v, 1, h) - ICEThrust > 0: ICEThrust = 0 ICErps = 0 self.RBOut[self.n] = 0 else: ICErps = brentq(lambda rps: PropTFun(v, rps, h) - ICEThrust, 1, self.PP['ICEMaprps'][-1]) self.RBOut[self.n] = 1 # plant is off elif thrustRequest == 0: ICEThrust = 0 EMThrust = 0 EMrps = 0 ICErps = 0 self.RBOut[self.n] = 0 self.EMrps[self.n] = EMrps self.ICErps[self.n] = ICErps self.EMThrust[self.n] = EMThrust self.ICEThrust[self.n] = ICEThrust
def TakeOff(s, minimizeTOD=False, fullOutput=True): # liftoff velocity at 0 angle of attack vlo = VLO(s) # make sure the plane can actually take off before proceeding if s.time != 0 or s.n != 0 or\ s.x2[s.n] != 0: raise ValueError('The aircraft is not at take-off conditions') if fullOutput: print('\n----------') print('-- Take Off --\n') print('Expected liftoff v: ', round(VLO(s, 8), 2), ' m/s') print('\n') # take off at maximum thrust if minimizeTOD: s.runtime = 1 s.steps = 2 h = 0 # add maximum thrusts T = PropTFun(vlo, s.PP['ICEMaprps'][-1], 0) + PropTFun( vlo, s.PP['maxEMrps'], 0) s.TShape = 'const' s.pitchShape = 'const' while h <= 0: if s.V() > vlo: print('Readjusting liftoff velocity') T = PropTFun(s.V() * 1.2, PP['ICEMapShaftrps[-1]'], 0) \ + PropTFun(s.V() * 1.2, PP['maxEMrps'], 0) s.TShape = 'const' s.TShape = 'const' s.pitchShape = 'const' s.TCeiling = Sigmoid(s.time, 0, T, 0, 10) s.pitchCeiling = Sigmoid(s.time, 0, AC['maxPitch'], 0, 5) h = s.x2[s.n] s.RunInterval() # run at max EM thrust plus ideal ICE thrust else: # set thrust to 90% of the upper limit to run the ICE at ideal rps T = s.IdealTRange(vlo, 0)[1] * 0.9 s.runtime = 1 s.steps = 2 s.TShape = 'const' s.pitchShape = 'const' h = s.x2[s.n] while h <= 0: if s.V() > vlo: print('Readjusting liftoff velocity') T = PropTFun(s.V() * 1.2, s.PP['ICEMaprps'][-1], 0)\ + PropTFun(s.V() * 1.2, s.PP['maxEMrps'], 0) s.TShape = 'const' s.TCeiling = T s.TShape = 'const' s.pitchShape = 'const' s.TCeiling = Sigmoid(s.time, 0, T, 0, 10) s.pitchCeiling = Sigmoid(s.time, 0, AC['maxPitch'], 0, 5) h = s.x2[s.n] s.RunInterval() if fullOutput: print('Lift off achieved in ', s.time, 's, ', '\n x1=', round(s.x1[s.n], 2), 'm | v1 =', round(s.v1[s.n], 2), 'm/s', '\n x2=', round(s.x2[s.n], 2), 'm | v2 =', round(s.v2[s.n], 2), 'm/s', '\n thrust =', round(s.thrust[s.n - 1], 2), 'N | pitch =', round(s.pitch[s.n - 1], 2), 'degrees') print('--------')