Sunteți pe pagina 1din 9

Alternating Direction Implicit (ADI) Methods

Pengfei Du

Mechanical engineering, University of Iowa

The problem to be solved is governed by the following equation

ut 2u x, y, t 0, lx 0, l y 0, t f

(1)

Where is a constant value (which is referred to as thermal diffusivity for heat


conduction problem). Physically this is the equation for transient heat conduction or
diffusion on a 2D domain. The definition of the complete problem is closed by
proper boundary and initial conditions.
The first discretization form one can think of is using forward difference
approximation for time derivative and central difference for spatial derivatives,
which is

uin1, j 2uin, j uin1, j uin, j 1 2uin, j uin, j 1


(2)

2
2

where n is time step index, x / y and t are spatial and time step length. This
uijn 1 uijn

discretization is explicit and stable only if t h2 4 where h min(x, y) .


You may also know Crank-Nicolson method which is an implicit method that
unconditionally stable.
Crank-Nicolson discretization:

uijn 1 uijn
t

u(i 1) j 2uij u(i 1) j


n

uin( j 1) 2uijn uin( j 1)

u(ni11) j 2uin, j 1 u(ni11) j

uin(j11) 2uin, j 1 uin(j11)

(3)

or

uijn1 Fox x2uijn1 Foy y2uijn1 uijn Fox x2uijn Foy y2uijn
where Fox

t
2 x

,Foy

t
2 y

(3)

If you are satisfied with an unconditionally stable scheme and dose not care
about the efficiency, Crank-Nicolson is one of the choices. The following will

introduce the alternating direction implicit (ADI) method which is also


unconditionally stable but more efficient comparing with Crank-Nicolson.
1. ADI using simple Peaceman-Rachford scheme
Now, we can factorize both the left and right hand side of equation (3). Then
we can factor both side to get

1 Fo 1 Fo u
2
x x

n 1
ij

2
y

1 Fox x2 1 Foy y2 uijn Fox Foy x2y2 uijn 1 uijn

(4)

This equation is then solved in splitting or fractional step methods. There are many
ways to accomplish the splitting. Peaceman-Rachford scheme is shown below

1 Fo u

1+ Foy y2 uijn

(5a)

1 Fo u

1+ Fox x2 uijn1/2

(5b)

n 1/2
ij

2
x

2
y

n 1
ij

It is clear that, instead of going directly from step n to n+1, we first get an
intermediate solution at (n+1/2) then to (n+1). To write down equation (5a) and
(5b) in a form that more suitable for programming, we need the following notations
(for now, neglect the boundary condition, we will fill in the boundary
conditions later.)

Ax

Fo 1 2 Fo
Fox
x
x

Fox
1 2 Fox Fox

Ay

Fo 1 2 Fo
Fo y
y
y

Fo y
1 2 Fo y Fo y

nxnx

nxnx

Ax

Fo 1 2 Fo
Fox
x
x
Fox
1 2 Fox

Fox

Ay

Fo 1 2 Fo
Fo y
y
y

Fo y
1 2 Fo y

nyny

nyny

Fo y

where nx is grid point number along x-direction and ny is the grid point number
along y-direction. With these notations, now we have

Ax uin; 1/2 Ay uin;

(6)

Ay u;nj1 Ax u;nj1/2

To solve equation (6) we have to be very careful with the boundary


conditions. Lets first consider the most easy Dirichlet boundary. To get the
boundary condition for the intermediate solution, we can flip equation (5b), add it
with equation (5a) and write the summation in the equivalent form:
n 1/2
ij

uijn uijn1
2

Foy y2 uijn uijn 1

(7)

For Dirichlet boundary condition, lets say at i=1, u1; B y, t , equation (7) yields

u1nj1/2

u1nj u1nj1
2

Fo y y2 u1nj u1nj1

B1nj B1nj1
2

Foy

n
1( j 1)

2 B1nj B1(n j 1) B1(n j11) 2 B1nj1 B1(n j11)


4
(8)

If B is constant, equation (8) is simply u1;n1/2 B1; , where ; denotes all possible
column numbers. An example code with such boundary conditions is attached to the
end of this write-up.
Neumann boundary is more complicated. Assume we have a Neumann
boundary at x=0 given by u y x,0, t g x,0, t where g(x,0,t) is a known function.
For those who are content with first order approximation, the discretization is given
by

uin,01 uin,11 yg ix,(n 1)t

(9)

If we use the second order approximation on the boundary, we have

uin,11 uin,11 2yg ix,0,(n 1)t

(10)

Substitute this equation into equation (5b) at j=0


n 1
;0

Foy

u;n11 2u;0n 1 u;1n 1


y 2

I + Fox x2 u;0n 1/2

to get

u;0n 1 Foy

u;1n1 2u;0n1 uin,11 2yg ix, (n 1)t


y

I + Fox x2 u;0n 1/2 (11)

or
n 1
;0

2 Foy

u;1n 1 u;0n 1
y

I + Fox x2 u;0n 1/2 2 Foy g ix, (n 1)t / y

(12)

If we have Neumann boundary conditions at i=0 or i=nx, we can switch the order of
(5a) and (5b), because there is no reason we should do the sweep along x or y in any
particular order. In this way, we can always have Neumann boundary at the n+1
time step.
2. Compact ADI scheme
High order finite difference schemes fall into two categories: explicit and
compact schemes. The explicit schemes approximate the derivatives by using large
stencils, while the compact schemes using smaller stencils with solving additional
linear systems. Here we only need the first and second order derivatives using the
sixth order accuracy formulas:

fi ' 1 fi ' fi ' 1 a


where 1/ 3; a

fi 1 fi 1
f f
b i 2 i 2
2h
4h

(13)

2
1
2 ; a 4 1 , and
3
3

fi '' 1 fi '' fi '' 1 a


where 2 /11; a

fi 1 2 fi fi 1
f 2 fi fi 2
b i2
2
h
4h2

(14)

4
1
1 ; a 10 1 .
3
3

Now, lets come back to the ADI scheme with the following splitting:

uijn 1/2 uijn


t 2

uijn 1 uijn 1/2


t 2

uxx ij

n 1/2

u yy

ij

uxx ij

n 1/2

uxx ij

(15)

n 1

(16)

where uijn 1/2 is a intermediate approximation and uijn 1 is the final solution. We can
substitute the second order derivatives with sixth-order compact formulas

uxx ; j A1Bu; j

and u yy C 1 Dui; . This substitution gives


i;

n 1/2
t
t 2 n
1
A
B
u
Ix
u, j u;nj
2
2 y ;j

2 x
2 x

(17)

n 1
t
t 2 n
1
C
D
u
Iy
ui ; uin, 1/2
2
2 x i;

2 y
2 y

(18)

where ui ; , u; j are the solution vectors at i-th row and j-th column, respectively.

ui''1 ui'' ui''1 a

ui 1 2ui ui 1

u ''j 1 u ''j u ''j 1 a


where a

u j 1 2u j u j 1

4 x

and

u j 2 2u j u j 2
4 y

4
1
2
1 and b 1 10 with . In more compact form, this is
3
3
11
Au '' Bu

where

ui 2 2ui ui 2

(19)

...

...

Nx Nx

...

B
2

...

Nx Nx
a
b
a
b
and
and
where
for x-direction and
for
2
2
2
2
4 x
4 y
x
y
y-direction sweep.
But in both A and B matrices, I did not show the boundary conditions. You
may refer to some papers on compact schemes. The result is presented below
without derivation. At first and second boundary layer:

f1'' f 2'' c1 f1 c2 f 2 c3 f3 c4 f 4 c5 f5 c6 f 6 c7 f 7 h 2
c1 2077 /157, c2 2943 /100, c3 573 / 44, c4 167 / 99,

(20)

c5 18 /11, c6 57 /110, c7 131/1980, 126 /11;


f1'' f 2'' f3'' c1 f1 c2 f 2 c3 f3 c4 f 4 c5 f5 c6 f 6 c7 f 7 h 2
c1 585 / 512, c2 141/ 64, c3 459 / 512, c4 9 / 3332,

(21)

c5 81/ 512, c6 3 / 64, c7 3 / 512, 11/128;


Similarly, on the boundary point n-1 and n, the sixth order formula is given by

f N'' 1 f N'' c1 f N c2 f N 1 c3 f N 2 c4 f N 3 c5 f N 4 c6 f N 5 c7 f N 6 h2

(22)

f N'' 2 f N'' 1 f N'' c1 f N c2 f N 1 c3 f N 2 c4 f N 3 c5 f N 4 c6 f N 5 c7 f N 6 h 2 (23)


In these two equations, the coefficients are from (20) and (21), respectively.
I had written a general purpose Java code using this compact ADI scheme. If
you want a copy of the code, you can send a request by email:
pengfeidu83@gmail.com.

Source code for ADI using Peaceman-Rachford scheme. The code is pretty much selfexplained.
//===========================================================================
// Name
: ADI.cpp
// Author : Pengfei Du, Mechanical Engineering, Univ. of Iowa.
// Website : http://pengfeidu.net/
// Description : Transient heat conduction problem solved using ADI scheme.
//
Initial inside temperature is 150;
//
All boundaries are Dirichlet boundaries kept at 50.
//
Calculation domain: x=[0:1] y=[0:1].
// NOTE: This is only a demonstration of Peaceman-Rachford scheme. It is
//
INEFFICIENT. To directly compile this short program, you need
//
TNT and JAMA libraries; otherwise, take this as a pseudo-code.
//===========================================================================
#include <iostream>
#include <fstream>
#include "tnt.h"
#include "jama_lu.h"
#include <iomanip>
using namespace TNT;
using namespace std;
using namespace JAMA;
int main()
{
ofstream result;
int i,j,Nx,Ny;
double fox,foy,dt,Time,dx,dy,Lx,Ly,alpha;
Nx=11,Ny=12; //node numbers along length and width;
//set Nx Ny to be different on purpose; You should think
//about this carefully to make sure you understand ADI scheme.
dt=0.01; //time step;
Time=0.2; //end of time evolving;
Lx=1.,Ly=1.; //domain length and width;
dx=Lx/(Nx-1),dy=Ly/(Ny-1);
alpha=.2; //thermal diffusivity;
fox=alpha*dt/2./dx/dx,foy=alpha*dt/2./dy/dy;
Array2D< double > Ax_m(Nx,Nx),Ay_m(Ny,Ny),Ax_p(Ny,Ny),Ay_p(Nx,Nx),u(Nx,Ny),
ulast(Nx,Ny),ulastT(Ny,Nx),uT(Ny,Nx);
result.open("result.txt");
for(i=0;i<Nx;i++)
{
for(j=0;j<Ny;j++)
{
u[i][j]=150.; //initial temperature;
ulast[i][j]=150.; //storage of intermediate temperature results;
if(i==0||i==Nx-1||j==0|j==Ny-1){
u[i][j]=50.; //set the temperature on the boundaries;
ulast[i][j]=50.;
}
}
}
for(i=0;i<Ny;i++)

{
for(j=0;j<Ny;j++)
{
Ay_m[i][j]=0.;
Ax_p[i][j]=0.;
}
}
for(i=0;i<Nx;i++)
{
for(j=0;j<Nx;j++)
{
Ax_m[i][j]=0.;
Ay_p[i][j]=0.;
}
}
for(i=1;i<Nx-1;i++)
{
Ax_m[i][i]=1+2*fox;
Ax_m[i][i-1]=-fox;
Ax_m[i][i+1]=-fox;
}
//left and right boundary, constant temperature = 50;
Ax_m[0][0]=1;
Ax_m[Nx-1][Nx-1]=1;
for(i=1;i<Ny-1;i++)
{
Ax_p[i][i]=1-2*fox;
Ax_p[i][i-1]=fox;
Ax_p[i][i+1]=fox;
}
Ax_p[0][0]=1;
Ax_p[Ny-1][Ny-1]=1;
for(i=1;i<Ny-1;i++)
{
Ay_m[i][i]=1+2*foy;
Ay_m[i][i-1]=-foy;
Ay_m[i][i+1]=-foy;
}
//top and bottom boundary, constant temperature = 50;
Ay_m[0][0]=1;
Ay_m[Ny-1][Ny-1]=1;
for(i=1;i<Nx-1;i++)
{
Ay_p[i][i]=1-2*fox;
Ay_p[i][i-1]=fox;
Ay_p[i][i+1]=fox;
}
Ay_p[0][0]=1;
Ay_p[Nx-1][Nx-1]=1;
LU<double> matAx_m(Ax_m);
LU<double> matAy_m(Ay_m);
LU<double> matAx_p(Ax_p);

LU<double> matAy_p(Ay_p);
for (float clock=0;clock<Time;clock=clock+dt){
u=matAx_m.solve(matmult(Ay_p,ulast));
for(j=0;j<Ny;j++){
for(i=0;i<Nx;i++){
uT[j][i]=u[i][j];
}
}
ulastT=matAy_m.solve(matmult(Ax_p,uT));
for(j=0;j<Ny;j++){
for(i=0;i<Nx;i++){
ulast[i][j]=ulastT[j][i];
}
}
result<<"#"<<clock/dt<<endl;
for(j=0;j<Ny;j++){
for(i=0;i<Nx;i++){
result<<setw(7)<<i*dx<<" "<<j*dy<<" "<<ulast[i][j]<<endl;
}
result<<endl;
}
result<<endl;
result<<endl;
}
result.close();
cout<<"Calculation done!";
return 0;
}

S-ar putea să vă placă și