In: Mechanical Engineering
Develop MATLAB codes for Blade Element Momentum Theory for horizontal axis tidal turbine for airfoil NACA 0015, analyzing the performance of the turbine; power.
function [cl,cd,phi,aoa,a,ap]=BEM(airfoils,blade,turbine,fastout,vel) %% [cl,cd,phi,aoa,a,ap]=BEM(airfoils,blade,turbine,fastout,vel) -> BEM theory. % % Function computes spanwise and rotor performance and loads via blade % element momentum theory. Includes corrections for skewed flow and % heavily loaded rotors. % % ****Input(s)**** % airfoils Structure containing airfoil performance tables % blade Structure containing blade geometry % turbine Structure containing turbine geometry % fastout Structure containing time-dependent kinematics % vel Structure containing velocity components in inertial and blade % coordinate systems % % ****Output(s)**** % cl Spanwise lift coefficient % cd Spanwise drag coefficient % phi Spanwise inflow angle % aoa Spanwise angle of attack % a Spanwise axial induction factor % ap Spanwise tangential induction factor %% Preallocate space for variables within loop %Determine size of test vectors/arrays ns=length(blade.RNodes); nt=length(fastout.Time); %Number of timesteps na=length(airfoils.Names); RNodes=blade.RNodes; Chord=blade.Chord; NFoil=blade.NFoil; a0=zeros(ns,nt); %Old (previous iteration) axial induction factor ap0=zeros(ns,nt); %Old (previous iteration) tangential induction factor phi=zeros(ns,nt); %Local inflow angle aoa=zeros(ns,nt); %Local angle of attack cl=zeros(ns,nt); %Local lift coefficient cd=zeros(ns,nt); %Local drag coefficient ct=zeros(ns,nt); %Local thrust coefficient ftip=zeros(ns,nt); %Tip loss factor fhub=zeros(ns,nt); %Hub loss factor f=zeros(ns,nt); %Total loss corection factor fiter=zeros(ns,nt); %Converence flag for gridpoints ('1' if converged, '9999' if not) %% Define convergence criteria tol=1e-6; %Convergence tolerance da=ones(ns,nt); %Set initial value for axial induction factor residual equal to 1 dap=ones(ns,nt); %Set initial value for tangential induction factor residual equal to 1 ncv=find(da>tol | dap>tol); %Identify all nonconverged points (all initially) miter=5000; %Maximum number of allowable iterations wt=0.1; %Weighting factor on corrections to balance speed with stability (faster as you %approach 1, but less stable) %% Compute relevant velocity/angle components Uinf=sqrt(sum(vel.relhub.^2,2)); Om=fastout.RotSpeed*(2*pi/60); twst=-blade.AeroTwst*pi/180; ptch=fastout.BldPitch1*pi/180; rP=-fastout.PtfmPitch*pi/180; %Rotor pitch (vector, wrt time) rY=(fastout.PtfmYaw+fastout.NacYaw)*pi/180; %Rotor yaw (vector, wrt time) if sign(rP)==0 sp=sign(rY); elseif sign(rY)==0 sp=sign(rP); else sp=sign(rP).*sign(rY); end gamma=sp.*acos(cos(rP).*cos(rY)); %Total skew angle psi=pi-atan2(cos(rP).*sin(rY),sin(rP)); %Total azimuthal angle of skew %% Compute initial guesses of key variables Om=repmat(Om',ns,1); Uinf=repmat(Uinf',ns,1); ptch=repmat(ptch',ns,1); gamma=repmat(gamma',ns,1); psi=repmat(psi',ns,1); twst=repmat(twst,1,nt); sigmap=repmat(turbine.NumBl.*Chord./(2.*pi.*RNodes),1,nt); %Local solidity RNodes=repmat(RNodes,1,nt); lambdar=Om.*RNodes./Uinf; %Local speed ratio % Initial values for axial and tangential induction factors a=real(0.25*(2+pi*lambdar.*sigmap-sqrt(4-4*pi*lambdar.*sigmap+pi*lambdar.^2.*sigmap.* ... (8*(twst+ptch)+pi*sigmap)))); ap=zeros(size(a)); %% Primary loop for BEM for j=1:200 % Save previous values of axial and tangential induction factors a0(ncv)=a(ncv); ap0(ncv)=ap(ncv); % Compute inflow angle and angle of attack phi(ncv)=atan2(Uinf(ncv).*(1-a(ncv)),Om(ncv).*RNodes(ncv).*(1+ap(ncv))); aoa(ncv)=(phi(ncv)-(twst(ncv)+ptch(ncv)))*180/pi; % Interpolate over airfoil database for lift and drag coefficients for k=1:na cl(NFoil==k,:)=interp1(airfoils.profiles(k,1).AoA,airfoils.profiles(k,1).Cl, ... aoa(NFoil==k,:)); cd(NFoil==k,:)=interp1(airfoils.profiles(k,1).AoA,airfoils.profiles(k,1).Cd, ... aoa(NFoil==k,:)); end % Compute elemental thrust coefficient ct(ncv)=sigmap(ncv).*(1-a(ncv)).^2.*(cl(ncv).*cos(phi(ncv))+cd(ncv).*sin(phi(ncv)))./ ... sin(phi(ncv)).^2; % Compute loss correction factor due to tip and hub losses ftip(ncv)=2./pi.*acos(exp(-(turbine.NumBl.*(blade.TipRad-RNodes(ncv))./ ... (2.*RNodes(ncv).*sin(phi(ncv)))))); %Tip loss factor fhub(ncv)=2./pi.*acos(exp(-(turbine.NumBl.*(RNodes(ncv)-blade.HubRad)./ ... (2*blade.HubRad.*sin(phi(ncv)))))); %Hub loss factor f(ncv)=fhub(ncv).*ftip(ncv); %Total loss correction factor % Compute axial induction factor using conventional BEM theory a(ncv)=real((1+4.*f(ncv).*sin(phi(ncv)).^2./(sigmap(ncv).*(cl(ncv).*cos(phi(ncv))+ ... cd(ncv).*sin(phi(ncv))))).^-1); % Identify highly loaded gridpoints (requires use of modified Glauert correction for % axial induction factor) ncvf=find(ct>0.96*f & (da>tol | dap>tol)); % Compute axial induction factor using modified Glauert correction (on identified gridpoints) a(ncvf)=real((18.*f(ncvf)-20-3.*sqrt(ct(ncvf).*(50-36.*f(ncvf))+12.*f(ncvf).* ... (3.*f(ncvf)-4)))./(36.*f(ncvf)-50)); % Compute tangential induction factor ap(ncv)=(4.*f(ncv).*cos(phi(ncv)).*sin(phi(ncv))./(sigmap(ncv).*(cl(ncv).*sin(phi(ncv)) ... -cd(ncv).*cos(phi(ncv))))-1).^-1; % Apply skewed wake correction if flow is non-axial if abs(gamma)>1e-8; a(ncv)=a(ncv).*(1+15*pi/32.*RNodes(ncv)./blade.TipRad.*tan(0.5.*(0.6.*a(ncv)+1).* ... gamma(ncv)).*cos(psi(ncv))); end % Compute residuals da(ncv)=abs(a0(ncv)-a(ncv)); dap(ncv)=abs(ap0(ncv)-ap(ncv)); % Apply corrective weighting for convergence stability if wt>0 a(ncv)=a0(ncv)+wt.*(a(ncv)-a0(ncv)); ap(ncv)=ap0(ncv)+wt.*(ap(ncv)-ap0(ncv)); end % Clear all gridpoint flags in preparation for next loop clear ncv ncvf ncvcl ida idap % Identify nonconverged gridpoints ncv=find(da>tol | dap>tol); % If all points meet convergence criteria, break loop if isempty(ncv) break end % If maximum allowable iterations has been reached, flag nonconverged gridpoints % with '9999' if j==miter fiter(ncv)=9999; else fiter(ncv)=j; end end