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 Ryzen 3700 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"
os.environ["MKL_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 = "S805b.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\nOPER\nv %u\nITER %u\nASEQ %f %f %f\n\nquit\n"%('tmpfoil.dat',RE,maxiter,AOA0,AOA0,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)
time.sleep(.1)
# Print comparison
print("N: %u XF: %5.5ss (%u failed) VF:%5.5ss (%u failed)"%(N,elapsedXF[-1],xf_unconverged,elapsedVF[-1],vf_unconverged))
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,30])
plt.xlim([90,500]);
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 system.