This little notebook compares viiflow and XFOIL runtimes for different panel densities of the S805 airfoil. It is not 100% fair, because
Note: These results were generated with a PC with a AMD Phenom 2 X6 1055T processor on a windows 10 64bit OS with numpy built with Intel MKL and the xfoil 6.99 binary version.
import os # For calling xfoil ''' Numpy (with MKL in this case) might want to use multiple threads to do linalg.solve. Solving 150x150->500x500 matrices with multiple cores it not super efficient, especially if your processor uses a higher clock if only one core is used. And even if it would be faster with multiple cores, it would not be fair to compare these results with single-core using XFOIL. ''' os.environ["OMP_NUM_THREADS"] = "1" # viiflow imports import viiflow as vf import viiflowtools.vf_tools as vft import numpy as np import time # For timing # For plotting at the end import matplotlib.pyplot as plt %matplotlib inline %config InlineBackend.figure_format = 'svg' import matplotlib
NVEC = np.arange(100,500,10) # Panel densities to compare # AOA Sweep AOA0 = -5 AOAE = 16 DAOA = .5 RE = 1e6 # Reynolds Number maxiter = 50 # maximum iterations for both methods FOIL = "S805.dat" # Container for results elapsedXF= elapsedVF= for N in NVEC: ## Build correct file with N panels by XFOIL, compare both solvers with this file # Make XFOIL command com = "load %s\nPPAR\nN %u\n\n\nsave tmpfoil.dat\ny\n"%(FOIL,N) # Save Xfoil Command with open('xfcom.inp', 'w') as f: print(com,file=f) f.close() # Run XFOIL os.system("xfoil < xfcom.inp > xf.out") ## XFOIL # Make XFOIL command com = "load %s\nOPER\nv %u\nITER %u\nASEQ %f %f %f\n\nquit\n"%('tmpfoil.dat',RE,maxiter,AOA0,AOAE,DAOA) #com = "load %s\nPPAR\nN %u\n\n\nOPER\nv %u\nITER %u\nASEQ %f %f %f\n\nquit\n"%(FOIL,N,RE,maxiter,AOA0,AOAE,DAOA) # Save Xfoil Command with open('xfcom.inp', 'w') as f: print(com,file=f) f.close() # Run XFOIL t = time.time() os.system("xfoil < xfcom.inp > xf.out") elapsedXF.append(time.time() - t) # Check for convergence f = open("xf.out", "r") lines = f.readlines() f.close() xf_unconverged=0 for line in lines: if line.startswith(" VISCAL: Convergence failed"): xf_unconverged+=1 ## viiflow s = vf.setup(Re=RE,Ma=0.0,Ncrit=9.0,Alpha=AOA0) s.Silent = True # Do not output residual/iterations internally s.Itermax = maxiter t = time.time() # Set-up and initialize based on inviscid panel solution # This calculates panel operator [p,bl,x] = vf.init(vft.read_selig('tmpfoil.dat'),s) vf.set_forced_transition(bl,p,[0.5],[0.5]) vf_unconverged = 0 for alpha in np.arange(AOA0,AOAE+DAOA,DAOA): # Set current alpha and set res/grad to None to tell viiflow that they are not valid s.Alpha = alpha res = None grad = None # Run viiflow [x,flag,res,_,_] = vf.iter(x,bl,p,s,res,grad) # Print if not converged if flag<=0: #print('Not converged at AL: %f' % alpha) vf_unconverged+=1 elapsedVF.append(time.time() - t) # Print comparison print("N: %u XF: %ss (%u failed) VF:%ss (%u failed)"%(N,elapsedXF[-1],xf_unconverged,elapsedVF[-1],vf_unconverged))
N: 100 XF: 1.4649670124053955s (0 failed) VF:1.8780105113983154s (0 failed) N: 110 XF: 1.3460237979888916s (0 failed) VF:1.8899648189544678s (1 failed) N: 120 XF: 1.616001844406128s (0 failed) VF:2.287841558456421s (1 failed) N: 130 XF: 2.231051445007324s (1 failed) VF:2.0320303440093994s (0 failed) N: 140 XF: 2.4480011463165283s (1 failed) VF:2.2030444145202637s (0 failed) N: 150 XF: 2.682016611099243s (1 failed) VF:2.918943166732788s (1 failed) N: 160 XF: 4.464014768600464s (4 failed) VF:3.068044424057007s (1 failed) N: 170 XF: 3.8319904804229736s (1 failed) VF:3.148983955383301s (1 failed) N: 180 XF: 4.529965877532959s (1 failed) VF:4.016063213348389s (1 failed) N: 190 XF: 5.858054876327515s (1 failed) VF:3.8120663166046143s (1 failed) N: 200 XF: 8.320648908615112s (1 failed) VF:4.857321739196777s (1 failed) N: 210 XF: 7.651485443115234s (1 failed) VF:4.7580320835113525s (1 failed) N: 220 XF: 9.569605112075806s (2 failed) VF:5.266568660736084s (1 failed) N: 230 XF: 9.881593465805054s (1 failed) VF:4.96503210067749s (0 failed) N: 240 XF: 9.89513897895813s (0 failed) VF:6.2639994621276855s (1 failed) N: 250 XF: 11.28543496131897s (1 failed) VF:6.127026081085205s (2 failed) N: 260 XF: 11.97486662864685s (1 failed) VF:7.138968467712402s (3 failed) N: 270 XF: 14.610000610351562s (2 failed) VF:6.7560131549835205s (1 failed) N: 280 XF: 16.955946445465088s (3 failed) VF:7.152999639511108s (2 failed) N: 290 XF: 14.916030883789062s (1 failed) VF:6.954985618591309s (1 failed) N: 300 XF: 13.336970567703247s (0 failed) VF:8.62898874282837s (2 failed) N: 310 XF: 15.923629999160767s (0 failed) VF:9.36094856262207s (3 failed) N: 320 XF: 21.14393639564514s (2 failed) VF:8.140997886657715s (1 failed) N: 330 XF: 17.09503436088562s (0 failed) VF:8.469033479690552s (1 failed) N: 340 XF: 27.852946519851685s (2 failed) VF:9.23200249671936s (1 failed) N: 350 XF: 15.972874164581299s (4 failed) VF:9.399247169494629s (1 failed) N: 360 XF: 29.75042223930359s (2 failed) VF:10.674961805343628s (2 failed) N: 370 XF: 32.890053272247314s (2 failed) VF:10.619025468826294s (1 failed) N: 380 XF: 29.8659348487854s (0 failed) VF:13.484004974365234s (3 failed) N: 390 XF: 41.35123872756958s (3 failed) VF:11.295965433120728s (1 failed) N: 400 XF: 42.52203321456909s (3 failed) VF:13.163064002990723s (2 failed) N: 410 XF: 39.591697454452515s (1 failed) VF:12.76315426826477s (0 failed) N: 420 XF: 37.881977558135986s (0 failed) VF:13.93502140045166s (1 failed) N: 430 XF: 64.33236360549927s (5 failed) VF:14.013046503067017s (1 failed) N: 440 XF: 69.2680275440216s (4 failed) VF:14.679842472076416s (1 failed) N: 450 XF: 50.97595524787903s (0 failed) VF:19.33501958847046s (3 failed) N: 460 XF: 56.86715316772461s (1 failed) VF:18.187987804412842s (2 failed) N: 470 XF: 72.29701685905457s (3 failed) VF:18.460018396377563s (2 failed) N: 480 XF: 83.77977252006531s (4 failed) VF:20.433030366897583s (2 failed) N: 490 XF: 77.3111047744751s (3 failed) VF:19.273021459579468s (1 failed)
matplotlib.rcParams['figure.figsize'] = [11, 6] # Make plots bigger than default n = len(elapsedVF) plt.plot(NVEC[0:n],elapsedVF,'-o') plt.plot(NVEC[0:n],elapsedXF,'-o') plt.legend(["viiflow","xfoil"]) plt.xlabel("Panels") plt.ylabel("Runtime [s]") plt.grid(1) plt.ylim([0,80]) plt.xlim([90,500]);
For less than 200 panels (NP) XFOIL is occasionally a bit faster than viiflow, and either way the runtime is similar. Above 200 panels viiflow is significantly faster. The runtime difference increases with increasing panel density. This is to be expected. XFOIL needs to solve a system of 3xNP linear equations at every Newton step, while viiflow only needs to solve a 1xNP+3xNF system (NF is the number of airfoils).