Challenge

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

The governing equations of a mathematical model describe how the values of the unknown variables (i.e. the dependent variables) change when one or more of the known (i.e. independent) variables change. It is divided into 2 types. They are

i Conservative form

ii Non-Conservative form

In the Conservative form, the control volume is stationary and in the Non-Conservative form, the control volume changes. Both are different only in the world of numerical discretization. But, the conservative form is more accurate and tend to work well than the Non-Conservative form.

The Governing Continuity, Energy, and Momentum equations for the quasi-1D, steady, isentropic flow can be expressed as

Continuity: `rho_1V_1A_1 = rho_2V_2A_2`

Energy: `h_1+V_1/2 = h_2+V_2/2`

Momentum: `P_1A_1+rho_1V_1^2A_1+intPdA = P_2A_2+rho_2V_2^2A_2`

There are different governing equations for Conservative and Non-Conservative form.

For Conservative form:

Continuity: `(del rho)/(del t) = -rho*(del v)/(del x) - rho*(v del(ln A))/(delx) - (vdelrho)/(delx)`

Energy: `(delv)/(delt) = -v*(delv)/(delx) - (1/gamma) *(((delT)/(delx))+(T/rho)*((delrho)/(delx)))`

Momentum: `(delT)/(delt) = -v(delT)/(delx)-(gamma-1)*T*((delv)/(delx)+v*(del lnA)/(delx))`

For Non-Conservative form:

Continuity: `del(rhoA)/(delt) + del(rhoAv)/(delx) = 0`

Energy: `(del(rhoAv))/(delt) + (del(rhoAv^2 + (1/gamma*pA)))/(delx) = 1/gamma*p*(delA)/(delx)`

Momentum: `(del(rhoA((e)/(gamma-1)+(gamma/2*v^2))))/(delt) + (del(rhoAv((e)/(gamma-1)+(gamma/2*v^2)+pAv)))/(delx) = 0`

After we got the governing equations, there are 3 types of steps to solve the problem.

i) Mesh ii) Discretise iii) solve(for this we require initial conditions and boundary conditions)

i) Mesh: A mesh is a barrier made of connected strands of metal, fiber, or other flexible or ductile materials. And it is similar to a web or a net in that it has many attached. Here it is a 1D problem so the x-axis is divided into n number of nodes. The 1st and the last nodes are known as the boundary conditions and the remaining nodes are known as inner nodes. The governing equations are solved only at the inner nodes because the values of the boundary conditions are specified or extrapolated.

ii) Discretise: For discretizing the inner nodes(grid points) of the x-axis, using the MacCormack's explicit method for the numerical solution of Continuity, Energy, and Momentum equations. MacCormack's method is a predictor-corrector method.

iii) Solve: Finally in the last step to solve the solution the boundary conditions for subsonic-supersonic isentropic flow and initial conditions for rho, T, v, and A are required. Here the rho and T decrease and v increases as the flow expands through the nozzle, hence we choose initial conditions that qualitatively behave in the same fashion.

Code for Conservative form:

function [rho2,T2,v2,m2,mach2,pr2,dx,rho_t2,T_t2,v_t2,m_t2,mach_t2,pr_t2] = conservative(x,n,throat)
  %n=61,
  %x= linspace(0,3,n);
  dx = x(2)-x(1);
  %throat = ((n-1)/2)+1;

%calculate initial values
for i = 1:n 
  if (x(i)>=0 && x(i)<=0.5)
    rho2(i) = 1;
    T2(i) = 1;   % T= temperature
   elseif (x(i)>=0.5 && x(i)<=1.5)
     rho2(i) = 1-0.366*(x(i)-0.5);
     T2(i) = 1-0.167*(x(i)-0.5);
   elseif (x(i)>=1.5 && x(i)<=3.5)
     rho2(i) = 0.634-0.3879*(x(i)-1.5);
     T2(i) = 0.833-0.3507*(x(i)-1.5);
   end
 
  end 
a = 1+2.2*(x-1.5).^2;  %  a = area
v2 = 0.59./(rho2.*a);
gamma = 1.4;


% vector parameters
u1 = rho2.*a;
u2 = rho2.*a.*v2;
u3 = u1.*((T2./(gamma-1))+((gamma/2)*(v2.^2)));

% time wrap 
 nt = 1400; 

% outer time loop 
for k = 1:nt

     dt = min(0.5.*(dx./((T2.^0.5)+v2)));
      
     u1_old = u1;
     u2_old = u2;
     u3_old = u3;  
  % pure form of the flux terms 
     f1 = u2;
     term = (((gamma-1)/gamma)*(u3-((gamma/2)*(u2.^2./u1))));
     f2 = ((u2.^2./u1)+term);
     f3 = ((gamma*u2.*u3)./u1)-(gamma*(gamma-1)*(u2.^3))./(2*u1.^2);
  
  % preditor methods
    
    for i = 2:n-1
      
      df1dx(i) = (f1(i+1)-f1(i))/dx;
      df2dx(i) = (f2(i+1)-f2(i))/dx;
      df3dx(i) = (f3(i+1)-f3(i))/dx;
     % dlogadx(i) = (log(a(i+1))-log(a(i)))/dx;
      
      % finally source term j2
      dadx(i) = (a(i+1)-a(i))/dx;
      j2(i) = (1/gamma)*(rho2(i)*T2(i))*dadx(i);
      
      % continuity equation
        du1dt_p(i) = -df1dx(i);
      % momentum equation
        du2dt_p(i) = -df2dx(i) + j2(i);
      % energy equation
        du3dt_p(i) = -df3dx(i);
        
        % solution update
        u1(i) = u1(i) + du1dt_p(i)*dt;
        u2(i) = u2(i) + du2dt_p(i)*dt;
        u3(i) = u3(i) + du3dt_p(i)*dt;
      end
    
  % decoding primitive terms to initialize the corrector step
    rho2 = u1./a;
    v2 = u2./u1;
    T2 = (gamma-1)*((u3./u1)-((gamma*v2.^2)/2));  

  % pure form of the flux terms 
     f1 = u2;
     term = (((gamma-1)/gamma)*(u3-((gamma/2)*(u2.^2./u1))));
     f2 = ((u2.^2./u1)+term);
     f3 = ((gamma*u2.*u3)./u1)-(gamma*(gamma-1)*(u2.^3))./(2*u1.^2);
  
  % preditor methods
    
    for i = 2 : n-1
      
      df1dx(i) = (f1(i)-f1(i-1))/dx;
      df2dx(i) = (f2(i)-f2(i-1))/dx;
      df3dx(i) = (f3(i)-f3(i-1))/dx;
      %dlogadx(i) = (log(a(i))-log(a(i-1)))/dx;
      
      % finally source term j2
      dadx(i) = (a(i)-a(i-1))/dx;
      j3(i) = (1/gamma)*(rho2(i)*T2(i))*dadx(i);
      
      % continuity equation
        du1dt_c(i) = -df1dx(i);
      % momentum equation
        du2dt_c(i) = -df2dx(i) + j3(i);
      % energy equation
        du3dt_c(i) = -df3dx(i);
    end    
        % average 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 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) = rho2(1)*a(1);
    u2(1) = 2*u2(2)-u2(3);
    v2(1) = u2(1)/u1(1);
    u3(1) = u1(1)*((T2(1)/(gamma-1))+((gamma/2)*v2(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);
   
   % decoding terms
   rho2 = u1./a;
   v2 = u2./u1;
   T2 = (gamma-1)*((u3./u1)-((gamma*v2.^2)/2)); 
   m2 = rho2.*v2.*a;
   mach2 = v2./((T2).^0.5); 
   pr2 = rho2.*T2; % pressure ratio
   
   % throat values
   rho_t2(k) = rho2(throat);
   T_t2(k) = T2(throat);
   v_t2(k) = v2(throat);
   m_t2(k) = m2(throat);
   mach_t2(k) = mach2(throat);
   pr_t2(k) = pr2(throat);
   
   
  figure(2) 
   if k == 50
     plot(x,m2, 'b','linewidth',1.5)
     hold on 
   elseif k == 100
     plot(x,m2, 'y','linewidth',1.5)
     hold on
   elseif k == 250
     plot(x,m2, 'r','linewidth',1.5)
     hold on
   elseif k == 500
     plot(x,m2, 'k','linewidth',1.5)
     hold on
   elseif k == 800
     plot(x,m2, 'c','linewidth',1.5)
     hold on
     elseif k == 1000
     plot(x,m2, 'g','linewidth',1.5)
     hold on
   elseif k == 1400
     plot(x,m2, 'm','linewidth',1.5)
     
     title('Mass flow rate(conservative form) along x, at different time steps')
     grid on
     xlabel('non-dimentional distance through nozzle');
     ylabel('non-dimentional mass flow rate');
     legend({'50 time steps','100 time steps','250 time steps','500 time steps','800 time steps','1000 time steps','1400 time steps'});
    end
end

Code for Non-Conservative form:

function [rho,T,v,m,mach,dx,pr,rho_t,T_t,v_t,m_t,mach_t,pr_t] = non_conservative(x,n,throat)
   
   n= 31;
  x= linspace(0,3,n);
  dx = x(2)-x(1);
  throat = ((n-1)/2)+1;
  
%calculate initial values
rho = 1-0.3146*x;
T = 1-0.2314*x;   % T= temperature
v = (0.1+1.09*x).*T.^0.5;
a = 1+2.2*(x-1.5).^2;  %  a = area
gamma = 1.4;

% time steps
nt= 1400;
dt = 0.01;


% outer time loop 
for k = 1:nt

     rho_old = rho;
     v_old = v;
     T_old = T;  
  
  % preditor methods
    
    for i = 2 : n-1
      
      dvdx = (v(i+1)-v(i))/dx;
      drhodx = (rho(i+1)-rho(i))/dx;
      dTdx = (T(i+1)-T(i))/dx;
      dlogadx = (log(a(i+1))-log(a(i)))/dx;
      
      % Continuity equation
      drhodt_p(i) = -rho(i)*(dvdx)- rho(i)*v(i)*dlogadx - v(i)*(drhodx);
      % Momemtum equation
      dvdt_p(i) = -v(i)*dvdx - (1/gamma)*(dTdx + (T(i)/rho(i))*(drhodx));
      % Energy equation
      dTdt_p(i) = -v(i)*dTdx - (gamma-1)*T(i)*(dvdx +v(i)*(dlogadx));
      
      % solution update
      rho(i) = rho(i) + drhodt_p(i)*dt;
      v(i) = v(i) + dvdt_p(i)*dt;
      T(i) = T(i) + dTdt_p(i)*dt;

  end 
  
  % corrector methods
    
    for i = 2:n-1
      
      dvdx = (v(i)-v(i-1))/dx;
      drhodx = (rho(i)-rho(i-1))/dx;
      dTdx = (T(i)-T(i-1))/dx;
      dlogadx = (log(a(i))-log(a(i-1)))/dx;
      
      % Continuity equation
      drhodt_c(i) = -rho(i)*(dvdx)- rho(i)*v(i)*dlogadx - v(i)*(drhodx);
      % Momemtum equation
      dvdt_c(i) = -v(i)*dvdx - (1/gamma)*(dTdx + (T(i)/rho(i))*(drhodx));
      % Energy equation
      dTdt_c(i) = -v(i)*dTdx - (gamma-1)*T(i)*(dvdx +v(i)*(dlogadx));
   
    end
     % compute the average time derivative
     
     drhodt = 0.5*(drhodt_p + drhodt_c);
     dvdt = 0.5*(dvdt_p + dvdt_c);
     dTdt = 0.5*(dTdt_p + dTdt_c);
     
     % final solution update
     for j= 2:n-1
       
      rho(j) = rho_old(j) + drhodt(j)*dt; 
      v(j)  = v_old(j) + dvdt(j)*dt;
      T(j)  = T_old(j) + dTdt(j)*dt;
     end 
   
   % apply boundary conditions
   % inlet
   v(1) = 2*v(2)-v(3);
   
   % 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);

   % calculate solution
   m = rho.*v.*a;
   pr = rho.*T;
   mach = v./((T).^0.5);
   
   % throat values
   rho_t(k) = rho(throat);
   T_t(k) = T(throat);
   v_t(k) = v(throat);
   m_t(k) = m(throat);
   mach_t(k) = mach(throat);
   pr_t(k) = pr(throat);
      
   figure(1)
  if k == 50
     plot(x,m, 'b','linewidth',1.5)
     hold on 
   elseif k == 100
     plot(x,m, 'y','linewidth',1.5)
     hold on
   elseif k == 250
     plot(x,m, 'r','linewidth',1.5)
     hold on
   elseif k == 500
     plot(x,m, 'k','linewidth',1.5)
     hold on 
   elseif k == 800
     plot(x,m, 'c','linewidth',1.5)
     hold on   
   elseif k == 1000
     plot(x,m, 'g','linewidth',1.5)
     hold on
   elseif k == 1400
     plot(x,m, 'm','linewidth',1.5)
  
     grid on
     title('Mass flow rate(non-conservative form) along x, at different time steps')
     xlabel('non-dimentional distance through nozzle');
     ylabel('non-dimentional mass flow rate');
     legend({'50 time steps','100 time steps','250 time steps','500 time steps','800 time steps','1000 time steps','1400 time step'});
    end 
end

Main code:

clear all
close all  
clc

% inputs 
  n = 31;
  x = linspace(0,3,n);
  throat = ((n-1)/2)+1;
  nt=1400;
 
 tic
 % function for non-conservative form
 [rho,T,v,m,mach,pr,dx,rho_t,T_t,v_t,m_t,mach_t,pr_t] = non_conservative(x,n,throat);

 % calculating the simulation
 non_conservative_simulation_time = toc

 tic 
 % function for conservative form
 [rho2,T2,v2,m2,mach2,pr2,dx,rho_t2,T_t2,v_t2,m_t2,mach_t2,pr_t2] = conservative(x,n,throat);

 % calculating the simulation
 conservative_simulation_time = toc 
 
 figure(3)
  plot(x,m,'r','linewidth',1.5)
  hold on
  plot(x,m2,'b','linewidth',1.5)
  hold on
  plot(x,linspace(0.579,0.579,n),'color','k','--','LineWidth',1.5)
  xlabel('non-dimentional distance through nozzle(x)')
  ylabel('non-dimentional mass flow rate')
  s= legend('non-conservative','conservative','exact solution')
   set(s,'location','northeast')
  title('non-dimentional mass flow rate comparision')
  grid on
   
  figure(4)
   a=subplot(4,1,1)
   plot(x,mach)
   hold on 
   plot(x,mach2,'color','r','*','MarkerSize',3) 
   s=legend(a,{'non-conservative','conservative'})
   set(s,'location','northeastoutside')
   title('variation of flow along x axis')
   grid on
   pause(0.03)
   ylabel('mach')
   
   b=subplot(4,1,2)
   plot(x,rho)
   hold on 
   plot(x,rho2,'color','r','*','markersize',3) 
   s=legend(b,{'non-conservative','conservative'})
   set(s,'location','northeastoutside')
   grid on
   pause(0.03)
   ylabel('rho')
   
   c=subplot(4,1,3)
   plot(x,T,'b','linewidth',1)
   hold on 
   plot(x,T2,'color','r','*','markersize',3) 
   pause(0.03)
   s=legend(c,{'non-conservative','conservative'})
   set(s,'location','northeastoutside')
   grid on 
   ylabel('T')
   
   d=subplot(4,1,4)
   plot(x,pr)
   hold on 
   plot(x,pr2,'color','r','*','markersize',3) 
   grid on
   s=legend(d,{'non-conservative','conservative'})
   set(s,'location','northeastoutside')
   pause(0.03)
   xlabel('non dimentional lenngth')
   ylabel('pr')
 
  figure(5)
  subplot(4,1,1)
  plot(linspace(1,nt,nt),rho_t)
  hold on
  plot(linspace(1,nt,nt),rho_t2,'color','r')
  hold on
  plot(linspace(nt-400,nt+200,600),linspace(0.634,0.634,600),'color','k')
  hold on
  title('Timewise variation flow at the nozzle throat')
  xlabel('no. of time steps')
  ylabel('rho')
  s=legend({'non-conservative','conservative','analytical solution'})
  set(s,'location','northeastoutside')
  grid on
  
  subplot(4,1,2)
  plot(linspace(1,nt,nt),T_t)
  hold on
  plot(linspace(1,nt,nt),T_t2,'color','r')
  hold on
  plot(linspace(nt-400,nt+200,600),linspace(0.833,0.833,600),'color','k')
  hold on
  xlabel('no. of time steps')
  ylabel('T')
  s=legend({'non-conservative','conservative','analytical solution'})
  set(s,'location','northeastoutside')
  grid on
  
  subplot(4,1,3)
  plot(linspace(1,nt,nt),pr_t)
  hold on
  plot(linspace(1,nt,nt),pr_t2,'color','r')
  hold on
  plot(linspace(nt-400,nt+200,600),linspace(0.528,0.528,600),'color','k')
  hold on
  xlabel('no. of time steps')
  ylabel('pr')
  s=legend({'non-conservative','conservative','analytical solution'})
   set(s,'location','northeastoutside')
  grid on
  
  subplot(4,1,4)
  plot(linspace(1,nt,nt),mach_t)
  hold on
  plot(linspace(1,nt,nt),mach_t2,'color','r')
  hold on
  plot(linspace(nt-400,nt+200,600),linspace(1,1,600),'color','k')
  hold on
  xlabel('no. of time steps')
  ylabel('mach')
  s=legend({'non-conservative','conservative','analytical solution'})
   set(s,'location','northeastoutside')
  grid on
  

Non-dimensional mass flow rate along the length of the nozzle:

For Non-Conservative form:

From the following figure, it can be observed that the mass flow rate curves obtained from 800,1000 and 1400 time steps are almost overlaying in the same region.

So, after the 800-time steps, almost the steady-state is obtained for the non-conservative form.

For Conservative form:

From the following plot, it can be observed that the mass flow rate curve obtained for 500, 800, 1000, and 1400 time steps are almost overlying in the same region.

When compared to the non-conservative plot, the fluctuations are less severe in the conservative plot. But the initial conditions are different for the non-conservative and for the conservative forms, so comparing these two makes no sense.

Comparison of non-dimensional mass flow rate :

The conservative form of the equations does better results for the mass-flow rate than the non-conservative equations.

Because in the conservative form, the mass flow itself is one of the dependent variables in the equations while the dependent variables of the non-conservative form of the equations are the primitive variables.

Variation of flow along the x-axis:

After 1400 time steps are carried out by time marching, both the Non-conservative and conservative forms produce similar plots.

Time-wise variation flow along with the nozzle throat:

The below plots show the variation of rho, T, mach no., and p at the nozzle throat plotted versus the number of time steps. The non-conservative form generates better results for the primitive variables.

From the plots below, it can be seen that the steady-state is almost obtained after 600-time steps. The dashed lines to the right of the curves represent the exact values.

If n=61

If the n value is increased to 61 from 31.

For Non-Conservative form(n=61):

Comparing with the previous non-conservative(n-31) plot the 800, 1000, and 1400 time steps are overlaying and almost after 800-time steps the steady-state is obtained.

For Conservative form(n=61):

Comparison of non-dimensional mass flow rate(n=61):

Variation of flow along the x-axis(n=61):

Time-wise variation flow along with the nozzle throat(n=61):

Which one is faster?

If n=61

Non-conservative simulation time = 41.359

Conservative simulation time = 29.052

If n=31

Non-conservative simulation time = 36.179

Conservative simulation time = 16.258

Finally, n=31 shows the fastest result.

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.