Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

All published worksheets from http://sagenb.org

Path: pub / 1-101 / 46.sagews
Views: 168738
Image: ubuntu2004
################################################ # TITLE: VORTEX LATTICE METHOD FOR PLANAR WING # # AUTHOR: PRASHANT AGRAWAL # # ROLL NUMBER: 06D04009 # ################################################ import matplotlib matplotlib.use('TkAgg') from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from math import pi,sin,cos,tan,sqrt from numpy import matrix from numpy import linalg from pylab import * from Tkinter import * import tkMessageBox from os import system b,theta,root,tip,N = 0.0,0.0,0.0,0.0,0 #Wing parameters declared as global variables #### CREATING THE GRAPHICAL WINDOW AND DECLARING VARIOUS FRAME, LABEL, ENTRY AND BUTTON OBJECTS #### top = Tk() top.geometry('+550+320') F = Frame(top,relief = 'flat',border=5) F .grid(sticky='n') F.master.title("Vortex Lattice Method") #Declaring various objects of the GUI. See naming convention in createwidgets() for better clarity eSpan,eSweep,eRootChord,eTipChord,eNo,fParams,bSolveBnS,bSolveCP,fSolve,bSolve,fOutput,bClear,lLabel,fWing = Entry(),Entry(),Entry(),Entry(),Entry(),Frame(),Button(),Button(),Frame(),Button(),Frame(),Button(),Label(),Frame() bSolveLabel = "Customize wing parameters" bCtrl,thetaCtrl,rootCtrl,tipCtrl,NCtrl = StringVar(F),StringVar(F),StringVar(F),StringVar(F),StringVar(F) #Control variables of various entries,i.e., when the values of #these variables change, displays on the entry also change #### DEFINING THE MAIN FUNCTION #### def main(): """ THIS IS THE MAIN APPLICATION LOGIC OF THE PROGRAM. WHAT FOLLOWS AFTER THIS FUNCTION IS JUST A GRAPHICAL USER INTERFACE TO IMPLEMENT IT. """ def w(m,n): """ Returns downwash velocity at control point m due to panel n on only one side of the wing. Note that, though, the expression for w(m,n) involves a factor of Tau/(4*pi), this function doesn't take this factor into account. It is incorporated in the right hand side of the system of equations to be solved. """ term1 = 1.0/((x[m]-x1[n])*(y[m]-y2[n]) - (x[m]-x2[n])*(y[m]-y1[n])) term2 = ((x2[n]-x1[n])*(x[m]-x1[n]) + (y2[n]-y1[n])*(y[m]-y1[n]))/sqrt(pow((x[m]-x1[n]),2) + pow((y[m]-y1[n]),2)) term3 = ((x2[n]-x1[n])*(x[m]-x2[n]) + (y2[n]-y1[n])*(y[m]-y2[n]))/sqrt(pow((x[m]-x2[n]),2) + pow((y[m]-y2[n]),2)) term4 = (1.0/(y1[n]-y[m]))*(1.0 + (x[m]-x1[n])/sqrt(pow((x[m]-x1[n]),2) + pow((y[m]-y1[n]),2))) term5 = (1.0/(y2[n]-y[m]))*(1.0 + (x[m]-x2[n])/sqrt(pow((x[m]-x2[n]),2) + pow((y[m]-y2[n]),2))) result = (term1*(term2-term3)) + term4 - term5 #print "w(",m,",",n,") = ", result return result global theta #### DEFINING VARIOUS PARAMETERS #### AR,theta,S,delY = 2*b/(root+tip),theta*pi/180,(root+tip)*b/2,b/(2*N) V_inf = 1.0/(4*pi*b) # alpha = 1 #in radians # Any value could be supplied for these things. They don't affect the final answer. rho_inf = 16*pi # #### WRITING COORDINATES OF CONTROL POINTS AND ENDS OF BOUND VORTICES #### y,y1,y2,x,x1,x2 = [],[],[],[],[],[] c = lambda y:(2*(tip-root)/b)*y + root # Returns chord length at a given point y for n in range(N): y1 = y1 + [n*delY] y2 = y2 + [delY + n*delY] y = y + [delY/2 + n*delY] x1 = x1 + [y1[n]*tan(theta) + c(y1[n])/4] x2 = x2 + [y2[n]*tan(theta) + c(y2[n])/4] x = x + [((x1[n] + x2[n])/2) + c((y1[n]+y2[n])/2)/2] #print n, x[n],y[n],x1[n],y1[n],x2[n],y2[n] #### CREATING MATRIX AX=B AND SOLVING FOR X #### #ws,wp denote downwash due to starboard and port wing respectively ws,wp,A,B,Tau = [],[],[],[],[] #A, B denote coefficient matrix of the system to be solved, and Tau #denotes the solution of the system A*Tau = B for m in range(N): A = A + [[]] B = B + [-4*pi*V_inf*alpha] ws = ws + [[]] wp = wp + [[]] for n in range(N): ws[m] = ws[m] + [w(m,n)] y1[n],y2[n] = -y1[n],-y2[n] #to account for panels of the port wing wp[m] = wp[m] + [w(m,n)] A[m] = A[m] + [ws[m][n]-wp[m][n]] y1[n],y2[n] = -y1[n],-y2[n] #to again consider the starboard panels in the first place for the next iteration #print A[m][n], #print " = ",B[m] LHS = matrix(A) # RHS = matrix(B).T #RHS = Transpose(B) # solving the created system of equations Tau = linalg.solve(LHS,RHS) # #print "Tau =", "\n",Tau #### CALCULATING LIFT USING KUTTA-JOUKOWSKI'S THEOREM #### L = 0 #L denotes Lift for n in range(len(Tau)): L = L + 2*rho_inf*V_inf*Tau[n]*delY L = norm(L) #L calculated in the above loop is a matrix of single element #print "L =", L #### CALCULATING LIFT COEFFICIENT #### q_inf = (1.0/2)*(rho_inf)*(V_inf)*(V_inf) C_L = L/(q_inf*S) #print "C_L =", C_L #### CALCULATING LIFT SLOPE #### #deg = lambda theta_in_rads: theta_in_rads*180/pi C_Lalpha = C_L/alpha #print "Lift Slope (C_L_alpha) =", round(C_Lalpha,4), "per radian" #### PLOTTING SECTIONAL LIFT COEFFICIENT VERSUS SEMI-SPAN OF THE WING #### y_for_plotting = arange(delY/2.0,b/2 + delY/2.0,delY) C_l_for_plotting = [] for n in range(N): C_l_for_plotting = C_l_for_plotting + [2*norm(Tau[n])/(V_inf*c(y_for_plotting[n]))] fig = figure(figsize=(8,6), dpi=80) plot(y_for_plotting,C_l_for_plotting) xlabel("Y ALONG THE SPANWISE DIRECTION") ylabel("SECTIONAL LIFT COEFFICIENT") title("VARIATION OF SECTIONAL LIFT COEFFICIENT ALONG SEMI-SPAN OF THE WING") top.wm_state('zoomed') # Maximize the application window draw_wing() # draw the wing shape display_output(round(C_Lalpha,4),fig) # display the output ############################################################### # APPLICATION LOGIC OF PROGRAM ENDED HERE. BELOW IS THE CODE # # FOR THE DESIGN OF THE GRAPHICAL USER INTERFACE TO IMPLEMENT # # ABOVE APPLICATION LOGIC. # ############################################################### #### GRAPHICALLY DRAWING THE WING #### def draw_wing(): """ Displays the semi-span view of the wing using the parameters supplied to main. """ fWing = Frame(top) #create a new frame to display the wing lWing = Label(fWing,text = "Wing Shape (Semi-span View)",font=('Helvetica',16,'bold','underline')) lWing.grid(padx=10,pady=10,sticky='n') lCanvas = Canvas(fWing,relief='raised',bg = 'gray',border=5,height = 330) # the wing is drawn using this canvas ## Appropriate scaling and drawing of wing done below ## width = int(lCanvas.cget('width')) height = int(lCanvas.cget('height')) w,h = width-60,height-30 xmax,xmin = max([0.0,b/2.0]),min([0.0,b/2.0]) ymax,ymin = max([0.0,tan(theta)*b/2.0,tan(theta)*b/2.0 + tip,root]),min([0.0,tan(theta)*b/2.0,tan(theta)*b/2.0 + tip,root]) xscale = lambda x: 45 + (w/(xmax-xmin))*x yscale = lambda y: 15 + (h/(ymax-ymin))*y lCanvas.create_polygon(xscale(0.0),yscale(0.0),xscale(b/2.0),yscale(tan(theta)*b/2.0),xscale(b/2.0),yscale(tan(theta)*b/2.0 + tip),xscale(0.0),yscale(root),fill='blue') ## Wing drawn. Sketching the axes and ticks ## lCanvas.create_line(45,15+h,45+w,15+h) # draw the x-axis lCanvas.create_line(45,15,45,15+h) # draw the y-axis for i in range(10): xLabel = round((xmin + i*(xmax-xmin)/9.0),2) x = xscale(xmin + i * (xmax-xmin)/9.0) lCanvas.create_line(x,15+h,x,15+h+5) # draw ticks on x-axis lCanvas.create_text(x,15+h+7, text=str(xLabel), anchor='n') # write caption corresponding to each tick for i in range(10): yCaption = round((ymin + i * (ymax-ymin)/9),2) y = yscale(ymin + i * (ymax-ymin)/9) lCanvas.create_line(45,y,40,y) # draw ticks on y-axis lCanvas.create_text(25,y, text=str(yCaption), anchor='n') # write caption on each tick lCanvas.grid(sticky='n') fWing.grid(row=1,column=0,sticky='n') #### DISPLAYING GRAPH AND LIFT SLOPE #### def display_output(answer,fig): """ Displays: 1. Value of Lift Slope C_Lalpha as calculated in main, and 2. Plot of Variation of Sectional Lift Coefficient along semi-span of the wing """ fOutput = Frame(top) #create a new frame to display the output lOutput = Label(fOutput,text = "Output",font=('Helvetica',16,'bold','underline')) lOutput.grid(padx = 10,pady = 10,sticky='n') out = "Lift Slope (C_L_alpha) = " + str(answer) + " per radian." lAnswer = Label(fOutput,text = out,font=('Helvetica',12,'bold') ) #lAnswer is a label to show the Lift Slope lAnswer .grid(padx = 10,pady = 10,sticky='n') canvas = FigureCanvasTkAgg(fig, master=fOutput) canvas._tkcanvas.config(height=600,width=700,relief='raised') canvas._tkcanvas.grid() fOutput.grid(row=0,column =1,sticky='nesw',rowspan=2) #### DEFINING WING PARAMETERS AND CALLING MAIN FUNCTION #### def define_params(span=0.0,sweep=0.0,rootChord=0.0,tipChord=0.0,No=0,inp=0): """ Defines input parameters b,theta,root,tip,N as according to: 1. "Solve Bertin and Smith problem" button, 2. "Solve Assignment problem" button 3. "Customize wing parameters" button Note that, if user selects the "Customize wing parameters" button, this function opens a window that allows user to enter various wing parameters and internally converts the above button to a "Solve" button. On clicking the "Solve" button then, this function is again called and this time it calls the main function with parameters as specified by the user. Otherwise, it calls the main function with pre-defined parameters (hard-coded in the program) to directly display the output. """ global b,theta,root,tip,N,fWing global bSolveLabel,bSolveBnS,bSolveCP,fSolve,bSolve,bClear b,theta,root,tip,N = span,sweep,rootChord,tipChord,No errorfound = False if not bSolveLabel=="Solve": """ If state of the button is not "Solve", convert it to "Solve" for further interaction. """ bSolve.config(text=" Solve ") bSolveLabel = "Solve" top.geometry('+550+230') #Re-defining position of window on screen else: if inp==1: """If button 3 (as defined in _doc_ string above) is clicked, re-define all parameters as specified by user """ try: b = float(eSpan.get()) theta = float(eSweep.get()) root = float(eRootChord.get()) tip = float(eTipChord.get()) N = int(eNo.get()) except ValueError: """Raises an error message if user inputs bad values for the parameters. It mostly catches the TypeError""" errorfound = True tkMessageBox.showwarning(title = "Error!", message="Invalid input.") if not errorfound: bCtrl.set(str(b)) # Updating display on the entries thetaCtrl.set(str(theta)) # according to current parameters of rootCtrl.set(str(root)) # the problem either directly entered tipCtrl.set(str(tip)) # or by clicking on NCtrl.set(str(N)) # buttons 1 or 2 #try: top.geometry('+60+3') main() #CALL TO THE MAIN FUNCTION #except Exception: # """If user has specified values which raise ZeroDivisionError or similar in main""" # errorfound = True # tkMessageBox.showwarning(title = "Error!", message="Invalid input.") fSolve.grid_forget() # fParams .grid(sticky='nesw') # Displaying entries for entering various parameters fSolve .grid(sticky='s') # bSolve .grid(padx = 10,pady = 10,columnspan = 1,sticky='w') # bClear = Button(fSolve,text = " Clear all ",command = evClear,font=('Helvetica',10,'bold')) # bClear .grid(padx = 10,pady = 10,column = 1, row = 0,sticky='e') # Create and show a new button named "Clear all" #### COMMAND FUNCTIONS OF VARIOUS BUTTONS #### def evSolve(): """ Command function of "Customize wing parameters" button and/or "Solve" button, depending on the state of the button. """ define_params(inp=1) def evSolveKey(event): """To bind pressing of "return" key with clicking on "Solve" button.""" evSolve() def evSolveBnS(): """ Command function of "Solve Bertin and Smith problem" button. """ global bSolveLabel,bSolve # bSolve.config(text=" Solve ") # When this button is clicked, button 3 will change its label to "Solve" bSolveLabel = "Solve" # define_params(span=1.0,sweep=45,rootChord=0.2,tipChord=0.2,No=4) #calling define_params with pre-specified inputs def evSolveCP(): """ Command function of "Solve Assignment problem" button. Exactly same as evSolveBnS function. """ global bSolveLabel,bSolve bSolve.config(text=" Solve ") bSolveLabel = "Solve" define_params(span=2.828,sweep=53.54,rootChord=1.5,tipChord=0.5,No=60) def evClear(): """ Command function of "Clear all" button. Clears all Entry widgets. """ bCtrl.set("") thetaCtrl.set("") rootCtrl.set("") tipCtrl.set("") NCtrl.set("") #### CREATION OF VARIOUS WIDGETS #### def createwidgets(): """ Creates various widgets on the GUI to interact with the user. The naming convention followed (for representing various labels, buttons, entries etc.) is described below: 1. A leading small 'l' to represent a Label widget. 2. A leading small 'f' to represent a Frame widget. 3. A leading small 'e' to represent an Entry widget. 4. A leading small 'b' to represent a Button widget. Following these leading letters comes the title of widget. """ global eSpan,eSweep,eRootChord,eTipChord,eNo,fParams,fSolve,bSolveLabel,bSolveBnS,bSolveCP,bSolve fParams = Frame(F) # Frame to contain widgets related to inputting of various parameters lInput = Label(fParams,text = "Wing Parameters",font=('Helvetica',16,'bold','underline')) # lInput.grid(padx = 10,pady = 10,columnspan=2,sticky='n') # A label to show the title "Wing parameters" lSpan = Label(fParams, text = "Span",font=('Helvetica',10,'bold')) # Label reading "Span" lSpan .grid(padx = 10,pady = 10,sticky='w') # Add it to the grid, to make it visible when fParams is visible eSpan = Entry(fParams,textvariable=bCtrl,font=('Helvetica',10,'bold') ) # Entry widget to take value of span from user eSpan.bind("<Return>",evSolveKey) # To enable "return" key support for "Solve" button eSpan .grid(column=1,row=1,padx = 10,pady = 10,sticky='e') # Add it to the grid, to make it visible when fParams is visible lSweep = Label(fParams, text = "Sweep_LE (in deg)",font=('Helvetica',10,'bold'))# lSweep .grid(padx = 10,pady = 10,sticky='w') # eSweep = Entry(fParams,textvariable=thetaCtrl ,font=('Helvetica',10,'bold')) # Same as "Span" eSweep.bind("<Return>",evSolveKey) # eSweep .grid(column=1,row=2,padx = 10,pady = 10,sticky='e') # lRootChord = Label(fParams, text = "Root Chord" ,font=('Helvetica',10,'bold')) # lRootChord .grid(padx = 10,pady = 10,sticky='w') # eRootChord = Entry(fParams,textvariable=rootCtrl ,font=('Helvetica',10,'bold')) # Same as "Span" eRootChord.bind("<Return>",evSolveKey) # eRootChord .grid(column=1,row=3,padx = 10,pady = 10,sticky='e') # lTipChord = Label(fParams, text = "Tip Chord" ,font=('Helvetica',10,'bold')) # lTipChord .grid(padx = 10,pady = 10,sticky='w') # eTipChord = Entry(fParams,textvariable=tipCtrl ,font=('Helvetica',10,'bold')) # Same as "Span" eTipChord.bind("<Return>",evSolveKey) # eTipChord .grid(column=1,row=4,padx = 10,pady = 10 ,sticky='e') # lNo = Label(fParams, text = "Number of Lattices" ,font=('Helvetica',10,'bold')) # lNo .grid(padx = 10,pady = 10,sticky='w') # eNo = Entry(fParams,textvariable=NCtrl ,font=('Helvetica',10,'bold')) # Same as "Span" eNo.bind("<Return>",evSolveKey) # eNo .grid(column=1,row=5,padx = 10,pady = 10,sticky='e') # fSolve = Frame(F ) # Frame to contain all the buttons for solving, plus the "Clear all" button fSolve .grid(sticky='nesw') # Make it visible bSolve = Button(fSolve, text = "Customize wing\nparameters", command = evSolve ,font=('Helvetica',10,'bold')) # Button reading "Customize wing parameters" bSolve .grid(padx = 10,pady = 10,columnspan = 2,sticky='n') # Add it to the grid, to make it visible bSolveBnS = Button(fSolve,text = "Solve Bertin and\nSmith problem",command = evSolveBnS ,font=('Helvetica',10,'bold')) # Same as bSolve bSolveBnS .grid(padx = 10,pady = 10,sticky='sw') # bSolveCP = Button(fSolve,text = "Solve Assignment\nProblem",command = evSolveCP ,font=('Helvetica',10,'bold')) # Same as bSolve bSolveCP .grid(column=1,row = 1,padx = 10,pady = 10,sticky='se') # createwidgets() # create the widgets #### ENSURING THAT WIDGETS RETAIN SAME PROPORTION ON RESIZING THE WINDOWS #### def configure(): top.columnconfigure(0,weight=1) top.columnconfigure(1,weight=2) top.rowconfigure(0,weight=1) top.rowconfigure(1,weight=1) F.columnconfigure(0,weight=1) F.rowconfigure(0,weight=2) F.rowconfigure(1,weight=1) fParams.columnconfigure(0,weight=1) fParams.columnconfigure(1,weight=1) fParams.rowconfigure(0,weight=1) fParams.rowconfigure(1,weight=1) fParams.rowconfigure(2,weight=1) fParams.rowconfigure(3,weight=1) fParams.rowconfigure(4,weight=1) fParams.rowconfigure(5,weight=1) fSolve.columnconfigure(0,weight=1) fSolve.columnconfigure(1,weight=1) fSolve.rowconfigure(0,weight=1) fSolve.rowconfigure(1,weight=1) fOutput.columnconfigure(0,weight=1) fOutput.rowconfigure(0,weight=1) fOutput.rowconfigure(1,weight=1) fOutput.rowconfigure(2,weight=4) configure() #### START THE APPLICATION'S MAIN LOOP, WAITING FOR KEYBOARD AND MOUSE EVENTS #### top.mainloop()
Traceback (most recent call last): from math import pi,sin,cos,tan,sqrt File "/home/sage/sage/local/lib/python2.5/site-packages/matplotlib/backends/backend_tkagg.py", line 7, in <module> import Tkinter as Tk, FileDialog File "/home/sage/sage/local/lib/python2.5/lib-tk/Tkinter.py", line 38, in <module> import _tkinter # If this fails your Python may not be configured for Tk ImportError: No module named _tkinter