Challenge

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

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

AIM

To simulate the isentropic flow through a quasi 1D subsonic-supersonic nozzle.

To determine the steady-state distribution of primitive variables inside the nozzle.

To simulate find Time-wise variation of the primitive variables.

To simuate the variation of Mass flow rate distribution inside the nozzle at different time steps during the time-marching process.

To compare the Normalized mass flow rate distributions of both forms.

DEFINITIONS OF THE TERMS USED

NOZZLE

A nozzle is a device which is used to give the direction to the gases coming out of the combustion chamber. Nozzle is a tube which has the capacity to convert the thermo-chemical energy generated in the combustion chamber into kinetic energy. The nozzle converts the low velocity, high pressure, high temperature gas in the combustion chamber into high velocity gas of lower pressure and low temperature. In a nozzle, the velocity of fluid increases at the expense of its pressure energy.

CONVERGENT DIVERGENT NOZZLE

An arrangement in which the forward portion of the nozzle is convergent, which increases the pressure of the exhaust gases, while the aft section is divergent to increase gas velocity to the supersonic speed and avoid losses from underexpansion.

SUBSONIC-SUPERSONIC NOZZLE

Convergent-divergent type of nozzles are mostly used for supersonic flows because it is impossible to create supersonic flows (mach number more than one) in convergent type of nozzle and therefore it restricts us to a limited amount of mass flow through a particular nozzle. In convergent-divergent type of nozzles we can increase the flow velocity much higher than sonic velocity that is why these type of nozzles have a wide applications such as propelling nozzles in jet engines or in air intake for engines working at high rpms.

FLOW FIELD VARIABLES

`T'=T/T_0`

`rho' = rho/rho_0`

`x' = x/L`

`a_0 = sqrt(gammaRT)`

`V' = V/a_0`

`t'=t/(L/a_0)`

`A' = A/Aast`

Where T is temperature, `rho` is density, X is length, V is velocity, `a_0`is velocity of sound, t is time and A is area, all are expressed in dimensionless form and are indicated using superscript`'`.

GOVERNING EQUATIONS

The flow field variables are expressed in non-dimensional form

NON-CONVECTIVE FORM

CONTINUITY - `(delrho')/(delt') = -rho'(delv')/(delx')-rho'V'del((lnA'))/(delx')-V'(delrho')/(delx')`

MOMENTUM - `(delV')/(delt') = -V'(delV')/(delx')-1/gamma((delT)/(delx')+(T')/(rho')(delrho')/(delx'))`

ENERGY - `(delT')/(delt')=-V'(delT')/(delx')-(gamma-1)T'[(delV')/(delx')+V'del((lnA'))/(delx')]`

CONSERVATIVE FORM

CONTINUITY - `del((rho'A'))/(delt')+del((rho'A'V'))/(delx')=0`

MOMENTUM - `del((rho'A'V'))/(delt')+del([rho'A'V'^2+(1/gamma)p'A'])/(delx') = 1/gammap'(delA')/(delx')`

ENERGY - `del([rho'((e')/(gamma-1)+gamma/2V'^2)A'])/(delt')+del([rho'((e')/(gamma-1)+gamma/2V'^2)V'A'+p'A'V'])/(delx')=0`

Simplifying the above equation

`U_1 = rho'A'`

`U_2=rho'A'V'`

`U_3 = rho'((e')/(gamma-1)+gamma/2V'^2)A'`

`F_1 = rho'A'V'`

`F_2 = rho'A'V'+1/gammap'A'`

F_3 = `rho'((e')/(gamma-1)+gamma/2V'^2)V'A'+p'A'V'`

`J_2 = 1/gammap'(delA')/(delx')`

Where `U_1,U_2,U_3` are the solution vectors and `F_1,F_2,F_3` are the flux vectors.

FORMULAS USED

MACCORMACK METHOD

The MacCormack method is an explicit finite difference technique which is a second order accurate in both space and time.

PREDICTOR STEP

The initial, "prediction" step, starts from a function fitted to the function-values and derivative-values at a preceding set of points to extrapolate ("anticipate") this function's value at a subsequent, new point.

Predictor step uses forward differencing for the space terms.

To get the final solution update `f_i=f_i+(delf)/(delt_p)Deltat`is used which is derived from Taylor series.

CORRECTOR STEP

Corrector step refines the initial approximation by using the predicted value of the function and another method to interpolate that unknown function's value at the same subsequent point.

It uses backward differencing for the space terms.

`(delf)/(delt_(avg)) = 0.5((delf)/(delt_p)+(delf)/(delt_c))` where `(delf)/(delt_p)`is the predictor time function and `(delf)/(delt_c)`is the corrector time function, which are derived using the space functions accordingly.

To get the final solution update `f_i=f_i+(delf)/(delt_(avg))Deltat`is used.

TIME STEP

`Deltat_i = C.(Deltax)/(a_i+v_i)`

where `a_i`is speed of sound

C is Courant number(CFL = 0.5)

`v_i`velocity

BASIC FORMULAS USED

Area = `1+2.2.(x-1.5)^2` `0lexle3`

Pressure = `rho.T`

Mass flow rate = `rho.A.V`

Mach no = `V/sqrtT`

BOUNDARY CONDITIONS

Boundary for conservative form

Inlet

`u1(1) = a(1);`

`u2(1)=2astu2(2)-u2(3);`

`u3(1)=2astu3(n-1)-u3(n-3);`

outlet conditions

`u1(n) = 2astu(n-1)-u1(n-2);`

`u2(n)=2astu2(n-1)-u2(n-2);`

`u3(n)=2astu3(n-1)-u3(n-2);`

Boundary for non-conservative

Inlet

`v(1)=2astv(2)-v(3);`

Outlet

`v(n)=2astv(n-1)-v(n-2)`

`rho(n)=2astrho(n-1)-rho(n-2)`

`t(n)=2astt(n-1)-t(n-2)`

MAIN PROGRAM

clear all
close all
clc

%inputs
n =31;
x = linspace(0,3,n);
dx =x(2)-x(1); %x(2)-x(1);
nt = 1400;
CFL = 0.5;
gamma = 1.4;
throat = 16;
[pressure,rho,t,v,mach_no,mass_flow_rate,throat_t,throat_pressure,throat_mass_flow_rate,throat_rho,throat_mach_no] = non_conservative(n,x,dx,nt,throat,CFL,gamma)
[con_pressure,con_rho,con_t,con_v,con_mach_no,con_mass_flow_rate,con_throat_mass_flow_rate,con_throat_pressure,con_throat_t,con_throat_rho,con_throat_mach_no] = conservative(n,x,dx,nt,throat,CFL,gamma)
        
        
figure(1)

figure(2)

figure(3)

figure(4)

figure(6)

figure(7)
plot(x,mass_flow_rate)
hold on
plot(x,con_mass_flow_rate)
xlabel('length of the nozzle')
ylabel('mass flow rate')
legend('non-conservative','conservative')
title('comparison of mass flow rate of conservative and non-conservative')

CODE EXPLANATION

The main program consists of the inputs such as number of nodes, length of the nozzle, distance between the grid points common for both forms and it calls the and executes the function and plots using it.

Non-Conservative function code explanation

Firstly, Non-Conservative functions calculates the initial profiles such as area, density, and pressure, etc and the time step using the formuals listed above.

Then, in the next step the time loop is executed, and a copy of the primitive variables is stored for the forthcoming use in finding the final exact values of the primitive variables.

After the previous step, discretization is done using the MacCormack method where the predictor step(the predictor and the corrctor formula is listed above) is executed, the solution is updated, which inturn is used in the corrector step and the solution for corrector step is also executed.

Following this, the arithmetic mean of predictor and corrector solution is executed and these values are used in calculating the final solution using the initial primitive variables.

Furthermore, the boundary values are updated and the mach number, pressure and mass flow rate values are executed using their basic formulas.

Finally, the throat values of all the primitive variables is found by assigning the throat node, which is 16 in this case.

Conservative function code explanation

The code for conservative function is similar to non-conservative, except instead of the primitive values being used solution vectors and flux variables(both list above) is used in the predictor and corrector step and these values are relatively used to find the primitive variables.

Finally, the plots are graphed comparing the variables as per the objective of the program.

Non_conservative function

function[pressure,rho,t,v,mach_no,mass_flow_rate,throat_t,throat_pressure,throat_mass_flow_rate,throat_rho,throat_mach_no] = non_conservative(n,x,dx,nt,throat,CFL,gamma)
% calculating Initial profiles
rho=1-0.3146*x;
t=1-0.2314*x;
v=(0.1+1.09*x).*(t).^0.5;

%area
a=1+2.2*(x-1.5).^2;
air = t.^(1/2);%speed of sound
dt = min((CFL*dx)./(v+air));

%time steps
 %outer time step
 for i=1:nt
    rho_old=rho;
    v_old=v;
    t_old=t;
%     %predictor method
    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;
        
        %contuinity 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+(t(j)/rho(j))*drhodx);       
        %energy equation
        dtdt_p(j)=-v(j)*dtdx-(gamma-1)*t(j)*((dvdx+v(j)*dlogadx));
         
    end
    
    for j=2:n-1
      %solution 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;
        
        %contuinity 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+(t(j)/rho(j))*drhodx);      
        %energy equation
        dtdt_c(j)=-v(j)*dtdx-(gamma-1)*t(j)*((dvdx+v(j)*dlogadx));
    end    
        %computing 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
        
        %applying the boundary condition
        %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);
        t(n)=2*t(n-1)-t(n-2);
        
        %calculating pressue, mass flow rate and mach no
        pressure = rho.*t;
        mach_no = v./(t.^(1/2));
        mass_flow_rate = rho.*a.*v;
        
        %assigning primitive variables at throat at node16
        throat_mach_no(i) = mach_no(throat);
        throat_t(i) = t(throat);
        throat_pressure(i) = pressure(throat);
        throat_rho(i) = rho(throat);
        throat_mass_flow_rate(i) = mass_flow_rate(throat);
        
        figure(3)
        if i==1
            plot(x,mass_flow_rate,'y')
            hold on
        elseif i==50
            plot(x,mass_flow_rate,'r')
            hold on
        elseif i==100
            plot(x,mass_flow_rate,'b')
            hold on
        elseif i==150
            plot(x,mass_flow_rate,'g')
            hold on
        elseif i==200
            plot(x,mass_flow_rate,'m')
            hold on
        elseif i ==700
            plot(x,mass_flow_rate,'c')
            hold on
            elseif i ==1400
                plot(x,mass_flow_rate,'k')
                hold on
        end
 end
legend('0dt','50dt','100dt','150dt','200dt','700dt','1400dt')
xlabel('non-dimensional mass flow')
ylabel('non-dimensional distance through nozzle')
title('Non-conservative: Variation of Mass flow rate distribution inside the nozzle at different time steps during the time-marching process')

        
figure(1)
%plotting steady state primitive variables 
subplot(4,1,1)
plot(x,mach_no,'g')
xlabel('length of the nozzle')
ylabel('mach no')
title('steady state distribution of primitive variables(Non-Conservative form)')
subplot(4,1,2) 
plot(x,t,'b')
xlabel('length of the nozzle')
ylabel('temperature rate')
subplot(4,1,3) 
plot(x,rho,'c')
xlabel('length of the nozzle')
ylabel('density rate')
subplot(4,1,4) 
plot(x,pressure,'r')
xlabel('length of the nozzle')
ylabel('pressure rate')

figure(2)
subplot(4,1,1) 
%plotting primitive variables        
plot(throat_mach_no,'g')
xlabel('time iterations')
ylabel('mach no')
title('timewise variations of primitive variables at throat(Non-Conservative form)')
subplot(4,1,2) 
plot(throat_t,'b')
xlabel('time iterations')
ylabel('temperature rate')
subplot(4,1,3) 
plot(throat_rho,'c')
xlabel('time iterations')
ylabel('density rate')
subplot(4,1,4) 
plot(throat_pressure,'r')
xlabel('time iterations')
ylabel('pressure rate')

end

Conservative function

function[con_pressure,con_rho,con_t,con_v,con_mach_no,con_mass_flow_rate,con_throat_mass_flow_rate,con_throat_pressure,con_throat_t,con_throat_rho,con_throat_mach_no] = conservative(n,x,dx,nt,throat,CFL,gamma)
%area
con_a = 1+2.2*((x-1.5).^2);
%initial conditions
for k = 1:n
    if x(k)>=0 && x(k)<=0.5
        con_rho(k)= 1;
        con_t(k)=1;
    elseif x(k)>=0.5 && x(k)<=1.5            
            con_rho(k) = 1-0.366*(x(k)-0.5);            
            con_t(k) = 1-0.167*(x(k)-0.5);
    elseif x(k)>=1.5 && x(k)<=3.5                
                con_rho(k) = 0.634-0.3879*(x(k)-1.5);
                con_t(k) = 0.833-0.3507*(x(k)-1.5);
    end
end
con_v = 0.59./(con_rho.*con_a);
%solution variables initialization
u1 = con_rho.*con_a;
u2 = con_rho.*con_v.*con_a;
u3 = con_rho.*((con_t/(gamma-1)+(gamma/2).*con_v.^2).*con_a);
air = con_t.^(1/2);%speed of sound
dt = min((CFL*dx)./(con_v+air));

%time step
for i = 1:nt
    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 step
    for j=2:n-1
        %space term
      %  j2(j)=(1/gamma)*(rho(j)*t(j))*((a(j)-a(j-1))/dx);  Forward differencing to be used
        j2(j)=(1/gamma)*(con_rho(j)*con_t(j))*((con_a(j+1)-con_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(j)+du1dt_p(j)*dt;
        u2(j) = u2(j)+du2dt_p(j)*dt;
        u3(j) = u3(j)+du3dt_p(j)*dt;
    end
        
        %updating primitive variables
        con_rho = u1./con_a;
        con_t = (gamma-1).*((u3./u1)-(gamma/2).*(u2./u1).^2);
        con_v = u2./u1;        
        
        %updating flux vectors
         f1 = u2;
         f2 = (u2.^2./u1)+((gamma-1)/gamma)*(u3-(gamma*u2.^2)./(2*u1));
         f3 = (gamma*u2.*u3)./u1-gamma*((gamma-1)/2)*(u2.^3./u1.^2);    
        
         %corrector method
         for j = 2:n-1
         j2(j)=(1/gamma)*(con_rho(j)*con_t(j))*((con_a(j)-con_a(j-1))/dx);  %Backward differencing
         %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
         
         %finding average time derivative
         du1dt_a = 0.5.*(du1dt_p+du1dt_c);
         du2dt_a = 0.5.*(du2dt_p+du2dt_c);
         du3dt_a = 0.5.*(du3dt_p+du3dt_c);
         
         %final solution update
         for j = 2:n-1
             u1(j) = u1_old(j)+du1dt_a(j)*dt;
             u2(j) = u2_old(j)+du2dt_a(j)*dt;
             u3(j) = u3_old(j)+du3dt_a(j)*dt;
         end
             
             %final update of premitive variables
             con_rho = u1./con_a;
             con_t = (gamma-1).*((u3./u1)-(gamma/2).*(u2./u1).^2);
             con_v = u2./u1;
             
             %boundary conditions
             %inlet
             u1(1)=con_a(1);
             u2(1)=2*u2(2)-u2(3);
             u3(1)=u1(1)*(con_t(1)/(gamma-1)+(gamma/2)*(con_v(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);
             
             %calculating pressure, mass flow rate,mach no
             con_pressure = con_rho.*con_t;
             con_mach_no = con_v./(con_t.^(1/2));
             con_mass_flow_rate = con_rho.*con_a.*con_v;
             
             %calculating pressure, mass flow rate,mach no at throat
             con_throat_mach_no(i) = con_mach_no(throat);
             con_throat_t(i) = con_t(throat);
             con_throat_pressure(i) = con_pressure(throat);
             con_throat_rho(i) = con_rho(throat);
             con_throat_mass_flow_rate(i) = con_mass_flow_rate(throat);
             
        figure(6)
        if i==1
            plot(x,con_mass_flow_rate,'y')
            hold on
        elseif i==50
            plot(x,con_mass_flow_rate,'r')
            hold on
        elseif i==100
            plot(x,con_mass_flow_rate,'b')
            hold on
        elseif i==150
            plot(x,con_mass_flow_rate,'g')
            hold on
        elseif i==200
            plot(x,con_mass_flow_rate,'m')
            hold on
        elseif i ==700
            plot(x,con_mass_flow_rate,'c')
            hold on
            elseif i ==1400
                plot(x,con_mass_flow_rate,'k')
                hold on
        end
end
        legend('0dt','50dt','100dt','150dt','200dt','700dt','1400dt')
        xlabel('non-dimensional mass flow')
        ylabel('non-dimensional distance through nozzle')
        title('conservative: Variation of Mass flow rate distribution inside the nozzle at different time steps during the time-marching process')
         figure(4)
        %plotting steady state primitive variables 
        subplot(4,1,1)       
        plot(x,con_mach_no,'g')
        xlabel('length of the nozzle')
        ylabel('mach no')
        title('steady state distribution of primitive variables(Conservative form)')
        subplot(4,1,2) 
        plot(x,con_t,'b')
        xlabel('length of the nozzle')
        ylabel('temperature rate')
        subplot(4,1,3) 
        plot(x,con_rho,'c')
        xlabel('length of the nozzle')
        ylabel('density rate')
        subplot(4,1,4) 
        plot(x,con_pressure,'r')
        xlabel('length of the nozzle')
        ylabel('pressure rate')
        
        figure(5)
        subplot(4,1,1) 
        %plotting primitive variables        
        plot(con_throat_mach_no,'g')
        xlabel('time iterations')
        ylabel('mach no')
        title('timewise variations of primitive variables at throat(Conservative form)')
        subplot(4,1,2) 
        plot(con_throat_t,'b')
        xlabel('time iterations')
        ylabel('temperature rate')
        subplot(4,1,3) 
        plot(con_throat_rho,'c')
        xlabel('time iterations')
        ylabel('density rate')
        subplot(4,1,4) 
        plot(con_throat_pressure,'r')
        xlabel('time iterations')
        ylabel('pressure rate')
end

FIGURE 1

NON-CONSERVATIVE: STEADY STATE DISTRIBUTION OF PRIMITIVE VARIABLES

FIGURE 2

NON-CONSERVATIVE: TIMEWISE VARIATIONS OF PRIMITIVE VARIABLES AT THROAT

FIGURE 3

NON-CONSERVATIVE: VARIATIONS OF MASS FLOW RATE AT DIFFERENT TIME STEPS DURING THE TIME MARCHING PROCESS

FIGURE 4

CONSERVATIVE: STEADY STATE DISTRIBUTION OF PRIMITIVE VARIABLES

FIGURE 5

CONSERVATIVE: TIMEWISE VARIATIONS OF PRIMITIVE VARIABLES AT THROAT

FIGURE 6

CONSERVATIVE: VARIATIONS OF MASS FLOW RATE AT DIFFERENT TIME STEPS DURING THE TIME MARCHING PROCESS

OBSERVATION

As seen in figure 1 and 4, all the primitive values such as density, temperature, pressure decreases along the length of the nozzle, but the mach no increases.

In figure 2 and 5, the primitive variables at different time steps shows there was some fluctuations in the initial steps and became steady which indicates the solution has reached steady state.

It can be observed from figure 3 and 6, there was no change in the mass flow rate after 700 iterations iteslf and the additional time steps until 1400 iterations remained same indicating the steady state achievement.

FIGURE 7

COMPARISON OF MASS FLOW RATE OF CONSERVATIVE AND NON-CONSERVATIVE

From figure 7, it can be seen that mass flow rate in more stable in conservative form as compared to the non-conservative form.

GRID INDEPENDENCE

By changing the number of nodes to 61 and the throat node we got sligtly better results.

The same is true for all locations within the nozzle. In short, the two steady state numerical solutions are essentilly the same, and therefore it can be concluded that the original calculations using 31 grid points is essentially grid-independent.

DEMONSTATION OF GRID INDEPENDENCE AT THE THROAT

FORMS `rho^ast/rho_0` `T^ast/T_0` `p^ast/p_0` `M`
CASE 1 :31 NODES

CONSERVATIVE FORM

NON-CONSERVATIVE

0.6525

0.6387

0.8413

0.8365

0.5487

0.5342

0.9780

0.9994

CASE 2: 61 NODES

CONSERVATIVE FORM

NON-CONSERVATIVE

0.5929

0.5940

0.8109

0.8121

0.4807

0.4824

1.0858

1.0826

EXACT ANALYTICAL SOLUTIONS - 0.634 0.833 0.528 1.000

From the above test we can can see that conservation form is time consuming but it's more stable than the non_conservative form.

The conservative form solutions are closer to the exact the solution.

CONCLUSION

The Non-Conservative is faster, easier and converges fast as the primitive variables are used directly.

While the conservation form produces more stable results as it uses flux variables.

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.