Originally Posted by
udai87
Hey, did you find a solution for your problem? I am also trying to use Xfoil via MATLAB. How do you check if your results are converged?
I did, actually! I totally forgot that you could use pipes in/out of files, so I have a Perl script generating an XFOIL "script" that gets executed. Here's the code of interest:
Code:
#!/usr/bin/perl
# xfoilwrapper.pl - Wrapper script to interact between MATLAB, XFOIL
use strict;
use warnings;
sub cleandie{
unlink $_ for qw(commands.xfoil coords.dat xfoil.def coeffs.txt);
die @_;
}
sub cleanup{
unlink $_ for qw(commands.xfoil coords.dat xfoil.def coeffs.txt);
}
my ($alfa, $Re, $Ma, $NACA, $coeff_type) = @ARGV;
# If the user wants a NACA foil, make sure it's a 4 or 5-series only.
if (defined $NACA && (length($NACA) <4 || length($NACA) >5 || $NACA =~ /\D+/)){
die "Only 4 or 5-digit series NACA foils allowed";
}
my $Re_10e6 = $Re/10**6; # Config file accepts Re/10^6 as input; need to transform it.
$Re_10e6 = sprintf("%.4f", $Re_10e6);
$Ma = sprintf("%.4f", $Ma);
#--------------------------------------------------
# Generate the coordinate files (see end of program)
#--------------------------------------------------
open my $COORDINATES, ">", "coords.dat"
or cleandie "Couldn't open coords.dat for writing: $!";
my $coords = get_coords();
print {$COORDINATES} $coords;
close $COORDINATES;
#--------------------------------------------------
# Build the config file using input $Re, $Ma
#--------------------------------------------------
my $xfoil_def = <<"EOF";
160 1.0000 0.1500 0.2000 | Npan PPanel TErat REFrat
1.0000 1.0000 1.0000 1.0000 | XrefS1 XrefS2 XrefP1 XrefP2
10.0000 0.5500 0.0150 0.8000 | Size plotAR CHsize ScrnFr
11.0000 8.5000 0.0000 0.0000 | Xpage Ypage Xmargn Ymargn
F T | Lcolor Lcursor
1.0000 -4.0000 -0.5000 | CPmax CPmin CPdel
0.0900 0.7000 0.0200 | XoffAir ScalAir BLUwt
0.0000 1.5000 0.5000 | CLmin CLmax CLdel
0.0000 0.0400 0.0100 | CDmin CDmax CDdel
-4.0000 10.0000 2.0000 | ALmin ALmax ALdel
-0.2500 0.0000 0.0500 | CMmin CMmax CMdel
1 $Ma 0.0100 | MAtype Mach Vaccel
1 $Re_10e6 9.0000 | REtype Re/10^6 Ncrit
0.1000 0.2500 | XtripT XtripB
EOF
open my $XFOIL_DEF, ">", "xfoil.def"
or cleandie "Couldn't open xfoil.def for writing: $!";
print {$XFOIL_DEF} $xfoil_def;
close $XFOIL_DEF;
# Build the XFOIL command list using $alfa and $Re.
# Start with 100 iterations; if the output result is a diverage, add 100 more iterations.
# die() the program after 1000 iterations fail.
my $numit = 100;
ITERATION:
while ($numit <= 1000){
my $command_file = defined $NACA ? <<"EOF"
y
plop
G
naca $NACA
oper
visc $Re
iter $numit
pacc
coeffs.txt
alfa $alfa
pacc
quit
EOF
: <<"EOF";
y
plop
G
oper
visc $Re
iter $numit
pacc
coeffs.txt
alfa $alfa
pacc
quit
EOF
open my $COMMANDS, ">", "commands.xfoil"
or cleandie "Couldn't open commands.xfoil for writing: $!";
print {$COMMANDS} $command_file;
close $COMMANDS;
if ($^O eq "linux" || $^O eq "darwin"){
if ($NACA){
system("xfoil <commands.xfoil >/dev/null");
}
else{
system("xfoil coords.dat <commands.xfoil >/dev/null");
}
}
else{
if ($NACA){
system('C:\xfoil\bin\xfoil.exe <commands.xfoil >nul');
}
else{
system('C:\xfoil\bin\xfoil.exe coords.dat <commands.xfoil >nul');
}
}
# Check coeffs.txt for CL and CD. If there's no numbers, divergence occurred.
open my $COEFF_FILE, "<", "coeffs.txt"
or cleandie("Couldn't open coeffs.txt for reading: $!");
while (my $line = <$COEFF_FILE>){
# CONVERAGE OCCURED! PRINT CL AND CD, RETURN TO MATLAB
if ($line =~ /(\d+[.]\d+) \s+ (\d+[.]\d+) \s+ (\d+[.]\d+)/xms){
print $coeff_type eq "lift" ? "CL=$2;\n" :
$coeff_type eq "drag" ? "CD=$3;\n" :
"CL=$2; CD=$3;\n";
cleanup();
unlink("coeffs.txt");
exit
}
}
$numit += 100;
close $COEFF_FILE;
}
# At this point we've failed to converge after 1000 iterations. Return inf to caller and let the caller deal with what to do.
cleanup();
print "CL=inf;CD=inf;\n";
sub get_coords{
my $coords = <<"EOF";
# Coordinates for your airfoil go here
EOF
return $coords;
}
And here's the MATLAB function calling this wrapper:
Code:
% get_coeffs - Get the lift and drag coefficients for an airfoil
%
% USAGE: [CL, CD] = get_coeffs(alfa, Re, Ma, [NACA])
% (r) alfa: Desired angle of attack
% (r) Re : Reynolds number
% (r) Ma : Mach number
% (s) NACA: NACA Airfoil designation. Must be a 4- or 5-digit string only.
function [CL,CD] = get_coeffs(alfa, Re, Ma, NACA)
% perl() command expects all arguments to be strings - transform into strings...
alfa = sprintf('%.5f', alfa);
Re = sprintf('%d' , Re);
Ma = sprintf('%0.5f', Ma);
% Result of the eval() command is CL and CD.
if (exist('NACA') && ~ isempty(NACA))
eval(perl('xfoilwrapper.pl', alfa, Re, Ma, NACA));
else
eval(perl('xfoilwrapper.pl', alfa, Re, Ma));
end
% In Windows, xfoilwrapper.pl fails to unlink coeffs.txt. Take care of
% it here.
if (exist('coeffs.txt'))
delete('coeffs.txt');
end
Note in the XFOIL wrapper that if divergence occurs, I return CL=inf, CD=inf, and these will be what the MATLAB function returns as well. So you need to check your return vals and have some kind of error catching in place. If I generate CL/CD data and there's holes in it (inf's), I kick the holes out and perform a spline interpolation to fill those holes back in:
Code:
if (y_of_interest(i) == inf)
y_of_interest(i) = fill_gaps(x_of_interest, y_of_interest, i);
end
function yy = fill_gap(x,y,i)
y_interp = [y(1:i-1) y(i+1:length(x))];
x_interp = [x(1:i-1) x(i+1:length(x))];
yy = interp1(x_interp, y_interp, x(i), 'spline');
end
Hope this helps!
Bookmarks