Project

Cfd analysis of 1d supersonic nozzle flow using MacCormack method

Goal: solve the 1d supersonic nozzle flow using Maccormack method

objective:

1) Implementing both conservative and non conservative form of governing equations by writing separate functions.

2) figure out minimum number of cycles for which simulation should be run for convergence.

3) compare normalized mass flow rate from both the conservative and non conservative form.

4) determine which method is faster.

#Main code

clear all
close all
clc

%inputs
n=31;
x=linspace(0,3,n);
xr=x./3; % normalized length
dx=x(2)-x(1);
gamma=1.4;

% area
a=1+2.2*(x-1.5).^2;

%location of throat
n_throat=find(a==1);

%paramter which keeps count of no of cycles for convergence
g=0;
tol=1e-6;
error=9e9;

%Non Conservative Form Solver

tic
[rho,v,t,g,m,p,mach,Mach_throat,Pressure_ratio_throat,Density_ratio_throat,Temperature_ratio_throat,k]=non_conservative(n,x,dx,a,gamma,g,tol,error,n_throat);
t_non_consv=toc;

fprintf(\'minimum number of iterations for convergence of non conservative form:%f\',g);
fprintf(\'time taken by non conservstive solver:%f\',t_non_consv);
  
%steady state profiles for non conservative
figure(1) 
subplot(4,1,1); 
plot(xr,mach,\'m\');
title(\'mach number variation along the length of nozzle using non conservative form\');
legend(\'Mach Number\');
grid minor

subplot(4,1,2); 
plot(xr,p,\'b\');
title(\'Pressure ratio variation along the length of nozzle using non conservative form\');
legend(\'Pressure ratio\');
grid minor
 
subplot(4,1,3); 
plot(xr,rho,\'g\');
title(\'density ratio variation along the length of nozzle using non conservative form\');
legend(\'Density ratio\');
grid minor 
  
 subplot(4,1,4); 
plot(xr,t,\'r\');
title(\'Temperature ratio variation along the length of nozzle using non conservative form\');
legend(\'Temperature ratio\');
grid minor


%Conservative Form Solver  
  g_c=0;
 tic
[rho_c,v_c,t_c,g_c,m_c,p_c,mach_c,Mach_throat_c,Pressure_ratio_throat_c,Density_ratio_throat_c,Temperature_ratio_throat_c,k_c]=conservative(n,x,n_throat,dx,a,gamma,g_c,tol,error);
t_consv=toc;


fprintf(\'minimum number of iterations for convergence of conservative form:%f\',g_c);
fprintf(\'time taken by conservstive solver:%f\',t_consv);


%steady state profiles for conservative
figure(2) 
subplot(4,1,1); 
plot(xr,mach_c,\'m\');
title(\'mach number variation along the length of nozzle using conservative form\');
legend(\'Mach Number\');
grid minor

subplot(4,1,2); 
plot(xr,p_c,\'b\');
title(\'Pressure ratio variation along the length of nozzle using conservative form\');
legend(\'Pressure ratio\');
grid minor
 
subplot(4,1,3); 
plot(xr,rho_c,\'g\');
title(\'density ratio variation along the length of nozzle using conservative form\');
legend(\'Density ratio\');
grid minor 
  
 subplot(4,1,4); 
plot(xr,t_c,\'r\');
title(\'Temperature ratio variation along the length of nozzle using conservative form\');
legend(\'Temperature ratio\');
grid minor

%convergence plots for both the forms
figure(3) 
subplot(4,1,1); 
plot(k,Mach_throat);
hold on
plot(k_c,Mach_throat_c);
title(\'mach number variation vs iterations using conservative form\');
legend(\'Mach Number Non-Conservative\',\'Mach Number Conservative\');
grid minor

subplot(4,1,2); 
plot(k,Pressure_ratio_throat);
hold on
plot(k_c,Pressure_ratio_throat_c);
title(\'Pressure ratio variation vs iteration using conservative form\');
legend(\'Pressure ratio Non Conservative\',\'Pressure ratio Conservative\');
grid minor
 
subplot(4,1,3); 
plot(k,Density_ratio_throat);
hold on
plot(k_c,Density_ratio_throat_c);
title(\'density ratio variation vs iteration using conservative form\');
legend(\'Density ratio Non Conservative\',\'Density ratio Conservative\');
grid minor 
  
 subplot(4,1,4); 
plot(k,Temperature_ratio_throat);
hold on
plot(k_c,Temperature_ratio_throat_c);
title(\'Temperature ratio variation vs iteration using conservative form\');
legend(\'Temperature ratio Non Conservative\',\'Temperature ratio Conservative\');
grid minor

figure(4)
plot(xr,m);
hold on
plot(xr,m_c);
title(\'Steady Mass Flowrate\');
legend(\'Non-Conservative\',\'Conservative\');
xlabel(\'x/L\');
ylabel(\'Mass Flowrate\');
grid minor

#Non conservative function code

function [rho,v,t,g,m,p,mach,Mach_throat,Pressure_ratio_throat,Density_ratio_throat,Temperature_ratio_throat,k]=non_conservative(n,x,dx,a,gamma,g,tol,error,n_throat)

% calculate initial profiles
rho=1-0.3146*x;
t=1-0.2314*x; % t is temperature
v=(0.1+1.09*x).*t.^0.5;
%time steps
nt=4000;
  
for k=1:nt
    rho_old=rho;
    v_old=v;
    t_old=t;
m_old=(rho_old.*a.*v_old);
    cfl=0.5;
    max_vel=v_old+(t_old.^0.5);
dt_vector = (cfl*dx)./(max_vel);
dt = min(abs(dt_vector));

%predictor step
for j=2:n-1
    dvdx=(v(j+1)-v(j))/dx;
    drhodx=(rho(j+1)-rho(j))/dx;
    dtdx=(t(j+1)-t(j))/dx;
    dlogadx=(log(a(j+1))-log(a(j)))/dx;
   
    %continuity eqn
    drhodt_p(j)=(-rho(j)*dvdx)-(rho(j)*v(j)*dlogadx)-(v(j)*drhodx);
    
    % momentum eqn
    dvdt_p(j)=(-v(j)*dvdx)-(1/gamma)*(dtdx+(t(j)/rho(j))*drhodx);
   
   % energy eqn
   dtdt_p(j)=(-v(j)*dtdx)-((gamma-1)*t(j)*(dvdx+(v(j)*dlogadx)));
   
   %soln update
   rho(j)=rho(j)+drhodt_p(j)*dt;
    v(j)=v(j)+dvdt_p(j)*dt;
     t(j)=t(j)+dtdt_p(j)*dt;
    
end
% corrector method
for j=2:n-1
    dvdx=(v(j)-v(j-1))/dx;
    drhodx=(rho(j)-rho(j-1))/dx;
    dtdx=(t(j)-t(j-1))/dx;
    dlogadx=(log(a(j))-log(a(j-1)))/dx;
   
    %continuity eqn
    drhodt_c(j)=(-rho(j)*dvdx)-(rho(j)*v(j)*dlogadx)-(v(j)*drhodx);
    
    % momentum eqn
    dvdt_c(j)=(-v(j)*dvdx)-(1/gamma)*(dtdx+(t(j)/rho(j))*drhodx);
   
   % energy eqn
   dtdt_c(j)=(-v(j)*dtdx)-((gamma-1)*t(j)*(dvdx+(v(j)*dlogadx)));
     
end

% compute avg time derivative
drhodt=0.5*(drhodt_p+drhodt_c);
dvdt=0.5*(dvdt_p+dvdt_c);
dtdt=0.5*(dtdt_p+dtdt_c);


%final soln update
for i=2:n-1
    rho(i)=rho_old(i)+drhodt(i)*dt;
    v(i)=v_old(i)+dvdt(i)*dt;
    t(i)=t_old(i)+dtdt(i)*dt;
  
end
% apply boundary consitions
%inlet
rho(1)=1;
v(1)=2*v(2)-v(3);
t(1)=1;
%outlet
rho(n)=2*rho(n-1)-rho(n-2);
v(n)=2*v(n-1)-v(n-2);
t(n)=2*t(n-1)-t(n-2);

 p=rho.*t; %pressure rati
 mach=v./(t.^0.5); %mach number 
 
 

%updated mass flow rate
m=rho.*a.*v;

% number of cycles for convergence

if error>tol
    error=max(abs(m-m_old));
    g=g+1;
end

% Transient throat values 
Mach_throat(g)=mach(n_throat);
Pressure_ratio_throat(g)=p(n_throat);
Density_ratio_throat(g)=rho(n_throat);
Temperature_ratio_throat(g)=t(n_throat);



end
k=linspace(1,g,g);

#conservative function code

function [rho,v,t,g_c,m,p,mach,Mach_throat,Pressure_ratio_throat,Density_ratio_throat,Temperature_ratio_throat,k]=conservative(n,x,n_throat,dx,a,gamma,g_c,tol,error)

% Calculate initial profiles
for inip = 1:length(x);
    if (x(inip)<=0.5);
        rho(inip) = 1.0;
        t(inip) = 1.0;
    elseif (x(inip)>=0.5) && (x(inip)<=1.5);
        rho(inip) = 1.0 - 0.366*(x(inip)-0.5);
        t(inip) = 1.0 - 0.167*(x(inip)-0.5);
    else
        rho(inip) = 0.634 - 0.3879*(x(inip)-1.5);
        t(inip) = 0.833 - 0.3507*(x(inip)-1.5);
    end
    
end
 
v = 0.59./(rho.*a); % velocity

p = rho.*t; % pressure

% Solution vecotors
U1 = rho.*a;
U2 = rho.*a.*v;
U3 = rho.*(t./(gamma-1) + ((gamma/2).*v.^2)).*a;
 
% Flux vectors
F1 = rho.*a.*v;
F2 = rho.*a.*v.^2 + (1/gamma).*rho.*a;
F3 = rho.*(t./(gamma-1) + (gamma/2).*v.^2).*v.*a + rho.*a.*v;
 
 
% Making a copy of all the elements
U1_old = U1;
U2_old = U2;
U3_old = U3;
F1_old = F1;
F2_old = F2;
F3_old = F3;

 

nt = 4000;
 

% Outer time loop
for k = 1:nt
    
    
    % Calculate minium time step
    CFL = 0.5;
    dt_vector = CFL.*(dx./(t.^0.5 + v));
    dt = min(abs(dt_vector));
    rho_old = rho;
    t_old = t;
    v_old = v;
     m_old = rho_old.*a.*v_old;
    % Making a copy of all the elements
        U1_old = U1;
        U2_old = U2;
        U3_old = U3;
       
    % Flux vectors
        F1 = U2;
        F2 = (U2.^2./U1) + ((gamma-1)/gamma).*(U3 - ((gamma/2).*(U2.^2./U1)));
        F3 = (gamma.*((U2.*U3)./U1)) - ((gamma*(gamma-1))/2).*((U2.^3)./(U1.^2));
       
    % Predictor Method
        for j=2:n-1
 
            dF1dx = (F1(j+1)-F1(j))/dx;
            dF2dx = (F2(j+1)-F2(j))/dx;
            dF3dx = (F3(j+1)-F3(j))/dx;
            dlogadx = (log(a(j+1))-log(a(j)))/dx;
            dadx = (a(j+1)-a(j))/dx;
            J2 = (1/gamma).*rho(j).*t(j).*dadx;
 
            % Continity Equation
            dU1dt_p(j) = -dF1dx;
           
            % Momentum Equation
            dU2dt_p(j) = -dF2dx + J2;
           
            % Energy Equation
            dU3dt_p(j) = -dF3dx;
           
            % Solution update
            U1(j) = U1(j) + dU1dt_p(j)*dt;
            U2(j) = U2(j) + dU2dt_p(j)*dt;
            U3(j) = U3(j) + dU3dt_p(j)*dt;
        end
   
    % Primitive variables using solution vector
        rho = U1./a; % density
        v = U2./U1; % velocity
        t = (gamma-1).*((U3./U1) - (gamma/2).*(v.^2)); % temp
        p = rho.*t; % pressure  
   
    % Flux vectors
        F1 = U2;
        F2 = (U2.^2./U1) + ((gamma-1)/gamma).*(U3 - (gamma/2).*(U2.^2./U1));
        F3 = (gamma.*((U2.*U3)./U1)) - ((gamma*(gamma-1))/2).*(U2.^3./U1.^2);
       
    % Corrector Method
        for j=2:n-1
 
            dF1dx = (F1(j)-F1(j-1))/dx;
            dF2dx = (F2(j)-F2(j-1))/dx;
            dF3dx = (F3(j)-F3(j-1))/dx;            
            dlogadx = (log(a(j))-log(a(j-1)))/dx;
            dadx = (a(j)-a(j-1))/dx;
            J2 = (1/gamma).*rho(j).*t(j).*dadx;            
           
            % Continity Equation
            dU1dt_c(j) = -dF1dx;
           
            % Momentum Equation
            dU2dt_c(j) = -dF2dx + J2;
           
            % Energy Equation
            dU3dt_c(j) = -dF3dx;
        end
       
    % Compute average time derivative
        dU1dt = 0.5*(dU1dt_p + dU1dt_c);
        dU2dt = 0.5*(dU2dt_p + dU2dt_c);
        dU3dt = 0.5*(dU3dt_p + dU3dt_c);
   
    % Final Solution Update
        for i = 2:n-1
            U1(i) = U1_old(i) + dU1dt(i)*dt;
            U2(i) = U2_old(i) + dU2dt(i)*dt;
            U3(i) = U3_old(i) + dU3dt(i)*dt;
        end
       
    % Apply boundary conditions
        % Inlet
        U2(1) = 2*U2(2) - U2(3);
 
        % Outlet
        U1(n) = 2*U1(n-1) - U1(n-2);
        U2(n) = 2*U2(n-1) - U2(n-2);
        U3(n) = 2*U3(n-1) - U3(n-2);
       
    % Primitive variables using solution vector
    rho = U1./a; % density
    v = U2./U1; % velocity
    t = (gamma-1).*((U3./U1) - (gamma/2).*(v.^2)); % temp
    p = rho.*t; % pressure
   
       
    % Mass Flow Rate
        m = rho.*a.*v;
        
    % Pressure
        p = rho.*t; % pressure
    % Mach Number
        mach = v./(sqrt(t));
        
        if error>tol
    error=max(abs(m-m_old));
    g_c=g_c+1;
end
       
    % Throat area variables
        Mach_throat(g_c)=mach(n_throat);
Pressure_ratio_throat(g_c)=p(n_throat);
Density_ratio_throat(g_c)=rho(n_throat);
Temperature_ratio_throat(g_c)=t(n_throat);

 
    
   
end
k=linspace(1,g_c,g_c);
 

#solution results

All the parameters listed in table1 and table2 are measured at Throat of nozzle.

Table1: Results of Non conservative form of governing equation and mesh independent study

Table 2: Results of conservative form of governing equation and mesh independent study

Discussion:

1) mesh independent study has been carried out and as you can see from above tables the non conservative form achieves accurate soln for all the parameters listed in table at n=31 itself.

2)from the above tables minimum iterations for convergence increases as the number of grid point increases for both the methods but the increase is more incase of non-conservative form infact at higher grid points the non conservative form require more iterations to convergence compared to conservative form.

3) the non conservative form is much faster compared to conservative form at any number of grid points.

Fig1: steady state plots of non conservative form for different parameters

Fig2: steady state plots of conservative form for different parameters

As you can see from the above figures the steady state plots for both conservative and non conservative form are same for different parameters like mach number, pressure ratio ,density ratio and temperature ratio

Fig3: convergence plots for both conservative and non conservative form for different parameters measured at Throat section of nozzle.

Fig4: steady state plot of non dimensionalized mass flow rate for both conservative and non conservative form of governing equation

as you can see from the above figure the mass flow rate variation over a length of nozzle is much larger for non-conservative form.

case1 n=31; avg mass flow rate for non conservative form is 0.587925.

avg mass flow rate for conservative form is 0.585173.

case2 n=61; avg mass flow rate for non conservative form is 0.583698.

avg mass flow rate for conservative form is 0.58285.

Conclusions

1)conservative form is best in calculating mass flow rate over the length of nozzle compared to non conservative form.

2)non conservative form achieves good accuracy at lower number of grid points only compared to conservative form.so this form is computational viable.

3)non conservative form is faster compared to conservative form, because in conservative form you need to calculate extra variables like flux variables and source variables.

4) as the number of grid point increase the minimum iterations for convergence also increases for both the forms , but the increase in case of non conservative form is more compared to conservative form.( refer above tables)

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.