Skip to content
Snippets Groups Projects
Verified Commit fb69c2db authored by Thomas Lambert's avatar Thomas Lambert :helicopter:
Browse files

Merge branch 'master' of gitlab.uliege.be:am-dept/matlab_airfoil_toolbox

parents a477481e 0fd62e40
No related branches found
No related tags found
No related merge requests found
...@@ -36,6 +36,7 @@ function [filenames, filepaths, idxOpts] = parsefileinputs(optList, filetype, va ...@@ -36,6 +36,7 @@ function [filenames, filepaths, idxOpts] = parsefileinputs(optList, filetype, va
ext = ['*', filetype]; ext = ['*', filetype];
[filenames, filepaths] = uigetfile(ext, 'Select all dat-files to aggregate', ... [filenames, filepaths] = uigetfile(ext, 'Select all dat-files to aggregate', ...
'MultiSelect', 'on'); 'MultiSelect', 'on');
filenames = string(filenames);
filepaths = repmat(string(filepaths), 1, length(filenames)); filepaths = repmat(string(filepaths), 1, length(filenames));
idxOpts = 1; idxOpts = 1;
......
function vect = spacedvector(spacing, nPoints) function vect = spacedvector(spacing, nPoints)
% SPACEDVECTOR Returns a vector based on chosen spacing and number of points % SPACEDVECTOR Returns a vector based on chosen spacing and number of points
%
% Spacing:
% - linear : points spaced linearily
% - halfcosine : more dense at beginning and end of vector
% - cosine : more dense at the beginning and more spaced out at the end
% - sine : more dense at the end and more spaced out at the beginning
%
% ----- % -----
% (c) Copyright 2022 University of Liege % (c) Copyright 2022-2023 University of Liege
% Author: Thomas Lambert <t.lambert@uliege.be> % Author: Thomas Lambert <t.lambert@uliege.be>
% ULiege - Aeroelasticity and Experimental Aerodynamics % ULiege - Aeroelasticity and Experimental Aerodynamics
% Apache 2.0 License % Apache 2.0 License
...@@ -18,6 +25,9 @@ function vect = spacedvector(spacing, nPoints) ...@@ -18,6 +25,9 @@ function vect = spacedvector(spacing, nPoints)
case 'cosine' case 'cosine'
beta = linspace(0, pi / 2, nPoints); beta = linspace(0, pi / 2, nPoints);
vect = 1 - cos(beta); vect = 1 - cos(beta);
case 'sine'
beta = linspace(0, pi / 2, nPoints);
vect = sin(beta);
end end
end end
...@@ -81,6 +81,7 @@ classdef Polar < handle ...@@ -81,6 +81,7 @@ classdef Polar < handle
Stall = struct('aoa', [], 'cl', [], 'cd', []) % Stall point data Stall = struct('aoa', [], 'cl', [], 'cd', []) % Stall point data
Zero = struct('aoa', [], 'cd', []) % Zero-lift point data Zero = struct('aoa', [], 'cd', []) % Zero-lift point data
Lin = struct('slope', [], 'aoaRange', [], 'clRange', []) % Lift linear range data Lin = struct('slope', [], 'aoaRange', [], 'clRange', []) % Lift linear range data
extrapMethod (1, :) {mustBeMember(extrapMethod, {'none', 'spline', 'viterna'})} = 'spline'
end end
% ---------------------------------------------------------------------------------------------- % ----------------------------------------------------------------------------------------------
...@@ -144,7 +145,7 @@ classdef Polar < handle ...@@ -144,7 +145,7 @@ classdef Polar < handle
% %
% See also: af_tools.findcllinearrange. % See also: af_tools.findcllinearrange.
[self.Lin.clRange, self.Lin.aoaRange, self.Lin.slope] = ... [self.Lin.aoaRange, self.Lin.clRange, self.Lin.slope] = ...
af_tools.findcllinearrange(self); af_tools.findcllinearrange(self);
end end
......
function [cl, cd, cm] = getcoeffs(self, aoa, re, polarType) function [cl, cd, cm] = getcoeffs(self, aoa, re, extrapMethod)
% getcoeffs Interpolate polars and returns coefficients for given AoA and Reynolds. % getcoeffs Interpolate polars and returns coefficients for given AoA and Reynolds.
% This function returns does mesh interpolation of the polars and returns the three % This function returns does mesh interpolation of the polars and returns the three
% coefficients (lift, drag, moment) for the input angles of attacks and reynolds. % coefficients (lift, drag, moment) for the input angles of attacks and reynolds.
% It is possible to specify an extrapolation method as well if results outside the original
% polars need to be retrieved. In that case, it is strongly suggested to use the 'Viterna'
% method as it is the only one that tries to emulate the proper aerodynamic behavior of the
% airfoil in the extreme ranges. If no extrapMethod is specified, self.extrapMethod will be
% used (default is 'spline').
% %
% Note % Note
% The inputs can be supplied as vectors of same size. In that case, the output will be the % The inputs can be supplied as vectors of same size. In that case, the output will be the
...@@ -16,9 +21,9 @@ function [cl, cd, cm] = getcoeffs(self, aoa, re, polarType) ...@@ -16,9 +21,9 @@ function [cl, cd, cm] = getcoeffs(self, aoa, re, polarType)
% [cl, cd, cm] = Airfoil.getcoeffs(aoa, re) % [cl, cd, cm] = Airfoil.getcoeffs(aoa, re)
% %
% Input % Input
% aoa : Angles of attacks, [rad] % aoa : Angles of attacks, [rad]
% re : Reynolds numbers, [-] % re : Reynolds numbers, [-]
% polarType : Type of Polar to use ('original', 'extended') % extrapMethod : Extrapolation method ('none', 'spline', 'viterna')
% %
% Output % Output
% cl : Lift coefficients, [-] % cl : Lift coefficients, [-]
...@@ -45,28 +50,36 @@ function [cl, cd, cm] = getcoeffs(self, aoa, re, polarType) ...@@ -45,28 +50,36 @@ function [cl, cd, cm] = getcoeffs(self, aoa, re, polarType)
narginchk(3, 4); narginchk(3, 4);
% Defaults and constants % Defaults and constants
ALLOWED_TYPES = {'original', 'extended'}; ALLOWED_EXTRAP = {'none', 'spline', 'viterna'};
DEF.POLAR_TYPE = 'extended'; EXTENDED_POLARS = {'viterna'};
% Input validation % Input validation
if nargin == 3 if nargin == 3
polarType = DEF.POLAR_TYPE; extrapMethod = self.extrapMethod;
end end
validateattributes(aoa, {'double'}, {'row', 'nonempty'}, mfilename(), 'aoa'); validateattributes(aoa, {'double'}, {'row', 'nonempty'}, mfilename(), 'aoa');
validateattributes(re, {'double'}, {'row', 'nonempty', 'size', size(aoa)}, mfilename(), 're'); validateattributes(re, {'double'}, {'row', 'nonempty', 'size', size(aoa)}, mfilename(), 're');
polarType = validatestring(polarType, ALLOWED_TYPES, mfilename(), 'polarType'); extrapMethod = validatestring(extrapMethod, ALLOWED_EXTRAP, mfilename(), 'extrapMethod');
if any(strcmpi(extrapMethod, EXTENDED_POLARS))
polarType = 'extended';
if isempty(self.Ext.aoa)
self.extendpolar;
end
else
polarType = 'original';
end
% Interpolate coefficients % Interpolate coefficients
% ------------------------------------------- % -------------------------------------------
% Select correct polar % Select correct polar
Pol = selectpolar(self, polarType); Pol = selectpolar(self, polarType);
if numel(self.reynolds) == 1 if numel(self.reynolds) == 1
cl = checkandinterp1(Pol, 'cl', aoa); cl = checkandinterp1(Pol, 'cl', aoa, extrapMethod);
cd = checkandinterp1(Pol, 'cd', aoa); cd = checkandinterp1(Pol, 'cd', aoa, extrapMethod);
cm = checkandinterp1(Pol, 'cm', aoa); cm = checkandinterp1(Pol, 'cm', aoa, extrapMethod);
else else
% Create meshgrid with the polar data points % Create meshgrid with the polar data points
[X, Y] = meshgrid(Pol.aoa(:, 1), Pol.reynolds); [X, Y] = meshgrid(Pol.aoa(:, 1), Pol.reynolds);
...@@ -75,9 +88,9 @@ function [cl, cd, cm] = getcoeffs(self, aoa, re, polarType) ...@@ -75,9 +88,9 @@ function [cl, cd, cm] = getcoeffs(self, aoa, re, polarType)
[Xq, Yq] = meshgrid(aoa', re); [Xq, Yq] = meshgrid(aoa', re);
% 2D interpolation % 2D interpolation
cl = checkandinterp2(X, Y, Pol.cl, Xq, Yq); cl = checkandinterp2(X, Y, Pol.cl, Xq, Yq, extrapMethod);
cd = checkandinterp2(X, Y, Pol.cd, Xq, Yq); cd = checkandinterp2(X, Y, Pol.cd, Xq, Yq, extrapMethod);
cm = checkandinterp2(X, Y, Pol.cm, Xq, Yq); cm = checkandinterp2(X, Y, Pol.cm, Xq, Yq, extrapMethod);
end end
end end
...@@ -99,28 +112,39 @@ function Polar = selectpolar(self, polarType) ...@@ -99,28 +112,39 @@ function Polar = selectpolar(self, polarType)
end end
function out = checkandinterp1(Pol, field, aoa) function out = checkandinterp1(Pol, field, aoa, extrapMethod)
% checkandinterp1 Checks if field is not empty and interpolate (1D) % checkandinterp1 Checks if field is not empty and interpolate (1D)
% If field is empty, return NaN vector of the size of AoA % If field is empty, return NaN vector of the size of AoA
val = Pol.(field); val = Pol.(field);
if ~isempty(val) if ~isempty(val)
out = interp1(Pol.aoa, val, aoa, 'spline'); if strcmpi(extrapMethod, 'none')
out = interp1(Pol.aoa, val, aoa, 'spline', NaN);
else
out = interp1(Pol.aoa, val, aoa, 'spline');
end
else else
out = nan(size(aoa)); out = nan(size(aoa));
end end
end end
function out = checkandinterp2(X, Y, val, Xq, Yq) function out = checkandinterp2(X, Y, val, Xq, Yq, extrapMethod)
% checkandinterp1 Checks if field is not empty and interpolate (1D) % checkandinterp1 Checks if field is not empty and interpolate (1D)
% If field is empty, return NaN vector of the size of AoA % If field is empty, return NaN vector of the size of AoA
warning('off', 'MATLAB:interp2:NaNstrip'); % Warning if original polars contain NaN already
if ~isempty(val) if ~isempty(val)
out = diag(interp2(X, Y, val', Xq, Yq, 'spline')); if strcmpi(extrapMethod, 'none')
out = diag(interp2(X, Y, val', Xq, Yq, 'spline', NaN));
else
out = diag(interp2(X, Y, val', Xq, Yq, 'spline'));
end
else else
out = nan(length(Xq)); out = nan(length(Xq));
end end
warning('on', 'MATLAB:interp2:NaNstrip');
end end
...@@ -139,7 +139,7 @@ function Dat = formatairfoilcoord(varargin) ...@@ -139,7 +139,7 @@ function Dat = formatairfoilcoord(varargin)
end end
% Output structure % Output structure
Dat(i).path = fullpaths; Dat(i).path = fullpaths{i};
Dat(i).file = allFileNames{i}; Dat(i).file = allFileNames{i};
Dat(i).airfoil = char(cellstr(tmpAirfoil{:})); Dat(i).airfoil = char(cellstr(tmpAirfoil{:}));
Dat(i).format = outputFormat; Dat(i).format = outputFormat;
......
...@@ -6,13 +6,13 @@ function [coord, gradY] = nacacamber(varargin) ...@@ -6,13 +6,13 @@ function [coord, gradY] = nacacamber(varargin)
% ----- % -----
% %
% Usage: % Usage:
% [X, Y] = NACACAMBER prompts the user for the airfoil digits, then calculates the coordinates % [coord, gradY] = NACACAMBER prompts the user for the airfoil digits, then calculates the
% of the camberline using 100 points spaced with the half-cosine rule. % coordinates of the camberline using 100 points spaced with the half-cosine rule.
% %
% [X, Y] = NACACAMBER(DIGITS) calculates the coordinates of the camberline for the NACA % [coord, gradY] = NACACAMBER(DIGITS) calculates the coordinates of the camberline for the
% airfoil specified by DIGITS, without further input. % NACA airfoil specified by DIGITS, without further input.
% %
% [X, Y] = NACACAMBER(DIGITS, NPOINTS) calculates the coordinates of the NACA airfoil % [coord, gradY] = NACACAMBER(DIGITS, NPOINTS) calculates the coordinates of the NACA airfoil
% specified by DIGITS, using NPOINTS points spaced with the half-cosine rule. % specified by DIGITS, using NPOINTS points spaced with the half-cosine rule.
% %
% [...] = NACACAMBER(..., 'spacing', SP) uses the defined spacing rule to determine to % [...] = NACACAMBER(..., 'spacing', SP) uses the defined spacing rule to determine to
...@@ -20,14 +20,14 @@ function [coord, gradY] = nacacamber(varargin) ...@@ -20,14 +20,14 @@ function [coord, gradY] = nacacamber(varargin)
% 'linear' - linear % 'linear' - linear
% 'halfcosine' - (default) finer at leading and trailing edges % 'halfcosine' - (default) finer at leading and trailing edges
% 'cosine' - finer at leading edge, coarser at the trailing edge % 'cosine' - finer at leading edge, coarser at the trailing edge
% 'sine' - finer at trailing edge, coarser at the leading edge
% %
% Inputs: % Inputs:
% digits : Character vector representing the NACA airfoil (ex: '0012', '24120', '24012') % digits : Character vector representing the NACA airfoil (ex: '0012', '24120', '24012')
% nPoints : Number of output coordinates % nPoints : Number of output coordinates
% %
% Output: % Output:
% xc : Camberline X coordinates (0 <= X <= 1) % coord : Camberline coordinates [nPts x 2]
% yc : Camberline Y coordinates
% gradY : Gradient of Y (required to get the whole airfoil coordinates) % gradY : Gradient of Y (required to get the whole airfoil coordinates)
% %
% Example: % Example:
...@@ -41,7 +41,7 @@ function [coord, gradY] = nacacamber(varargin) ...@@ -41,7 +41,7 @@ function [coord, gradY] = nacacamber(varargin)
% <a href="https://gitlab.uliege.be/am-dept/matlab_airfoil_toolbox">Documentation (online)</a> % <a href="https://gitlab.uliege.be/am-dept/matlab_airfoil_toolbox">Documentation (online)</a>
% ------------------------------------------- % -------------------------------------------
% (c) Copyright 2022 University of Liege % (c) Copyright 2022-2023 University of Liege
% Author: Thomas Lambert <t.lambert@uliege.be> % Author: Thomas Lambert <t.lambert@uliege.be>
% ULiege - Aeroelasticity and Experimental Aerodynamics % ULiege - Aeroelasticity and Experimental Aerodynamics
% MIT License % MIT License
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment