MATH76110/05/2018

Lab06: Multidimensional finite difference schemes for hyperbolic equations

1Approaches to discretization in multiple spatial dimensions

1.1Semi-discretization

Semi-discretization of the consdervation equation

𝒒t+𝒇(𝒒)x+π’ˆ(𝒒)y=0

leads to the linearized ODE system

ddt𝑸=-𝐀𝑸-𝐁𝑸,𝐀=βˆ‚π’‡βˆ‚π’’,𝐁=βˆ‚π’ˆβˆ‚π’’.

that can be integrated in time using standard schemes. The methods are similar to those obtained in the one spatial dimension case. As an example, we'll consider the midpoint (leap-frog scheme)

    𝑸n+1=𝑸n-1-𝐀𝑸n-𝐁𝑸n.

1.2Taylor series

Taylor series expansion to second-order accuracy:

𝒒(t+k) = 𝒒+k𝒒t+k22𝒒tt 𝒒t = -𝐀𝒒x-𝐁𝒒y 𝒒tt = -𝐀(-𝐀𝒒x-𝐁𝒒y)x-𝐁(-𝐀𝒒x-𝐁𝒒y)y 𝒒tt = 𝐀2𝒒xx+(𝐀𝐁+𝐁𝐀)𝒒xy+𝐁2𝒒yy

1.3Dimensional splitting

The linearized equation leads to the solution

𝒒(t+k,x,y)=e-(π’œ+ℬ)k𝒒(t,x,y),π’œ=π€βˆ‚x,ℬ=πβˆ‚y.

The formal solution can be approximated by

𝒒(t+k,x,y)β‰…e-π’œke-ℬk𝒒(t,x,y),

or to higher order (Strang-splitting)

𝒒(t+k,x,y)β‰…e-ℬk/2e-π’œke-ℬk/2𝒒(t,x,y)

2Implementation

2.1Global definitions

A module is constructed with global definitions.

SELECTED_REAL_KIND(P,R) is a Fortran intrinsic function that returns the available type closest to the requested precision of P decimal digits and an exponent range R. Two, possibly different, precisions are defined for the dependent variables (q) and the independent variables (space, time).

2.2Time stepping

A common interface to all finite difference schemes:

method: scheme to apply

m: number of interior nodes

nSteps: number of time steps

cfl: CFL number

Q0,Q1: initial conditions

Q: final state after time stepping

Qlft: boundary values at left

Qrgt: boundary values at right

Internal variable declarations

Precomputation of common expresions

Start of SELECT statement

2.2.1FTCS

Carry out time steps.

For u>0, use specified left boundary value, extrapolate at right. For u<0 use specified right boundary value, extrapolate at left.

Qin+1=Qin-Ξ½2(Qi+1n-Qi-1n)

Stability.
Use Von Neumann analysis Qjn∼Gneijθ, with θ=ξh.

In[45]:=

Q[n_,j_,theta_] = G[n] Exp[I j theta]

G(n)eijΞΈ

In[46]:=

FTCS = Q[n+1,j,theta] - (Q[n,j,theta] - nu/2 (Q[n,j+1,theta]-Q[n,j-1,theta]))

12Ξ½(G(n)ei(j+1)ΞΈ-G(n)ei(j-1)ΞΈ)+G(n)(-eijΞΈ)+G(n+1)eijΞΈ

In[47]:=

expr = Expand[FTCS/G[n]] /. G[n+1]/G[n]->A

AeijΞΈ-12Ξ½ei(j-1)ΞΈ+12Ξ½ei(j+1)ΞΈ-eijΞΈ

In[48]:=

AmpFact[theta_] = Simplify[ComplexExpand[A /. Solve[expr == 0,A][[1,1]]]]

1-iΞ½sin(ΞΈ)

In[49]:=

The amplifcation factor is |A|β©Ύ1, hence the FTCS method is always unstable.

Modified equation.

In[10]:=

FTCS = s[t+k,x] - (s[t,x] - nu/2 (s[t,x+h]-s[t,x-h]))

12Ξ½(s(t,h+x)-s(t,x-h))+s(k+t,x)-s(t,x)

In[14]:=

mFTCS = Simplify[Normal[Series[FTCS,{k,0,2},{h,0,2}]]]

hΞ½s(0,1)(t,x)+12k2s(2,0)(t,x)+ks(1,0)(t,x)

From above series expansions find the modified equation

st+usx=-k2stt+π’ͺ(k2,h2)=-u2k2sxx+π’ͺ(k2,h2),

an advection-diffusion equation with negative diffusivity, again indicating instability of the FTCS method.

Qin+1=Qin-Ξ½(Qin-Qi-1n) for u>0

Qin+1=Qin-Ξ½(Qi+1n-Qin) for u<0

Stability.
Use Von Neumann analysis Qjn∼Gneijθ, with θ=ξh (assume u>0)

In[87]:=

Upwind = Q[n+1,j,theta] - (Q[n,j,theta] - nu (Q[n,j,theta]-Q[n,j-1,theta]))

Ξ½(G(n)eijΞΈ-G(n)ei(j-1)ΞΈ)+G(n)(-eijΞΈ)+G(n+1)eijΞΈ

In[88]:=

expr = Expand[Upwind/G[n]] /. G[n+1]/G[n]->A

AeijΞΈ-Ξ½ei(j-1)ΞΈ+Ξ½eijΞΈ-eijΞΈ

In[89]:=

AmpFact[theta_] = Simplify[TrigReduce[ComplexExpand[A /. Solve[expr == 0,A][[1,1]]]]]

-iΞ½sin(ΞΈ)+Ξ½cos(ΞΈ)-Ξ½+1

In[90]:=

A[theta_,nu_]=Sqrt[TrigReduce[ComplexExpand[AmpFact[theta] Conjugate[AmpFact[theta]]]]]

-2Ξ½2cos(ΞΈ)+2Ξ½2+2Ξ½cos(ΞΈ)-2Ξ½+1

In[93]:=

UpwindStabPlot=Plot[Table[A[theta,nu],{nu,0.1,1.0,0.1}],{theta,0,2Pi},

GridLines->Automatic,Axes->False,Frame->True,FrameLabel->{"theta","A(theta)"}];

Export["/home/student/courses/MATH761/lab05/UpwindStabPlot.pdf",UpwindStabPlot]

/home/student/courses/MATH761/lab05/UpwindStabPlot.pdf

In[94]:=

Figure 1. Upwind amplification factor obtained from Von Neumann analysis

Modified equation.

In[94]:=

Upwind = s[t+k,x] - (s[t,x] - nu (s[t,x]-s[t,x-h]))

Ξ½(s(t,x)-s(t,x-h))+s(k+t,x)-s(t,x)

In[96]:=

mUpwind = Simplify[Normal[Series[Upwind,{k,0,2},{h,0,2}]]]

-12h2Ξ½s(0,2)(t,x)+hΞ½s(0,1)(t,x)+12k2s(2,0)(t,x)+ks(1,0)(t,x)

In[97]:=

From above series expansions find the modified equation

st+usx=-k2stt+h2Ξ½2ksxx+π’ͺ(k2,h2)=12(-ku2+h2Ξ½k)sxx+π’ͺ(k2,h2)=Ξ½h22k(1-Ξ½)sxx+π’ͺ(k2,h2),

again an advection-diffusion equation with diffusivity

Ξ±=Ξ½h22k(1-Ξ½).

Note that the diffusivity is zero at CFL Ξ½=1. The analytical solution to

{ st+usx=Ξ±sxx s(t=0,x)=H(-x) .

is

s(t,x)=12[1+erf(x-ut4Ξ±t)],erf(x)=2Ο€0xe-ΞΎ2dΞΎ

In[99]:=

s[t_,x_]=(1+Erf[(x-u t)/Sqrt[4 alpha t]])/2

12(erf(x-tu2Ξ±t)+1)

In[100]:=

Simplify[ D[s[t,x],t] + u D[s[t,x],x] - alpha D[s[t,x],{x,2}] ]

0

In[101]:=

Qin+1=Qin-1-Ξ½(Qi+1n-Qi-1n)

Qin+1=Qin-1-Ξ½2(Qi+1n-Qi-1n)+Ξ½22(Qi+1n-2Qin+Qi-1n)

3Numerical experiments

Compilation of the above implementation leads to a Python-loadable module than can be used for numerical experiments.

Python]

from pylab import *

Python]

import os,sys

os.chdir('/home/student/courses/MATH761/lab05')

cwd=os.getcwd()

sys.path.append(cwd)

Python]

from lab05 import *

Python]

print scheme.__doc__

q = scheme(method,cfl,q0,q1,qlft,qrgt,[m,nsteps])

Wrapper for ‘‘scheme‘‘. Parameters ---------- method : input int cfl : input float q0 : in/output rank-1 array('d') with bounds (m + 2) q1 : in/output rank-1 array('d') with bounds (m + 2) qlft : input rank-1 array('d') with bounds (nsteps + 1) qrgt : input rank-1 array('d') with bounds (nsteps + 1) Other Parameters ---------------- m : input int, optional Default: (len(q0)-2) nsteps : input int, optional Default: (len(qlft)-1) Returns -------

q : rank-1 array('d') with bounds (m + 2)

Python]

3.1Discontinuous boundary condition

Study now the behavior for a discontinuous (shock) initial condition q(0,x)=H(-x). The upwind solution will be compared to the exact solution q(t,x)=H(ut-x) for the advection equation qt+uqx=0, and the exact solution

s(t,x)=12[1+erf(ut-x4Ξ±t)],erf(x)=2Ο€0xe-ΞΎ2dΞΎ

to the modified equation st+usx=Ξ±sxx, with artificial diffusivity

Ξ±=Ξ½h22k(1-Ξ½).

Python]

def f(x,kappa):

return zeros(size(x))

def g(t,kappa):

return (sign(t)+1)/2

u=1;

Python]

FTCS=1; Upwind=2; LaxFriedrichs=3; LeapFrog=4; LaxWendroff=5; BeamWarming=6;

Python]

kappa=4

Python]

3.1.1Upwind

Python]

method=Upwind

from math import erf

m=99; h=1./(m+1); x=arange(m+2)*h;

dcfl=0.2; tfinal=0.5;

clf();

qex=g(tfinal-x/u,kappa);

plot(x[1:m],qex[1:m],'k.'); s = zeros(size(x));

for cfl in arange(dcfl,1+dcfl,dcfl):

k=h*cfl/u; nSteps=ceil(tfinal/k); t=arange(nSteps+1)*k; kappa=4;

Q0=f(x,kappa); Q1=zeros(size(x));

Qlft=g(t,kappa); Qrgt=zeros(size(t));

Q1=scheme(method,cfl,Q0,Q1,Qlft,Qrgt);

alpha = max(cfl*h**2*(1-cfl)/(2*k),10**(-6));

y = (u*tfinal-x)/sqrt(4*alpha*tfinal);

for i in range(m+1):

s[i] = 0.5*(1+erf(y[i]));

plot(x[1:m],Q1[1:m],'b',x[1:m],s[1:m],'r.');

xlabel('x'); ylabel('q'); title('Shock propagation by upwind scheme');

savefig("Lab05UpwindShockInitCond.pdf");

Python]

Figure 2. The exact solution to the modified equation corresponds closely to the results from the upwind scheme