class CostFunction(object): def __init__(self,costFcn,lb,ub): """ cost function should return f,g""" self.costFcn = costFcn self.nEval = 0 self.penalty = 1.0e5 self.norm = Normalization(lb,ub,0,1) def evaluate(self,x,penalty=None): x = self.norm.denormalize(x) if penalty==None: penalty = self.penalty f,g = self.costFcn(x) self.nEval += 1 cost = f for cnstr in g: cost += max([0.0,cnstr]) * penalty return cost,f,g def __call__(self,x,penalty=None): x = np.asarray(x) if x.ndim==1: return self.evaluate(x,penalty) elif x.ndim==2: n = x.shape[0] cost = np.zeros(n) f = np.zeros(n) cost[0],f[0],gtmp = self.evaluate(x[0],penalty) g = np.zeros([n,len(gtmp)]) g[0] = gtmp for i in range(1,n): cost[i],f[i],g[i] = self.evaluate(x[i],penalty) return cost,f,g
class AirfoilObjective: def __init__(self,x0,lb,ub): self.x0 = x0 self.af = None self.clCruise = [0.2,0.3] self.clmaxMin = 1.4 self.tcMin = 0.135 self.tcMax = 0.145 self.norm = Normalization(lb,ub) self.cruise = FlightConditions(55,1500) self.landing = FlightConditions(1.2*20.6, 0) self.cdminAlpha = [0,3.0] self.afBaseline = cst_x(x0) def set_cst(self,xnorm): x = self.norm.denormalize(xnorm) # for x1,x2 in zip(xnorm,x): # print '%.4f\t%.4f'%(x1,x2) # raw_input() self.af = cst_x(x,35) self.tc = self.af.thickness def f(self,x): sys.stdout.write('.') self.set_cst(x) pol = self.af.get_jfoil_polar(self.cruise.Mach, self.cruise.Re, [-10,10,0.5]) try: cd = np.array([pol.get_cd_at_cl(cl) for cl in self.clCruise]) return cd.mean() except ValueError: #self.af.display() #pol.display() return pol.cd[0] def fDeriv(self,x,dx=1e-2): grad = np.zeros(len(x)) fval = self.f(x) for i,xx in enumerate(x): X = np.copy(x) X[i] = X[i]+dx grad[i] = (self.f(X)-fval)/dx return grad def g1Deriv(self,x,dx=2e-3): grad = np.zeros(len(x)) fval = self.g1high(x) for i,xx in enumerate(x): X = np.copy(x) X[i] = X[i]+dx grad[i] = (self.g1high(X)-fval)/dx return grad def run_cfd(self,x,alpha=[12,14,16,18]): self.set_cst(x) self.af.coord = self.af.pts solver = CFDsolver(self.af,self.landing,1.0,mesh='O') solver.fluent.residuals['energy']=1e-5 solver.fluent.relaxationFactor['xvelocity'] = 1e-4 solver.fluent.residuals['continuity']=1e-4 solver.mesh._airfoilPts = 75 solver.mesh._interiorPts = 100 solver.mesh._dsTE = 2e-4 solver.mesh._dsLE = 1e-3 solver.mesh._growthRate = 1.15 solver.create_mesh() result = solver.run_for_multiple_aoa(alpha,'ke-realizable') result.Mach = self.landing.Mach result.Re = self.landing.Re result._calc_clmax() sys.stdout.write('|') return result def g1high(self,x): pol = self.run_cfd(x) return pol.clmax - self.clmaxMin def g1low(self,x): sys.stdout.write('.') self.set_cst(x) pol = self.af.get_jfoil_polar(self.landing.Mach, self.landing.Re, [0,20,1]) return pol.clmax-self.clmaxMin def g2(self,x): self.set_cst(x) return self.tc - self.tcMin def g3(self,x): self.set_cst(x) return self.tcMax - self.tc def g4(self,x): self.set_cst(x) pol = self.af.get_jfoil_polar(self.cruise.Mach, self.cruise.Re, [-10,10,0.5]) return pol.get_alpha_cdmin() - self.cdminAlpha[0] def g5(self,x): self.set_cst(x) pol = self.af.get_jfoil_polar(self.cruise.Mach, self.cruise.Re, [-10,10,0.5]) return self.cdminAlpha[1] - pol.get_alpha_cdmin()
def run_optimization_1(): pathIn = "design_out4.txt" pathInSamples = "DOE_LHS250_FFD2_3_3.txt" learnData = read_tabulated_data_without_header(pathIn) xNorm = read_tabulated_data_without_header(pathInSamples) # xNorm = np.transpose(xNorm) learnData = np.transpose(learnData) WemptyMax = 3500.0 CnbMin = 0.0001 ClbMax = -0.05 SMmin = -0.05 SMmax = 0.10 combatRadiusMin = 1000.0 RCmin = 125.0 VmaxMin = 0.90 # Mach LD = RbfMod(xNorm, learnData[0]) We = RbfMod(xNorm, learnData[1]) _Cnb = RbfMod(xNorm, (learnData[2]) * 1e3) Clb = RbfMod(xNorm, learnData[3]) _SM = RbfMod(xNorm, learnData[4] * 1e3) Rcombat = RbfMod(xNorm, learnData[5]) RC = RbfMod(xNorm, learnData[6]) Vmax = RbfMod(xNorm, learnData[7]) Cnb = lambda x: _Cnb(x) / 1e3 SM = lambda x: _SM(x) / 1e3 bnds = np.ones([9, 2]) bnds[:, 0] = -bnds[:, 0] bnds[8, 0] = 0 bnds[7, 0] = 0 bnds = tuple(bnds) f = lambda x: -LD(x) g1 = lambda x: WemptyMax - We(x) g2 = lambda x: (Cnb(x) - CnbMin) * 1e3 g3 = lambda x: ClbMax - Clb(x) g4 = lambda x: SMmax - SM(x) g5 = lambda x: SM(x) - SMmin g6 = lambda x: Rcombat(x) / 1e3 - combatRadiusMin g7 = lambda x: RC(x) - RCmin g8 = lambda x: Vmax(x) - VmaxMin cnstr = ( {"type": "ineq", "fun": g1}, {"type": "ineq", "fun": g2}, {"type": "ineq", "fun": g3}, {"type": "ineq", "fun": g4}, {"type": "ineq", "fun": g5}, {"type": "ineq", "fun": g6}, {"type": "ineq", "fun": g7}, {"type": "ineq", "fun": g8}, ) x0 = np.zeros(9) rslt = minimize(f, x0, method="SLSQP", constraints=cnstr, bounds=bnds) print rslt rslt2 = minimize(f, x0, constraints=cnstr, bounds=bnds, options={"maxiter": 10000}) print rslt2 xopt = rslt.x print g1(xopt), We(xopt) print g2(xopt), Cnb(xopt) print g3(xopt), Clb(xopt) print g4(xopt), SM(xopt) print g5(xopt), SM(xopt) print g6(xopt), Rcombat(xopt) print g7(xopt), RC(xopt) print g8(xopt), Vmax(xopt) ac = DesignFormulation() ac.load_xls("Baseline1") ac.setup() ac.set_x(ac.x0) x2dBaseline = ac.wing.x2d y2dBaseline = ac.wing.y2d print "Baseline" print ac.analysisData print "--->" normalize = Normalization(ac.lb, ac.ub) xoptDenorm = normalize.denormalize(xopt) print xoptDenorm ac.set_x(xoptDenorm) x2dOptimum = ac.wing.x2d y2dOptimum = ac.wing.y2d print ac.analysisData, "\n---" print (ac.analysisData[0] - LD(xopt)) / ac.analysisData[0] print (ac.analysisData[1] - We(xopt)) / ac.analysisData[1] print (ac.analysisData[2] - Cnb(xopt)) / ac.analysisData[2] print (ac.analysisData[3] - Clb(xopt)) / ac.analysisData[3] print (ac.analysisData[4] - SM(xopt)) / ac.analysisData[4] print (ac.analysisData[5] - Rcombat(xopt)) / ac.analysisData[5] print (ac.analysisData[6] - RC(xopt)) / ac.analysisData[6] print (ac.analysisData[7] - Vmax(xopt)) / ac.analysisData[7] plt.figure() plt.hold(True) plt.plot(x2dBaseline, y2dBaseline, "r-") plt.plot(x2dOptimum, y2dOptimum, "k-") plt.legend(["Baseline", "Low-fi Optimum"]) plt.show() ac.display()
class DesignFormulation(design.Design): def setup(self): self.neval = 0 self.lb = np.array([40, 40, 6.00, 3.00, 0.5, 1.00, 3.000, -4, -4]) #self.lb = np.array([40, 40, 6.00, 3.00, 0.5, 1.00, 3.000, -4, -4]) self.ub = np.array([60, 60, 7.50, 5.25, 1.8, 1.80, 3.200, 0, 0]) #self.ub = np.array([60, 60, 7.50, 5.25, 1.8, 1.80, 3.200, 0, 0]) self.x0 = np.array([55, 55, 6.91, 4.15, 1.1, 1.44, 3.115, 0, -3]) self.norm = Normalization(self.lb, self.ub,-1.,1.) self.xCurrent = np.zeros(len(self.x0)) self.x0norm = self.norm.normalize(self.x0) #self.bnds = np.array([[l,u] for l,u in zip(self.lb,self.ub)]) # --- constraints --- self.WemptyMax = 3500.0 self.CnbMin = 0.003 self.ClbMax = -0.075 #-6.0e-4 self.SMmin = 0.05 self.SMmax = 0.15 self.combatRadiusMin= 750.0 self.RCmin = 125.0 self.VmaxMin = 0.90 # Mach self.minSectionLen = 1.4*self.propulsion.engine.length self.CmdeReq = -0.01 # baseline -0.00866 self.alphaTrimMax = 8.0+1e-4 # deg self.elevTrimMax = 20.0 self.elevTrimMin = -20.0 self.gvfmAero = True self.Vtrim = 65.0 # 135kts: assumed value self._load_rbf_models() # --- payload --- self.SDB = MassComponent('drop payload', 1132.0, np.array([4.5, 0.0, 0.12])) # --- misc --- self.analysisData = np.zeros(10) # self._upd_approximation() # --- initial data --- self.Wf = self.mass.fuel.mass self.CGf = self.mass.fuel.coords self.engineOffset = 0.75*self.propulsion.engine.length self.payloadOffset = 0.75*self.propulsion.engine.length self.fileFeasible = 'ucav_feasible.txt' self.set_x(self.x0norm) def get_bounds(self,x0,c1=0.3): n = len(self.x0norm) #c1 = 0.25 treshold = 0.005 xUold = np.ones(n) xLold = -np.ones(n) xUnew = np.zeros(n) xLnew = np.zeros(n) u = xUold-x0 l = x0 - xLold delta = np.zeros(len(self.x0)) i=0 for _l,_u in zip(l,u): delta[i] = min([_l,_u])*c1 if delta[i]<treshold: d = c1*(xUold[i]-xLold[i]) if _u<treshold: xLnew[i] = x0[i] - d xUnew[i] = x0[i] else: xLnew[i] = x0[i] xUnew[i] = x0[i] + d else: xUnew[i] = x0[i] + delta[i] xLnew[i] = x0[i] - delta[i] print '%.4f\t%.4f\t%.4f'%(_l,_u,delta[i]) i += 1 bounds = np.transpose(np.vstack([xLnew,xUnew])) return bounds # # def _upd_approximation(self): # pathIn = 'design_out4.txt' # pathInSamples = 'DOE_LHS250_FFD2_3_3.txt' # learnData = read_tabulated_data_without_header(pathIn) # xNorm = read_tabulated_data_without_header(pathInSamples) # learnData = np.transpose(learnData) # _Cnb = RbfMod(xNorm, (learnData[2])*1e3) # self.Cnb = lambda x: _Cnb(x)/1e3 # self.Clb = RbfMod(xNorm, learnData[3]) # self.LD = RbfMod(xNorm, learnData[0]) def set_x(self,xnorm,fullUpdate=True): """ To minimize function evaluation, this function re-calculates analysis if new x is given, otherwise precalculated results are used. """ self.xcurNorm = xnorm x = self.norm.denormalize(xnorm) try: self._upd_configuration(x) self._upd_analysis(xnorm,fullUpdate) except: print x print xnorm self.display_2d() self._upd_configuration(x) print 'Error occured' self._upd_analysis(xnorm,fullUpdate) # self.analysisData[0] = 0.0 # self.analysisData[1:] = -np.ones(len(self.analysisData)-1)*100.0 # raise ValueError def _upd_configuration(self,x): sweep1 = x[0] sweep2 = x[1] chord1 = x[2] chord2 = x[3] chord3 = x[4] span1 = x[5] span2 = x[6] twist1 = x[7] twist2 = x[8] self.set_spans([span1,span2]) self.set_sweep_angles([sweep1, sweep2]) self.set_chords([chord1,chord2,chord3]) self.set_twist_by_index(twist1,0) self.set_twist_by_index(twist2,1) self._set_engine_location() self._update_mass() def _set_engine_location(self): engineDiameter = self.propulsion.engine.diameter x,l = self.wing.get_max_segment_length(engineDiameter) self.maxSectionLength = l cgNew = x+self.engineOffset cgNew2 = x+self.payloadOffset #self.mass.empty.update_item_cg('engine',cgNew,0,0) #self.set_engine_cg(cgNew,0,0) self.SDB = MassComponent('drop payload', 1132.0, np.array([cgNew2, 0.0, 0.12])) #self.mass.payload.update_item_cg('drop payload',cgNew,.0,.0) def _upd_analysis(self,xnorm,fullUpdate): #self._update_mass() self._upd_drag() alt = self.designGoals.cruiseAltitude aero = self.get_aero_single_point(0.7,1e4,2.0) self.analysisData[0] = aero.LD if fullUpdate: # mission self.mass.set_fuel_mass(self.Wf, self.CGf) if not self.mass.payload.item_exists(self.SDB.name): self.mass.payload.add_component(self.SDB) self.mass.set_fuel_mass(self.Wf,self.CGf) self.combatRadius = run_mission_B15(self) /1e3 # performance self.mass.set_fuel_mass(self.Wf,self.CGf) if not self.mass.payload.item_exists(self.SDB.name): self.mass.payload.add_component(self.SDB) slf = SteadyLevelFlight(self) self.analysisData[1] = self.mass.empty() self.analysisData[2] = aero.derivs.Cnb self.analysisData[3] = aero.derivs.Clb #self.aero.derivs.Clb self.analysisData[4] = aero.SM self.analysisData[5] = self.combatRadius self.analysisData[7] = slf.run_max_TAS(alt).Mach aeroTrim = self.get_aero_trim(self.Vtrim, 0.0) self.analysisData[8] = aeroTrim.elevator self.analysisData[9] = aeroTrim.alpha self.mass.set_fuel_mass(self.Wf,self.CGf) if not self.mass.payload.item_exists(self.SDB.name): self.mass.payload.add_component(self.SDB) clm = ClimbDescent(self) self.analysisData[6] = clm.run_max_climb_rate(0).climbRate print self.analysisData[0] def f(self,x): self.neval += 1 self.set_x(x,False) return -self.analysisData[0] def g(self,x): self.set_x(x,True) _x = self.norm.denormalize(x) g = np.zeros(12) g[0] = self.WemptyMax - self.analysisData[1] g[1] = self.analysisData[2] - self.CnbMin g[2] = self.ClbMax - self.analysisData[3] g[3] = self.SMmax - self.analysisData[4] g[4] = self.analysisData[4] - self.SMmin g[5] = self.analysisData[5] - self.combatRadiusMin g[6] = self.analysisData[6] - self.RCmin g[7] = self.analysisData[7] - self.VmaxMin g[8] = self.maxSectionLength - self.minSectionLen g[9] = self.analysisData[8] - self.elevTrimMin g[10] = _x[0] - _x[1] g[11] = self.alphaTrimMax - self.analysisData[9] print g>0 out = '' for v in g: out += '%.0e '%v print out print '%.4f\t%.4f\t%.4f'%(self.analysisData[1],self.analysisData[5],self.analysisData[8]) g[0] *= 1e-2 g[1] *= 1e4 g[2] *= 1e3 g[3] *= 1e3 g[4] *= 1e3 g[5] *= 1e-1 g[6] *= 1e-1 g[7] *= 1e2 g[9] *= 10. g[11] *= 10 return g*1000. def get_aero_single_point(self,velocity,altitude,alpha=0.0,beta=0.0, elevator=0.0,mass=None,cg=None,inertia=None,CD0=None): aero = super(DesignFormulation,self).get_aero_single_point(velocity,altitude,alpha,beta,elevator,mass,cg,inertia,CD0) if self.gvfmAero: sys.stdout.write('GVFM add> ') xcurrent = self.xcurNorm LDold = aero.coef.CL/(aero.coef.CD-self.CD0rbf(xcurrent)) aero.coef.CL += self.CLrbf(xcurrent) aero.coef.CD += self.CDrbf(xcurrent)-self.CD0rbf(xcurrent) aero.LD = LDold + self.LDrbf(xcurrent) aero.SM += self.SMrbf(xcurrent) aero.CD0 += self.CD0rbf(xcurrent) aero.k += self.krbf(xcurrent) return aero def update_aero_trim(self,velocity,altitude,CmTrim=0.0,loadFactor=1.0, mass=None,cg=None,inertia=None,CD0=None): super(DesignFormulation,self).update_aero_trim(velocity,altitude,CmTrim,loadFactor,mass,cg,inertia,CD0) if self.gvfmAero: xcurrent = self.xcurNorm #self.aeroResults.CD0 += self.CD0rbf(xcurrent) self.aeroResults.k += self.krbf(xcurrent) def get_drag(self,velocity=None,altitude=None): cd0 = super(DesignFormulation,self).get_drag(velocity,altitude) if self.gvfmAero: return cd0 + self.CD0rbf(self.xcurNorm) else: return cd0 def _load_rbf_models(self,DOEpath=None,rsltPath=None): if DOEpath==None: DOEpath = r'D:\1. Current work\2014 - UAV performance code\Results\DOE\LHS_dvar9_sample24.txt' if rsltPath==None: rsltPath = r'D:\1. Current work\2014 - UAV performance code\Results\DOE\CFDresults.txt' dCD0 = 0.0005 xDOE = read_tabulated_data_without_header(DOEpath) fDOE = read_tabulated_data_without_header(rsltPath,1) self.CLrbf = RbfMod(xDOE, fDOE[:,4]-fDOE[:,13]) self.CDrbf = RbfMod(xDOE, fDOE[:,5]-fDOE[:,14]) self.CD0rbf= RbfMod(xDOE, fDOE[:,11]-fDOE[:,19]+dCD0) self.krbf = RbfMod(xDOE, fDOE[:,12]-fDOE[:,20]) self.SMrbf = RbfMod(xDOE, fDOE[:,10]-fDOE[:,18],0.5) self.LDrbf = RbfMod(xDOE, fDOE[:,7] -fDOE[:,15]) self._xdoe = xDOE def show_results(self): print '{0:10}={1:10.4f}'.format('LD',self.analysisData[0]) print '{0:10}={1:10.4f}'.format('SM',self.analysisData[4]) print '{0:10}={1:10.4f}'.format('Cnb',self.analysisData[2]) print '{0:10}={1:10.4f}'.format('Clb',self.analysisData[3]) print '{0:10}={1:10.4f}'.format('elev',self.analysisData[8]) print '{0:10}={1:10.4f}'.format('alpha',self.analysisData[9]) print '{0:10}={1:10.4f}'.format('We',self.analysisData[1]) print '{0:10}={1:10.4f}'.format('Rcombat',self.analysisData[5]) print '{0:10}={1:10.4f}'.format('ROC',self.analysisData[6]) print '{0:10}={1:10.4f}'.format('Mmax',self.analysisData[7])