Challenge

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

In this work we will deal with deals with the quasi-one-dimensional flow through a convergent-divergent nozzle, we will choose a specific CFD technique ,and the solution will be set up and the procedure will be explained step by step.

We consider the steady, isentropic flow through a convergent-divergent nozzle. The flow at the inlet to the nozzle comes from a reservoir where the pressure and temperature are denoted by p0 , and To, respectively. The cross-sectional area of the reservoir is large ( theoretically, A --+ oo ), and hence thevelocity is very small ( V --+ O)

Simulating the flow through the nozzle by deriving the non-conservative equation and conservative form:

Discretisation methode used in this work is named The Macormac method which consist on:

Time marching solution, where we start with an initial conditions and we use it to calculate flow quantities in the next step.

Let F a variable.  We calculate from the governing equations using the forward differencing for space terms then we update  using the taylor series as follow ,then we calculate the corrector step from the governing equation .Then we finish by calculating .

predictor step usnig the forward differencing for space terms:

corrector step using the backward differncing for space terms

(partialv)/(partialx)=(v_i^n-v_(i-1)^n)/(Deltax)

Time derivative expressions:

1-non-conservative form

governing equation using The non-conservative equations to solve:

Equation of continuity:

momentum equation:

energy equation:

 ; .

these equations are hyperbolic equation.

Here is the sub program code to solve the non-conservative equation:

function [rho,t,v,a,Mfr_steps]=non_conservative1(n,nt)

% inputs  
x=linspace(0,3,n); 
gamma=1.4;
dx=x(2)-x(1);
c=0.5; %assumed CFL number
middle=(n+1)/2;

%Initial profiles
a=1+2.2*(x-1.5).^2;
rho = 1-0.3146*x;
t = 1-0.2314*x;
v =(0.1+1.09*x).*t.^0.5;


dt=min(c*dx./(t.^0.5+v));

for k=1:nt

    rhold=rho;
    vold=v;
    told=t;
    %part one
    %predictor step 
    for j=2:n-1
        dvdx=(v(j+1)-v(j))/dx;
        dlogdx=(log(a(j+1))-log(a(j)))/dx;
        drhodx=(rho(j+1)-rho(j))/dx;
        dtdx=(t(j+1)-t(j))/dx;

        %continuity
        drhodt_p(j)=-rho(j)*dvdx-rho(j)*v(j)*dlogdx-v(j)*drhodx;
        %momentum
        dvdt_p(j)=-v(j)*dvdx-(1/gamma)*(dtdx+(t(j)/rho(j))*drhodx);
        %energy
        dtdt_p(j)=-v(j)*dtdx-(gamma-1)*t(j)*(dvdx+v(j)*dlogdx);

        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
    
    %part 2
    %corrector step
    for j=2:n-1
    dvdx=(v(j)-v(j-1))/dx;
    dlogdx=(log(a(j))-log(a(j-1)))/dx;
    drhodx=(rho(j)-rho(j-1))/dx;
    dtdx=(t(j)-t(j-1))/dx;

    %continuity
    drhodt_c(j)=-rho(j)*dvdx-rho(j)*v(j)*dlogdx-v(j)*drhodx;
    %momentum
    dvdt_c(j)=-v(j)*dvdx-(1/gamma)*(dtdx+(t(j)/rho(j))*drhodx);
    %energy
    dtdt_c(j)=-v(j)*dtdx-(gamma-1)*t(j)*(dvdx+v(j)*dlogdx);


    end
    %part three
        %final solution update
    for i=2:n-1
        drhodt_avg(i)=0.5*(drhodt_p(i)+drhodt_c(i));
        dvdt_avg(i)=0.5*(dvdt_c(i)+dvdt_p(i));
        dtdt_avg(i)=0.5*(dtdt_c(i)+dtdt_p(i));
        rho(i)=rhold(i)+drhodt_avg(i)*dt;
        v(i)=vold(i)+dvdt_avg(i)*dt;
        t(i)=told(i)+dtdt_avg(i)*dt;
    end
    %part four
    %apply boundar conditions
    %outlet boudaries
    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);
    %Inlet boundaries
%    rho(1)=2*rho(2)-rho(3);
        v(1)=2*v(2)-v(3);
%    t(1)=2*t(2)-t(3);

        R=8.31;

        iter(k)=k;
        rho_t(k)=rho(15);
        v_t(k)=v(15);
        t_t(k)=t(15);
        
        % Mass flow rate distribution inside the nozzle  
    Mfr_steps=rho.*v.*a;
    
    if k==100
        D1=Mfr_steps;
    end
      
    if k==200
        D2=Mfr_steps;
    end
    
    if k==700
        D3=Mfr_steps;
    end
        
    if k==900
        D4=Mfr_steps;
    end
        
    if k==nt
         figure(4)
         plot(x,D1,'b')
         hold on
         plot(x,D2,'r')
         hold on
         plot(x,D3,'y')
         hold on
         plot(x,D4,'g')
         hold off
         gtext('100dt')
         gtext('200dt')
         gtext('700dt')
         gtext('900dt')
         title(' Mass flow rate distribution inside the nozzle at different time steps')     
    end
        
end         
%Time-wise variation of the primitive variables
figure(5)
subplot(3,1,1)
plot(iter,rho_t)
title('Time-wise variation of the primitive variables')
subplot(3,1,2)
plot(iter,v_t)
subplot(3,1,3)
plot(iter,t_t)
xlabel 'iteration'
    
%Steady-state distribution of primitive variables inside the nozzle
figure(6)
subplot(3,1,1)
plot(x,rho)
title('density inside the nozzle')
subplot(3,1,2)
plot(x,v)
title('velocity inside the nozzle')
subplot(3,1,3)
plot(x,t)
xlabel 'x'
title('temperature inside the nozzle')
end

 Code explanation:

In this code i started by giving the inputs and meshing the space we will working on, then i gived the initial conditions as intitial profiles for each variables Tempertature,density,velocity,area.

Then we we start a time for loop which includs three parts :Using the governing equations and expressions of forward differences we went to calculate the predictor step and update the earlier profiles of primitive variables. The second part was dedicated for backward differences to calculate the predictor step the third part part to give at the end of the day the final results for one time step, we apply boundarie condition to reach the values of each primitive variables in the boundaries by assuming that derivative of each variable at point n and at point n-1 are equale, the same for the side of subsonic flow the derivative at point 1 and point 2 are equal.

in the end we plot three figures as follow

Steady-state distribution of primitive variables inside the nozzle

 

2-conservative form :

the sub program code to solve the conservative equation:

function [rho,t,v,a,Mfr_steps]=conservative1(n,nt)




%conservative compution 

    gamma=1.4;
    x=linspace(0,3,n);
    dx=x(2)-x(1);
    dt=0.0267;
    middle=(n+1)/2;
    
    %intial density
    rho1=x(1:6).^0;
    rho2=1-0.366*(x(7:16)-0.5);
    rho3= 0.634 - 0.3879*(x(17:end) - 1.5);
    rho=[rho1,rho2,rho3];
    
    %initial temperature
    t1=x(1:6).^0;
    t2=1-0.167*(x(7:16)-0.5);
    t3= 0.833 - 0.3507*(x(17:end) - 1.5);
    t=[t1,t2,t3];
    
    %initial area:
    a=1+2.2*(x-1.5).^2;
    
    %initial velocity
    v=0.59./(rho.*a);
    
    %solution vector
    u1=rho.*a;
    u2=rho.*a.*v;
    u3=rho.*(t./(gamma-1)+0.5*gamma.*v.^2).*a;
    
    %flux terms
    
    
    %source term
%     dlogdx=log(a(2))-log(a);
%     j2=(1/gamma)*(gamma-1)*(u3-0.5*gamma*(u2.^2)./u1)*(1/dx).*(dlogdx);
    
    for i=1:nt
        
        f1=u2;
        f2=(u2.^2)./u1+(1-gamma^-1)*(u3-0.5*gamma*u2.^2./u1);
        f3=gamma*(u2.*u3)./u1-(0.5*gamma)*(gamma-1)*(u2.^3)./(u1.^2);
    
        u1old=u1;
        u2old=u2;
        u3old=u3;
        %predictor step
        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;
            
%             j2(j)=(1/gamma)*(gamma-1)*(u3(j)-0.5*gamma*(u2(j)^2)/u1(j))*(1/dx)*(log(a(j+1))-log(a(j)));
            j2(j)=(1/gamma)*rho(j)*t(j)*((a(j+1))-(a(j)))/dx;
            
            du1dt_p(j)=-df1dx;
            du2dt_p(j)=-df2dx+j2(j);
            du3dt_p(j)=-df3dx;
            
            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
            
        rho=u1./a;
        t=(gamma-1)*(u3./u1-0.5*gamma*v.^2);
        v=u2./u1;
        p=rho.*t;
            
        f1=u2;
        f2=((u2.^2)./u1)+((gamma-1)/gamma)*(u3-((gamma.*u2.^2)./(2*u1)));
        f3=(gamma*u2.*u3./u1)-(0.5*gamma)*(gamma-1)*(u2.^3)./(u1.^2);
            
            
        
        
        %corrector step
        for j=2:n-1
            
            j2(j)=(1/gamma)*rho(j)*t(j)*((a(j)-a(j-1))/dx);
            
            df1dx=(f1(j)-f1(j-1))/dx;
            df2dx=(f2(j)-f2(j-1))/dx;
            df3dx=(f3(j)-f3(j-1))/dx;
            
           
           
            du1dt_c(j)=-df1dx;
            du2dt_c(j)=-df2dx+j2(j);
            du3dt_c(j)=-df3dx;
            
        end
        
%             u1(j)=u1(j)+du1dt*dt;
%             u2(j)=u2(j)+du2dt*dt;
%             u2(j)=u3(j)+du3dt*dt;
        
          du1dt_avg=0.5*(du1dt_c+du1dt_p);
          du2dt_avg=0.5*(du2dt_c+du2dt_p);
          du3dt_avg=0.5*(du3dt_c+du3dt_p);
          
          for m=2:n-1
              u1(m)=u1old(m)+du1dt_avg(m)*dt;
              u2(m)=u2old(m)+du2dt_avg(m)*dt;
              u3(m)=u3old(m)+du3dt_avg(m)*dt;
          end
     %apply boundar conditions
%     outlet boudaries
        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);
        
%         f1(n)=u2(n);
%         f2(n)=u2(n)^2/u1(n)+(gamma-1)*(u3(n)-0.5*gamma*u2(n)^2/u1(n))/gamma;
%         f3(n)=gamma*(u2(n)*u3(n))/u1(n)-0.5*gamma*(gamma-1)*u2(n)^3/u1(n)^2;
        
        

%     Inlet boundaries
        u1(1)=rho(1).*a(1);
        u2(1)=2*u2(2)-u2(3);
        u3(1)=u1(1)*(t(1)/(gamma-1)+0.5*gamma*v(1)^2);
        
%         f1(1)=u2(1);
%         f2(1)=u2(1)^2/u1(1)+(gamma-1)*(u3(1)-0.5*gamma*u2(1)^2/u1(1))/gamma;
%         f3(1)=gamma*(u2(1)*u3(1))/u1(1)-0.5*gamma*(gamma-1)*u2(1)^3/u1(1)^2;
        
        rho=u1./a;
        t=(gamma-1)*(u3./u1-0.5*gamma*(u2./u1).^2);
        v=u2./u1;
        
        
        %distribution of primitive variables inside the nozzle
        
        
        %Time-wise variation of the primitive variables
        time=1:1:nt;
        
        rho_middle(i)=rho(middle);
        t_middle(i)=t(middle);
        v_middle(i)=v(middle);
        Mfr_middle(i)=rho(middle)*a(middle)*v(middle);
        

        
      
        % Variation of Mass flow rate distribution inside the nozzle at different time steps 
        %during the time-marching process
        Mfr_steps=rho.*v.*a;
        
        if i==100
            D1=Mfr_steps;
        end
       
        if i==200
            D2=Mfr_steps;
        end
        
        if i==700
            D3=Mfr_steps;
        end
        
        if i==900
            D4=Mfr_steps;
        end
        
        if i==nt
             figure(3)
             plot(x,D1,'b')
             hold on
             plot(x,D2,'r')
             hold on
             plot(x,D3,'y')
             hold on
             plot(x,D4,'g')
             hold off
             gtext('100dt')
             gtext('200dt')
             gtext('700dt')
             gtext('900dt')
             title(' Mass flow rate distribution inside the nozzle at different time steps')
        end
         
         
        %legend('100','200','700','1000')
        
    
    
    end
        figure(1)
        title('distribution of primitive variables inside the nozzle');
        
        subplot(3,1,1)
        plot(x,rho)
        xlabel 'grid points'
        ylabel 'rho/rho_{0}'
        
        subplot(3,1,2)
        plot(x,t)
        xlabel 'grid points'
        ylabel 't/t_{0}'
        
        subplot(3,1,3)
        plot(x,v)
        xlabel 'grid points'
        ylabel 'v/v_{0}'
        
        figure(2)
        subplot(4,1,1)
        plot(rho_middle)
        xlabel 'iteratio n°'
        ylabel 'p/p_{0}'
        
        
        subplot(4,1,2)
        plot(t_middle)
        xlabel 'iteratio n°'
        ylabel 't/t_{0}'
        
        
        subplot(4,1,3)
        plot(v_middle)
        xlabel 'iteratio n°'
        ylabel 'v/v_{0}'
        
        
        subplot(4,1,4)
        plot(Mfr_middle)
        xlabel 'iteratio n°'
        ylabel 'Mfr/Mfr_{0}'
        
                figure(2)
        subplot(4,1,1)
        plot(rho_middle)
        xlabel 'iteratio n°'
        ylabel 'p/p_{0}'
        
        
        subplot(4,1,2)
        plot(t_middle)
        xlabel 'iteratio n°'
        ylabel 't/t_{0}'
        
        
        subplot(4,1,3)
        plot(v_middle)
        xlabel 'iteratio n°'
        ylabel 'v/v_{0}'
        
        
        subplot(4,1,4)
        plot(Mfr_middle)
        xlabel 'iteratio n°'
        ylabel 'Mfr/Mfr_{0}'
       
        
        
        
end

 Code explanation:

the procedure i follow in this code si  the same as the earlier one .However, by referring to ANDERSON CFD book we didn't proceed to calculate directly the primitive variables but we introduced 6 variables which include in their inside all the primitive variables:

 

where U is the solution vector and Fthe flux vector and J the source term.

F1, F2, and F3 are couched in terms of the primitive variables, solving the governing equation by constructing F1,F2and F3 at each time step by primitive variables lead to some numerical difficulties until the blow up of the solution.

So we construct them like

with some rearangement we get:

 

we get by the end these plots:

The steady state of both conservative and non-conservative get reached in the same profile at the end

The main progaram that use these two sub program :

clear all 
close all
clc


nt=1000;
n=31;

 [rho_c,t_c,v_c,a_c,Mfr_c]=conservative1(n,nt);
% 
 [rho_n,t_n,v_n,a_n,Mfr_n]=non_conservative1(n,nt);

 
% exact analytical solution of p'A'V' = 0.579 
x=linspace(0,3,n); %meshing
e_a_s=0.579*ones(n); %exact analytical solution
figure(7)
title('Variation of mass flow distributi?n through the nozzle at different times')
hold on
plot(x,Mfr_c)
plot(x,Mfr_n)
plot(x,e_a_s)
xlabel 'x/L'
ylabel 'mass flow rate'
gtext('non-conservative resolver')
gtext('conservative resolver')
gtext('exact analytical solution')

we get this comparaison between the normalized mass flow rate of the conservative and non-conservative form :

we notice that the conservative form is more stable and close to to the exact analytical solution thus we called the "conservative form"

>> rho_exact=0.634;
>> rho_c(16)-rho_exact

ans =

    0.0147

>> rho_n(16)-rho_exact

ans =

    0.0047

>> t_exact=0.833;
>> t_c(16)-t_exact

ans =

    0.0061

>> t_n(16)-t_exact

ans =

    0.0034

>> 

comparing the results of primitive variables from the conservative and non-conservative form we can conclude that the non conservative form are more accurate than the conservative form.

Conclusion :

1-The conservation form yields a better mass flow distribution. The conservation form simply does a better job of conserving mass.
2-The nonconservation form leads to smaller residuals. The amount by which the residuals decay is often used as an index of "quality" of the numerical algorithm.In this sense, the nonconservation form does a better job.
3. There is no clear superiority of either form in terms of accuracy of the results. The nonconservation form seems to produce slightly more accurate results for the primitive variables, and the conservation form seems to produce slightly more accurate results for the flux variables. The results in either case are certainly satisfactory.

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.