Challenge

Week 7 - Simulation of a 1D Super-sonic nozzle flow simulation using Macormack Method

TITLE

1D flow through a convergent divergent nozzle(subsonic-supersonic)

OBJECTIVES

To show the steady state distribution of primitive variables in the nozzle

2. Time-wise variation of the primitive variables

3. Variation of Mass flow rate distribution inside the nozzle at different time steps during the time-marching process

4. Comparison of Normalized mass flow rate distributions of both forms

THEORY

Subsonic-supersonic(delaval or convergent-divergent nozzle) Nozzle

This nozzle has 3 main sections

a. subsonic or inlet

b. throat

c. supersonic or outlet

The criteria for determination of the flow, whether its subsonic or super sonic depends on the Mach number.

  1. Subsonic conditions occur for Mach numbers less than one, M < 1 . For the lowest subsonic conditions, compressibility can be ignored.
  2. As the speed of the object approaches the speed of sound, the flight Mach number is nearly equal to one, M = 1, and the flow is said to be transonic. At some places on the object, the local speed exceeds the speed of sound. Compressibility effects are most important in transonic flows and lead to the early belief in a sound barrier. Flight faster than sound was thought to be impossible. In fact, the sound barrier was only an increase in the drag near sonic conditions because of compressibility effects. Because of the high drag associated with compressibility effects, aircraft do not cruise near Mach 1.
  3. Supersonic conditions occur for Mach numbers greater than one, 1 < M < 3. Compressibility effects are important for supersonic aircraft, and shock waves are generated by the surface of the object. For high supersonic speeds, 3 < M < 5, aerodynamic heating also becomes very important for aircraft design.

THEORY

There are two approaches to get this done, Conservative and Non Conservative

NON CONSERVATIVE

In the above equations above are in the form of dimensional numbers. But in CFD e are using non dimensional numbers which give us a better final result. Where (P/`P_0`) and (T/`T_0`) values varies from 0 to 1.

The image below shows the non dimensional multiplied on both sides of the above equations

Governing equations for conservative form

\

definition of the above equation with solution vector U :

above equations can be written as

We apply the macormack's technique to solve the problem and get solutions.

To obtain the primitive variables we need to decode variables u1 u2 and u3 and we use those values to find out primitive variables

For Non Conservative form

Initial Conditions(same for both forms)

Boundary conditions for Conservative
INLET
u1(1)=a(1);
u2(1)=2*u2(2)-u2(3);
v_c(1) = u2(1)/u1(1);
u3(1)=u1(1)*((temp_c(1)/(gamma-1)) + 0.7*(v_c(1)^2));

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);

CODE LOGIC

CODE

clear all
close all
clc

nt=1400;
% calling non conservative function  
tic
[v,rho,temp,m,mach_no,p,rho_t,v_t,temp_t,p_t,mach_no_t,m_t,x]=nozzle_nonconservative();
non_conservative=toc;

% calling conservative function 
tic
[v_c,rho_c,temp_c,m_c,mach_no_c,p_c,rho_ct,v_ct,temp_ct,p_ct,mach_no_ct,m_ct]=nozzle_conservative();
conservative=toc;

%plotting conservative vs non conservative
%mass flow rate 
figure(3)
subplot(3,2,1)
plot(x,m);
hold on 
plot(x,m_c,'*');
%analytical solution is 0.579
a=0.579*ones(1,31);
plot(x,a,'-');
xlabel('non-dimensional flow throw the nozzle (x)');
ylabel('non-dimensional mass flow throw the nozzle (m)');
legend('non-conservative','conserative','analytical');
title('mass flow rate comparison');
grid on 

%variation of non dimentional flow parameters
%mach number
subplot(3,2,2)
plot(x,mach_no);
hold on 
plot(x,mach_no_c,'*');
xlabel('nozzle distace');
ylabel('mach number');
legend('non-conservative','conserative');
title('mach number comparison');
grid on 

%pressure
subplot(3,2,3)
plot(x,p);
hold on 
plot(x,p_c,'*');
xlabel('nozzle distace');
ylabel('presssure');
legend('non-conservative','conserative');
title('pressure comparison');
grid on 

%density
subplot(3,2,4)
plot(x,rho);
hold on 
plot(x,rho_c,'*');
xlabel('nozzle distace');
ylabel('density');
legend('non-conservative','conserative');
title('density comparison');
grid on 

%temperature
subplot(3,2,5)
plot(x,temp);
hold on 
plot(x,temp_c,'*');
xlabel('nozzle distace');
ylabel('temperature');
legend('non-conservative','conserative');
title('temperature comparison');
grid on 

%velocity
subplot(3,2,6)
plot(x,v);
hold on 
plot(x,v_c,'*');
xlabel('nozzle distace');
ylabel('velocity');
legend('non-conservative','conserative');
title('velocity comparison');
grid on 

% variation of flow at throat 
figure(4)
%plotting density 
subplot(4,1,1)
plot(rho_t)
hold on 
plot(rho_ct,'r')
ylabel('density');
legend('non-conservative','conserative');
title('density comparison at throat for various time step ');


%plotting temperature
subplot(4,1,2)
plot(temp_t)
hold on 
plot(temp_ct,'r')
ylabel('temperature');
legend('non-conservative','conserative');
title('temperature comparison at throat for various time step ');

%pressure
subplot(4,1,3)
plot(p_t)
hold on 
plot(p_ct,'r')
ylabel('pressure');
legend('non-conservative','conserative');
title('pressure comparison at throat for various time step ');

%mach number
subplot(4,1,4)
plot(mach_no_t)
hold on 
plot(mach_no_ct,'r')
ylabel('mach number');
legend('non-conservative','conserative');
title('mach number comparison at throat for various time step ');

FUNCTIONS

function [v,rho,temp,m,mach_no,p,rho_t,v_t,temp_t,p_t,mach_no_t,m_t,x]=nozzle_nonconservative()
%non conservative approach
%inputs
n=31;
x=linspace(0,3,n);
dx=x(2)-x(1);

%calculating initial profiles 
rho=1-0.3146*x; %density 
temp= 1-0.2314*x; % temperature
v=(0.1+1.09*x).*temp.^0.5;% velocity
gamma =1.4;

a=1 + 2.2.*(x-1.5).^2;
c=0.5; %cfl condition for stability
nt=1400;
l=[1:1400];
throat=(n+1)/2;
dt=min(c.*(dx./(sqrt(temp)+v)));
% dt=0.02;
%outer time loop 
for k=1:nt
    
    rho_old=rho;
    v_old=v;
    temp_old=temp;
    %predictor method 
    for j=2:n-1
       %drho_dt_p = -rho(j)*(v(j+1)-v(j))/dx - rho(j)*v(j)*(log(a(j+1))-log(a(j)))/dx-v(j)*(rho(j).....)
        dvdx=(v(j+1)-v(j))/dx;
        drhodx=(rho(j+1)-rho(j))/dx;
        dtdx=(temp(j+1)-temp(j))/dx;
        dlogadx=(log(a(j+1))-log(a(j)))/dx;
        %continuity equation
        drhodt_p(j) = -rho(j)*dvdx -rho(j)*v(j)*dlogadx-v(j)*drhodx;
        
        %momentum equation 
        dvdt_p(j) =-v(j)*dvdx -(1/gamma)*(dtdx+(temp(j)/rho(j))*drhodx);
        
        %energy equation
        dtdt_p(j)=-v(j)*dtdx-(gamma-1)*temp(j)*(dvdx+v(j)*dlogadx);
        
        %solution update
        rho(j)=rho(j)+drhodt_p(j)*dt;
        v(j)=v(j)+dvdt_p(j)*dt  ;
        temp(j)=temp(j)+dtdt_p(j)*dt;
        
    end
    
        %corrector method 
    for j=2:n-1
       %drho_dt_p = -rho(j)*(v(j+1)-v(j))/dx - rho(j)*v(j)*(log(a(j+1))-log(a(j)))/dx-v(j)*(rho(j).....)
        dvdx=(v(j)-v(j-1))/dx;
        drhodx=(rho(j)-rho(j-1))/dx;
        dtdx=(temp(j)-temp(j-1))/dx;
        dlogadx=(log(a(j))-log(a(j-1)))/dx;
        %continuity equation
        drhodt_c(j) = -rho(j)*dvdx -rho(j)*v(j)*dlogadx-v(j)*drhodx;
        
        %momentum equation 
        dvdt_c(j) =-v(j)*dvdx -(1/gamma)*(dtdx+(temp(j)/rho(j))*drhodx);
        
        %energy equation
        dtdt_c(j)=-v(j)*dtdx-(gamma-1)*temp(j)*(dvdx+v(j)*dlogadx);
        
    end
    %computing the average time derivative 
    dvdt= 0.5*(dvdt_p + dvdt_c);
    drhodt= 0.5*(drhodt_p + drhodt_c);
    dtdt= 0.5*(dtdt_p + dtdt_c);
    
    %calculating residual 
    dvdt_t(k)=abs(dvdt(throat));
    drhodt_t(k)=abs(drhodt(throat));
    dtdt_t(k)=abs(dtdt(throat));
   
    %final solution update
    
    for i=2:n-1
        v(i)=v_old(i)+dvdt(i)*dt;
        rho(i)=rho_old(i)+drhodt(i)*dt;
        temp(i)=temp_old(i)+dtdt(i)*dt;
    end
    %applying boundary conditions
    %inlet
    v(1)=2*v(2)-v(3);
    
    %outlet
    v(n)=2*v(n-1)-v(n-2);
    rho(n)=2*rho(n-1)-rho(n-2);
    temp(n)=2*temp(n-1)-temp(n-2);
    
    %mass flow rate m
    m=rho.*a.*v;
    %pressure ratio 
    p=rho.*temp;
    %mach no
    mach_no = v./sqrt(temp);
    
    %VALUEs at throat 
    rho_t(k)=rho(throat);
    v_t(k)=v(throat);
    temp_t(k)=temp(throat);
    p_t(k)=p(throat);
    mach_no_t(k)=  mach_no(throat);
    m_t(k)=m(throat);
    
    %plotting mass flow rate at different time steps 
    figure(1);
    if k==50
        plot(x,m,'color','b','linewidth',1.5);
        hold on 
    elseif k == 100
        plot(x,m,'color','g','linewidth',1.5);
        hold on 
    elseif k == 150
        plot(x,m,'color','y','linewidth',1.5);
        hold on 
    elseif k == 200
        plot(x,m,'color','black','linewidth',1.5);
        hold on 
    elseif k == 500
        plot(x,m,'color','cyan','linewidth',1.5);
        hold on 
    elseif k == 700
        plot(x,m,'color','r','linewidth',1.5);
        hold on 
    elseif k == 1400
        plot(x,m,'color','m','linewidth',1.5);
        grid on 
        title('Non Conservative')
    end
end
hold off
% 'Name','Mass flow rate at diff time step'
xlabel('non-dimensional flow throw the nozzle (x)');
ylabel('non-dimensional mass flow throw the nozzle (m)');
legend({'50 time steps','100 time steps','150 time steps','200 time steps','500 time steps','700 time steps','1400 time steps'});

figure(5)
semilogy(l,dvdt_t,'r');
hold on
semilogy(l,drhodt_t,'b');
semilogy(l,dtdt_t,'g');
xlabel('number of time steps ');
ylabel('values of residual at throat');
legend('dvdt','drhodt','dTdt');

title('Non conservative')


end

Function Conservative


function [v_c,rho_c,temp_c,m_c,mach_no_c,p_c,rho_ct,v_ct,temp_ct,p_ct,mach_no_ct,m_ct]=nozzle_conservative()
% conservative approach
%inputs
n=31;
x=linspace(0,3,n);
dx=x(2)-x(1);
l=[1:1400];
%calculating initial profiles 
%initialising density and temperature for conservative form.
for i=1:length(x)   
    if x(i)>=0 && x(i)<=0.5
        rho_c(i)=1;
        temp_c(i)=1;
    elseif x(i)>0.5 && x(i)<=1.5
        rho_c(i)= 1-0.366*(x(i)-0.5);
        temp_c(i)=1-0.167*(x(i)-0.5);
    elseif x(i)>1.5 && x(i)<=3
        rho_c(i)= 0.634-0.3879*(x(i)-1.5);
        temp_c(i)=0.833-0.3507*(x(i)-1.5);
    end
end
 

gamma =1.4;
a=1 + (2.2.*((x-1.5).^2)); % nozzle area 
c=0.5; %cfl condition for stability
nt=1400; % no of time steps
throat=(n+1)/2;
v_c=0.59./(rho_c.*a);% velocity
for i=1:n
    dt_calc(i) = c.*(dx./(sqrt(temp_c(i))+v_c(i))); 
end
dt= min(dt_calc);
%dt = 0.0267;



%solution vector in terms of initial condition
u1= rho_c.*a;
u2= rho_c.*a.*v_c;
u3= rho_c.*((temp_c./(gamma-1))+(gamma./2)*(v_c.^2))    .*a;

  

 for k=1:1400
   % storing the old values of u1, u2 and u3 
    u1_old=u1;
    u2_old=u2;
    u3_old=u3;
    %flux variables for predictor step 
    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
        
      %  calculating the source term j2 
        j2(j)=(1/gamma)*rho_c(j)*temp_c(j)*((a(j+1)-a(j))/dx);
        
       % continuity equation
        du1dt_p(j) = -(f1(j+1)-f1(j))/dx;
       % momentum equation 
        du2dt_p(j) = -((f2(j+1)-f2(j))/dx)+j2(j);
       % energy equation 
        du3dt_p(j) = -(f3(j+1)-f3(j))/dx;
        
        %solution update 
        u1(j)=u1_old(j) + (du1dt_p(j)*dt);
        u2(j)=u2_old(j) + (du2dt_p(j)*dt);
        u3(j)=u3_old(j) + (du3dt_p(j)*dt);
    
       
    end
    
   % decode the predicted values of primitive variables using u1 u2 u3 
        rho_c= u1./a;
        temp_c= (gamma-1)*((u3./u1)-(gamma/2)*(u2.^2./u1.^2));
        v_c= u2./u1;
        p_c=rho_c.*temp_c;
        
    %flux variables for corrector step (check)
    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
        
        % calculating the source term j2- updated 
        j2(j)=(1/gamma)*rho_c(j)*temp_c(j)*((a(j)-a(j-1))/dx);
        
        %continuity equation
        du1dt_c(j) = -(f1(j)-f1(j-1))/dx;
        %momentum equation 
        du2dt_c(j) = -((f2(j)-f2(j-1))/dx)+j2(j);
        %energy equation 
        du3dt_c(j) = -(f3(j)-f3(j-1))/dx;
    end
    
      %computing the average time derivative 
    du1dt= 0.5.*(du1dt_p + du1dt_c);
    du2dt= 0.5.*(du2dt_p + du2dt_c);
    du3dt= 0.5.*(du3dt_p + du3dt_c);
    
    %calculating the residual 
    du1dt_t(k)= du1dt(throat);
    du2dt_t(k)= du2dt(throat);
    du3dt_t(k)= du3dt(throat);
    
    %final solution update 
     for j=2:n-1
        u1(j)= u1_old(j) + (du1dt(j).*dt);
        u2(j)= u2_old(j) + (du2dt(j).*dt);
        u3(j)= u3_old(j) + (du3dt(j).*dt);
     end
     
     %applying boundary conditions
     %inlet 
     u1(1)=a(1);
     u2(1)=2*u2(2)-u2(3);
     v_c(1) = u2(1)/u1(1);
     u3(1)=u1(1)*((temp_c(1)/(gamma-1)) + 0.7*(v_c(1)^2));
     
     %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);
     
     % decode the predicted values of primitive variables using u1 u2 u3 
    rho_c= u1./a;
    temp_c= (gamma-1)*((u3./u1)-(gamma/2)*(u2.^2./u1.^2));
    v_c= u2./u1;
    p_c=rho_c.*temp_c;
     %mass flow rate m
     m_c=rho_c.*a.*v_c;
     %pressure ratio 
     p_c=rho_c.*temp_c;
     %mach no
     mach_no_c = v_c./sqrt(temp_c);

     %VALUEs at throat 
     rho_ct(k)=rho_c(throat);
     v_ct(k)=v_c(throat);
     temp_ct(k)=temp_c(throat);
     p_ct(k)=p_c(throat);
     mach_no_ct(k)=  mach_no_c(throat);
     m_ct(k)=m_c(throat);
     
      %plotting mass flow rate at different time steps 
    figure(2);
    if k==50
        plot(x,m_c,'color','b','linewidth',1.5);
        hold on 
    elseif k == 100
        plot(x,m_c,'color','g','linewidth',1.5);
        hold on 
    elseif k == 150
        plot(x,m_c,'color','y','linewidth',1.5);
        hold on 
    elseif k == 200
        plot(x,m_c,'color','black','linewidth',1.5);
        hold on 
    elseif k == 500
        plot(x,m_c,'color','cyan','linewidth',1.5);
        hold on 
    elseif k == 700
        plot(x,m_c,'color','r','linewidth',1.5);
        hold on 
    elseif k == 1400
        plot(x,m_c,'color','m','linewidth',1.5);
        grid on 
        title(' Conservative ')
    end
end
hold off
% 'Name','Mass flow rate at diff time step'
xlabel('non-dimensional flow throw the nozzle (x)');
ylabel('non-dimensional mass flow throw the nozzle (m)');
legend({'50 time steps','100 time steps','150 time steps','200 time steps','500 time steps','700 time steps','1400 time steps'});

figure(6)
semilogy(l,du1dt_t,'r');
hold on
semilogy(l,du2dt_t,'b');
semilogy(l,du3dt_t,'g');
xlabel('number of time steps ');
ylabel('values of residual at throat');
legend('du1dt','du2dt','du3dt');

title('Conservative')



end

   

RESULTS AND CONCLUSIONS

NON CONSERVATIVE

As you ca see in the graph that for each number of time steps how the flow is getting affected. At 50 time steps you can see it converge at a very slow rate, then at 1400 time steps you can see a straight line. this is what we needed to achieve. The above graph is of the non conservative code and the one below is the conservative code graph. they fairly show the same things happening.

CONSERVATIVE

RESIDUAL VALUES AT THROAT FOR BOTH CONSERVATIVE AND NON CONSERVATIVE CODES ARE BELOW.

COMPARISON OF VARIOUS PARAMETERS WRT NOZZLE DISTANCE.

the graph below shows how the quantities behave through the nozzle. they are density, temperature, pressure and mach number respectively.

(blue: Non conservative.)

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.