Challenge

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

the governing equation for conservative and non conservative forms

The initial profile for a, rho, t and v as it is defined in CFD book by John Anderson.

x = linspace(0,3,n);

% calculate intial profiles
rho = 1-0.3146*x;
t = 1-0.2314*x; % t = temprature
v = (0.1+1.09*x).*t.^0.5;

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

  • Non conservative governing equation of 1D supersonic nozzle flow:

The function talks n, nt, dt, gama, rho, t, v, a, and dx as inputs and massflow1, rho1, v1 and t1 as outputs. Then starting with for loop for total of time steps tn.

Inside this loop there is a second for loop for number of nodes “31” to calculate the predictor method for continuity, momentum, and energy equations.

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 equation
drhodt_p(j) = -rho(j)*dvdx - rho(j)*v(j)*dlogadx - v(j)*drhodx;

% momentum equation
dvdt_p(j) = -v(j)*dvdx - (1/gama)*(dtdx + (t(j)/rho(j))*drhodx);

% energy equation
dtdt_p(j) = -v(j)*dtdx - (gama -1)*t(j)*(dvdx + v(j)*dlogadx);

% 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

Then the corrector method loop which calculate the correction equation for continuity, momentum, and energy equations.

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 equation
drhodt_c(j) = -rho(j)*dvdx - rho(j)*v(j)*dlogadx - v(j)*drhodx;

% momentum equation
dvdt_c(j) = -v(j)*dvdx - (1/gama)*(dtdx + (t(j)/rho(j))*drhodx);

% energy equation
dtdt_c(j) = -v(j)*dtdx - (gama -1)*t(j)*(dvdx + v(j)*dlogadx);

end

The average of predictor and corrector method will be calculated.

drhodt = 0.5*(drhodt_p + drhodt_c);
dvdt = 0.5*(dvdt_p + dvdt_c);
dtdt = 0.5*(dtdt_p + dtdt_c);

Then the new rho, v, and t values should be updated.

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

At the end, the boundary condition for inlet and outlet will be updated. % 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);

Then rho, v, t, and massflow for each time iteration will be save in function outputs.

rho1(k,:) = rho;
v1(k,:) = v;
t1(k,:) = t;
massflow1(k,:) = rho.*a.*v;

  • Conservative method

The function has the same inputs and returns the same parameters.

To solve the conservative equation, I should define additional variables u1, u2, and u3.

u1 = rho.*a;
u2 = rho.*a.*v;
u3 = u1.*((t./(gama-1))+((gama/2).*(v.^2)));

Then inside a for loop for the number of time steps I defined the flux terms regarding new terms.

f1 = u2;
f2 = ((u2.^2)./u1)+(((gama-1)/gama)*(u3-((gama/2)*(u2.^2)./u1)));
f3 = ((gama*u2.*u3)./u1)-(gama*0.5*(gama-1)*(u2.^3)./(u1.^2));

After that inside a second for loop I calculated the predictor method for continuity, momentum, and energy equations. And updated the initial values as well. for j = 2:n-1

dadx = (a(j+1)-a(j))/dx;
j2 = (rho(j)*t(j)*dadx)/gama;
% continuity equation
du1dt_p(j) = -(f1(j+1)-f1(j))/dx;
% momentum equation
du2dt_p(j) = -(f2(j+1)-f2(j))/dx + j2;
% 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

Then the prediction of the primitive.

rho = u1./a;
v = u2./u1;
t = (gama-1)*((u3./u1)-((gama/2)*(v.^2)));
f1 = u2;
f2 = ((u2.^2)./u1)+(((gama-1)/gama)*(u3-((gama/2)*(u2.^2)./u1)));
f3 = ((gama*u2.*u3)./u1)-(gama*0.5*(gama-1)*(u2.^3)./(u1.^2));

The second stage of maccormack method is the correction equation for continuity, momentum, and energy equations which will be written in separated for loop.

for j = 2:n-1
dadx = (a(j)-a(j-1))/dx;
j2 = (rho(j)*t(j)*dadx)/gama;
% continuity equation
du1dt_c(j) = -(f1(j)-f1(j-1))/dx;
% momentum equation
du2dt_c(j) = -(f2(j)-f2(j-1))/dx + j2;
% energy equation
du3dt_c(j) = -(f3(j)-f3(j-1))/dx;

end

Finally calculate the average and the final solution for current 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

At the end applying the boundary conditions and return function outputs.

% inlet
u1(1) = rho(1)*a(1);
u2(1) = 2*u2(2) - u2(3);
v(1) = u2(1)/u1(1);
u3(1) = u1(1)*((t(1)/(gama-1))+((gama/2)*(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);

rho = u1./a;
v = u2./u1;
t = (gama-1)*((u3./u1)-((gama/2)*(v.^2)));

rho2(k,:) = rho;
v2(k,:) = v;
t2(k,:) = t;
massflow2(k,:) = rho.*a.*v;
Mach2(k,:) = v./(t.^0.5);

Conclusion:

The conversion time for both conservative and non-conservative forms are comparable about (tn=500).

There is not that big difference between the result of both forms.

The results also getting more accurate when the mesh is finer.

clear all
clear all
clc

% inputs
n = 31;
x = linspace(0,3,n);
dx = x(2)-x(1);
gama = 1.4;

% calculate intial profiles
rho = 1-0.3146*x;
t = 1-0.2314*x;  % t = temprature
v = (0.1+1.09*x).*t.^0.5;

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

% Time steps
nt = 1500;
dt = 0.01;
dt_min1 = min(0.5.*(dx./((t.^0.5)+v)));
[Mach1,massflow1,rho1,v1,t1] = non_conservative_maccormack(n,nt,dt_min1,gama,rho,t,v,a,dx);

% Initial profiles
for i=1:n
    if (x(i)>0 && x(i)<=0.5)
    rho(i) = 1;
    t(i) = 1;
    elseif (x(i)>0.5 && x(i)<=1.5)
        rho(i) = 1-0.366*(x(i)-0.5);
        t(i) = 1-0.167*(x(i)-0.5);
    elseif (x(i)>1.5 && x(i)<=3.5)
        rho(i)= 0.634-0.3879*(x(i)-1.5);
        t(i) = 0.833-0.3507*(x(i)-1.5);
    end

end
v = 0.59./(rho.*a);
dt = 0.0001;
% minimum time step for stabilation
dt_min2 = min(0.5*(dx./((t.^0.5)+v)));
[Mach2,massflow2,rho2,v2,t2] = conservative_maccormack(n,nt,dt_min2,gama,rho,t,v,a,dx);

figure(1)
plot(t1(1500,:),'color','r');
hold on
plot(t2(1500,:),'color','g');
xlabel('Distance from the inlet');
ylabel('Temperature');
title('Temperature comparison ');

figure(2)
plot(v1(1500,:),'color','r');
hold on
plot(v2(1500,:),'color','g');
xlabel('Distance from the inlet');
ylabel('massflow');
title('velocity comparison');

figure(3)
plot(rho1(1500,:),'color','r');
hold on
plot(rho2(1500,:),'color','g');
xlabel('Distance from the inlet');
ylabel('massflow');
title('Rho comparison');

figure(4)
plot(Mach1(1500,:),'color','r');
hold on
plot(Mach2(1500,:),'color','g');
xlabel('Distance from the inlet');
ylabel('massflow');
title('Mach comparison');

figure(5)
plot(massflow1(1500,:),'color','r');
hold on
plot(massflow2(1500,:),'color','g');
xlabel('Distance from the inlet');
ylabel('massflow');
title('Mass flow comparison');




figure(6)
plot(t1(:,10),'color','r');
hold on
plot(t2(:,10),'color','g');
xlabel('Time iterations');
ylabel('Temperature');
title('Temperature comparison at node 10');

figure(7)
plot(v1(:,10),'color','r');
hold on
plot(v2(:,10),'color','g');
xlabel('Time iterations');
ylabel('massflow');
title('velocity comparison at node 10');

figure(8)
plot(rho1(:,10),'color','r');
hold on
plot(rho2(:,10),'color','g');
xlabel('Time iterations');
ylabel('massflow');
title('Rho comparison at node 10');

figure(9)
plot(Mach1(:,10),'color','r');
hold on
plot(Mach2(:,10),'color','g');
xlabel('Time iterations');
ylabel('massflow');
title('Mach comparison at node 10');

figure(10)
plot(massflow1(:,10),'color','r');
hold on
plot(massflow2(:,10),'color','g');
xlabel('Time iterations');
ylabel('massflow');
title('Mass flow comparison at node 10');
function [Mach2,massflow2, rho2,v2,t2] = conservative_maccormack(n,nt,dt,gama,rho,t,v,a,dx)

     % initial solution
    u1 = rho.*a;
    u2 = rho.*a.*v;
    u3 = u1.*((t./(gama-1))+((gama/2).*(v.^2))); 
    
    % outer time loop
    for k = 1:nt

        %predictor method
        u1_old = u1;
        u2_old = u2;
        u3_old = u3;
        
        % flux terms regaeding new terms u1 u2 u3
        f1 = u2;
        f2 = ((u2.^2)./u1)+(((gama-1)/gama)*(u3-((gama/2)*(u2.^2)./u1)));
        f3 = ((gama*u2.*u3)./u1)-(gama*0.5*(gama-1)*(u2.^3)./(u1.^2));

        for j = 2:n-1

            dadx = (a(j+1)-a(j))/dx;
            j2 = (rho(j)*t(j)*dadx)/gama;
            % continuity equation
            du1dt_p(j) = -(f1(j+1)-f1(j))/dx;
            % momentum equation
            du2dt_p(j) = -(f2(j+1)-f2(j))/dx + j2;
            % 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
      
        % prediction of the primitves
        rho = u1./a;
        v = u2./u1;
        t = (gama-1)*((u3./u1)-((gama/2)*(v.^2)));
        f1 = u2;
        f2 = ((u2.^2)./u1)+(((gama-1)/gama)*(u3-((gama/2)*(u2.^2)./u1)));
        f3 = ((gama*u2.*u3)./u1)-(gama*0.5*(gama-1)*(u2.^3)./(u1.^2));
        % corrector method
        for j = 2:n-1
          
            dadx = (a(j)-a(j-1))/dx;
            j2 = (rho(j)*t(j)*dadx)/gama;
            % continuity equation
            du1dt_c(j) = -(f1(j)-f1(j-1))/dx;
            % momentum equation
            du2dt_c(j) = -(f2(j)-f2(j-1))/dx + j2;
            % energy equation
            du3dt_c(j) = -(f3(j)-f3(j-1))/dx;

        end

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

        % 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 the boundary conditions
        % inlet
        u1(1) = rho(1)*a(1);
        u2(1) = 2*u2(2) - u2(3);
        v(1) = u2(1)/u1(1);
        u3(1) = u1(1)*((t(1)/(gama-1))+((gama/2)*(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);
        
        rho = u1./a;
        v = u2./u1;
        t = (gama-1)*((u3./u1)-((gama/2)*(v.^2)));
        
        rho2(k,:) = rho;
        v2(k,:) = v;
        t2(k,:) = t;
        massflow2(k,:) = rho.*a.*v;
        Mach2(k,:) = v./(t.^0.5);
    end
end






function [Mach1,massflow1,rho1,v1,t1] = non_conservative_maccormack(n,nt,dt,gama,rho,t,v,a,dx)

    % outer time loop
    for k = 1:nt

        %predictor method
        rho_old = rho;
        v_old = v;
        t_old = t;

        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 equation
            drhodt_p(j) = -rho(j)*dvdx - rho(j)*v(j)*dlogadx - v(j)*drhodx;

            % momentum equation
            dvdt_p(j) = -v(j)*dvdx - (1/gama)*(dtdx + (t(j)/rho(j))*drhodx);

            % energy equation
            dtdt_p(j) = -v(j)*dtdx - (gama -1)*t(j)*(dvdx + v(j)*dlogadx);

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

            % 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/gama)*(dtdx + (t(j)/rho(j))*drhodx);

            % energy equation
            dtdt_c(j) = -v(j)*dtdx - (gama -1)*t(j)*(dvdx + v(j)*dlogadx);

        end

        % cmpute 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 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 the 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);
        t(n) = 2*t(n-1) - t(n-2);

        rho1(k,:) = rho;
        v1(k,:) = v;
        t1(k,:) = t;
        massflow1(k,:) = rho.*a.*v;
        Mach1(k,:) = v./(t.^0.5);
    end
end






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.