You are on page 1of 14

Diffusion Equation Example Using Isoparametric Elements

Let D = {(x, y) : 0 < x, y < 1} be the unit square, and consider the boundary-initial value problem
u
u = 0, (x, y) D, t > 0,
t
u(x, y, 0) = 0, u(x, 0, t) = 0, u(x, 1, t)/y = x, 0 x 1, t > 0 and u(0, y, t) = 0, u(1, y, t)/x =
y, 0 y 1, t > 0. The weak form of this problem is
Z
Z 1
Z 1
Z
u(1, y, t)
u(x, 1, t)
u
v
v
dA +
v u dA =
dy +
dx
v
x
y
0
0
D
D t
Pn
Using bilinear elements we take u = j=1 uj (t)j (x, y), v = i (x, y), i = 1, . . . , n (We ignore boundary conditions for the moment, as usual, these will be imposed near the end of the computation.)
This assumption leads to the element mass and stiffness matrices

Z
Z 
H e (H e )T
H e (H e )T
+
dA
m=
H e (H e )T dA, k =
x
x
y
y
De
De
where H e = [H1e (x, y), . . . , H4e (x, y)]T is the element shape function vector. The two contributions
to the element load vectors are of the form

0
0
Z ye+1 Z xe+1
Z ye+1
Z xe+1
Z xe+1
e
0

H2 (x, 1)
y dy =
H e (x, 1)x dx =
e
y dy,
e
x dx
H
(1,
y)
H3 (x, 1)
3
ye
xe
ye
xe
xe
H4e (1, y)
0
Because the shape functions are bilinear, the Hke (1, y), Hje (x, 1) are linear functions of their arguments. In this particular problem the boundary contributions to the element load functions are
independent of time in the general case these contributions can depend on time. We can now build
a Matlab file to solve this initial boundary value problem based on our Textbook files from Chapters
5 and 6. (All files necessary to compile this example are included below with the exception of the
utility files gridgen.m, gridplot.m.)
function heat_eq(nx,ny)
%----------------------------------------------------------------------------% Based on Textbook Example 6.6.2
%
to solve the two-dimensional Laplaces equation given as
%
u,t-u,xx - u,yy =0, 0 < x < 1, 0 < y < 1
%
u(x,0) = 0, u,y(x,1) = x
%
u(0,y) = 0, u,x(1,y) = y
%
u(x,y,0)=0
%
using isoparametric four-node quadrilateral elements
%
% Variable descriptions
%
k = element matrix
%
f = element vector
%
kk = system matrix
%
ff = system vector
%
gcoord = coordinate values of each node
%
nodes = nodal connectivity of each element

%
index = a vector containing system dofs associated with each element
%
bcdof = a vector containing dofs associated with boundary conditions
%
bcval = a vector containing boundary condition values associated with
%
the dofs in bcdof
%
point2 - integration (or sampling) points
%
weight2 - weighting coefficients
%
nglx - number of integration points along x-axis
%
ngly - number of integration points along y-axis
%
xcoord - x coordinate values of nodes
%
ycoord - y coordinate values of nodes
%
jacob2 - jacobian matrix
%
shape - four-node quadrilateral shape functions
%
dhdr - derivatives of shape functions w.r.t. natural coord. r
%
dhds - derivatives of shape functions w.r.t. natural coord. s
%
dhdx - derivatives of shape functions w.r.t. physical coord. x
%
dhdy - derivatives of shape functions w.r.t. physical coord. y
%----------------------------------------------------------------------------%-----------------------------------% input data for control parameters
%-----------------------------------bl=[0,0]; ur=[1,1];
nx1=nx+1; ny1=ny+1;
nel=nx*ny;
nnel=4;
ndof=1;
nnode=nx1*ny1;
nglx=2; ngly=2;
sdof=nnode*ndof;
edof=nnel*ndof;

% number of elements
% number of nodes per element
% number of dofs per node
% total number of nodes in system
% use 2x2 integration rule
% total system dofs
% dofs per element

deltt=0.04;
% time step size for transient analysis
stime=0.0;
% initial time
ftime=4;
% termination time
ntime=fix((ftime-stime)/deltt); % number of time increment
%--------------------------------------------% input data for nodal coordinate values
% gcoord(i,j) where i->node no. and j->x or y
% nodes(i,j) where i-> element no. and j-> connected nodes
%--------------------------------------------[gcoord,nodes]=gridgen(bl,ur, nx, ny, 1);
gridplot(nx, ny, gcoord, nodes, 1);
input(press any key to continue);
close all
%------------------------------------% input data for boundary conditions
%------------------------------------bcdof=[1:nx1,1+nx1:nx1:nx1*ny1-nx];

nbcdof=length(bcdof);
bcval=zeros(1,nbcdof);
%----------------------------------------% initialization of matrices and vectors
%----------------------------------------ff=zeros(sdof,1);
% initialization of system force vector
kk=zeros(sdof,sdof);
% initialization of system matrix
mm=zeros(sdof,sdof);
% initialization of system mass matrix
index=zeros(nnel*ndof,1); % initialization of index vector
% Note: The only contribution to ff in this problem is from the boundary fluxes
%----------------------------------------------------------% loop for computation and assembly of element matrices
%----------------------------------------------------------[point2,weight2]=feglqd2(nglx,ngly);
for iel=1:nel

% sampling points & weights

% loop for the total number of elements

for i=1:nnel
nd(i)=nodes(iel,i);
xcoord(i)=gcoord(nd(i),1);
ycoord(i)=gcoord(nd(i),2);
end

% extract connected node for (iel)-th element


% extract x value of the node
% extract y value of the node

k=zeros(edof,edof);
% initialization of element matrix to zero
m=zeros(edof,edof);
% element mass matrix
%-------------------------------% numerical integration
%-------------------------------for intx=1:nglx
x=point2(intx,1);
wtx=weight2(intx,1);
for inty=1:ngly
y=point2(inty,2);
wty=weight2(inty,2) ;

% sampling point in x-axis


% weight in x-axis
% sampling point in y-axis
% weight in y-axis

[shape,dhdr,dhds]=feisoq4(x,y); % compute shape functions and


% derivatives at sampling point
jacob2=fejacob2(nnel,dhdr,dhds,xcoord,ycoord);
detjacob=det(jacob2);
invjacob=inv(jacob2);

% compute Jacobian

% determinant of Jacobian
% inverse of Jacobian matrix

[dhdx,dhdy]=federiv2(nnel,dhdr,dhds,invjacob); % derivatives w.r.t.


% physical coordinate

%-----------------------------% compute element matrix


%-----------------------------for i=1:edof
for j=1:edof
k(i,j)=k(i,j)+(dhdx(i)*dhdx(j)+dhdy(i)*dhdy(j))*wtx*wty*detjacob;
m(i,j)=m(i,j)+shape(i)*shape(j)*wtx*wty*detjacob;
end
end
end % y loop
end % x loop
index=feeldof(nd,nnel,ndof);% extract system dofs associated with element
%---------------------------------% assemble element mass and stiffness matrices
%---------------------------------kk=feasmbl1(kk,k,index);
mm=feasmbl1(mm,m,index);
end

% end of element loops

%-----------------------------------% Now compute the flux contributions to the load vector.


% These are independent of time for this problem -- so do not
% have to be computed in the time integration loop.
% The loops below could really be moved into the main assembly loop
% and then the textbook file feasmbl2() could be used to
% assemble kk and ff at the same time.
%-----------------------------------[point1, weight1]=feglqd1(ngly); % get integration points for 1D boundary integrals
for iel=nx:nx:nx*ny % loop over elements with boundary on x=1, 0<=y<=1(local nodes 2,3)
for i=1:nnel
nd(i)=nodes(iel,i);
% extract connected node for (iel)-th element
xcoord(i)=gcoord(nd(i),1); % x value of the node
ycoord(i)=gcoord(nd(i),2); % y value of the node
end
f=zeros(4,1);
for ints=1:ngly % integration points on boundary r=1 of master element
s=point1(ints);
wty=weight1(ints);
[shape,dhdr,dhds]=feisoq4(1,s); % get master element shape functions
% at integration pt (1,s)
[shape1,dhdr1]=feisol2(s); % master element shape functions
% restricted to r=1 are linear fncs of s
bfnc=shape(2:3)*ycoord(2:3); % evaluate boundary flux=y at integration

% pt (y=sum_j H_j(1,s)y_j)
jacob1=fejacob1(2,dhdr1,ycoord(2:3));
for i=2:3
f(i)=f(i)+shape(i)*bfnc*wty*jacob1; % only shape(2),shape(3) nonzero
end
end
for i=2:3 ff(nd(i))=ff(nd(i))+f(i); end % assemble load vector
end
[point1, weight1]=feglqd1(nglx);
for iel=nx*ny-nx+1:nx*ny % loop over elements with boundary on y=1,0<=x<=1 (local nodes 3,4)
for i=1:nnel
nd(i)=nodes(iel,i);
% extract connected node for (iel)-th element
xcoord(i)=gcoord(nd(i),1); % x value of the node
ycoord(i)=gcoord(nd(i),2); % y value of the node
end
f=zeros(4,1);
for intr=1:nglx % integration points on boundary s=1 of master element
r=point1(intr);
wtx=weight1(intr);
[shape,dhdr,dhds]=feisoq4(r,1); % get master element shape functions
% at integration pt (r,1)
[shape1,dhdr1]=feisol2(r); % master element shape functions
% restricted to s=1 are linear
bfnc=shape(3:4)*xcoord(3:4); % evaluate boundary flux=x at integration
% pt (x=sum_j H_j(r,1)x_j)
jacob1=fejacob1(2,dhdr1,xcoord(4:-1:3));
for i=3:4
f(i)=f(i)+shape(i)*bfnc*wtx*jacob1; % only shape(3),shape(4) nonzero
end
end
for i=3:4 ff(nd(i))=ff(nd(i))+f(i); end % assemble load vector
end
%compute steady state
us=zeros(sdof,1); ssol=zeros(sdof,1);
[kk,ff]=feaplyc2(kk,ff,bcdof,bcval);
us=kk\ff;
for i=1:nnode
x=gcoord(i,1); y=gcoord(i,2);
ssol(i)=x*y;
end
disp([(1:nnode), us, ssol]);
%----------------------------%
loop for time integration: backwards time difference method used
%-----------------------------

fsol=zeros(sdof,1); %initial value of solution


sol(1,1)=fsol((nnode+1)/2);

kn=mm+deltt*kk;
for it=1:ntime

% store time history solution for middle node (assumes nnode is odd)

% compute effective system matrix (time invariant)


% start loop for time integration

fn=deltt*ff+mm*fsol;

% compute effective column vector

[kn,fn]=feaplyc2(kn,fn,bcdof,bcval); % apply essential boundary conditions


fsol=kn\fn;

% solve the matrix equation

sol(1,it+1)=fsol((nnode+1)/2); %
end

%----------------------------------% analytical solution at node middle node


%----------------------------------xypt=gcoord((nnode+1)/2,:);
for it=1:ntime+1
tt=(it-1)*deltt;
esol(it)=xypt(1)*xypt(2)-trans(xypt(1),tt,10)*trans(xypt(2),tt,10);
end
%-----------------------------------% plot the solution at nodes middle node
%-----------------------------------time=0:deltt:ntime*deltt;
plot(time,sol(1,:), time, esol, o);
xlabel(Time)
ylabel(Solution at nodes)
%===================================================================
% end of main routine
%===================================================================

function [point1,weight1]=feglqd1(ngl)
%------------------------------------------------------------------% Purpose:
%
determine the integration points and weighting coefficients
%
of Gauss-Legendre quadrature for one-dimensional integration
%

% Synopsis:
%
[point1,weight1]=feglqd1(ngl)
%
% Variable Description:
%
ngl - number of integration points
%
point1 - vector containing integration points
%
weight1 - vector containing weighting coefficients
%------------------------------------------------------------------%

initialization
point1=zeros(ngl,1);
weight1=zeros(ngl,1);

find corresponding integration points and weights


if ngl==1
point1(1)=0.0;
weight1(1)=2.0;

% 1-point quadrature rule

elseif ngl==2
% 2-point quadrature rule
point1(1)=-0.577350269189626;
point1(2)=-point1(1);
weight1(1)=1.0;
weight1(2)=weight1(1);
elseif ngl==3
% 3-point quadrature rule
point1(1)=-0.774596669241483;
point1(2)=0.0;
point1(3)=-point1(1);
weight1(1)=0.555555555555556;
weight1(2)=0.888888888888889;
weight1(3)=weight1(1);
elseif ngl==4
% 4-point quadrature rule
point1(1)=-0.861136311594053;
point1(2)=-0.339981043584856;
point1(3)=-point1(2);
point1(4)=-point1(1);
weight1(1)=0.347854845137454;
weight1(2)=0.652145154862546;
weight1(3)=weight1(2);
weight1(4)=weight1(1);
else

% 5-point quadrature rule


point1(1)=-0.906179845938664;
point1(2)=-0.538469310105683;
point1(3)=0.0;
point1(4)=-point1(2);
point1(5)=-point1(1);
weight1(1)=0.236926885056189;

weight1(2)=0.478628670499366;
weight1(3)=0.568888888888889;
weight1(4)=weight1(2);
weight1(5)=weight1(1);
end
%------------------------------------------------------------------function [point2,weight2]=feglqd2(nglx,ngly)
%------------------------------------------------------------------% Purpose:
%
determine the integration points and weighting coefficients
%
of Gauss-Legendre quadrature for two-dimensional integration
%
% Synopsis:
%
[point2,weight2]=feglqd2(nglx,ngly)
%
% Variable Description:
%
nglx - number of integration points in the x-axis
%
ngly - number of integration points in the y-axis
%
point2 - vector containing integration points
%
weight2 - vector containing weighting coefficients
%------------------------------------------------------------------%

determine the largest one between nglx and ngly


if nglx > ngly
ngl=nglx;
else
ngl=ngly;
end

initialization
point2=zeros(ngl,2);
weight2=zeros(ngl,2);

find corresponding integration points and weights


[pointx,weightx]=feglqd1(nglx);
[pointy,weighty]=feglqd1(ngly);

% quadrature rule for x-axis


% quadrature rule for y-axis

quadrature for two-dimension


for intx=1:nglx
point2(intx,1)=pointx(intx);
weight2(intx,1)=weightx(intx);
end

% quadrature in x-axis

for inty=1:ngly
point2(inty,2)=pointy(inty);
weight2(inty,2)=weighty(inty);
end

% quadrature in y-axis

%-------------------------------------------------------------------

function [shapeq4,dhdrq4,dhdsq4]=feisoq4(rvalue,svalue)
%-----------------------------------------------------------------------% Purpose:
%
compute isoparametric four-node quadilateral shape functions
%
and their derivatves at the selected (integration) point
%
in terms of the natural coordinate
%
% Synopsis:
%
[shapeq4,dhdrq4,dhdsq4]=feisoq4(rvalue,svalue)
%
% Variable Description:
%
shapeq4 - shape functions for four-node element
%
dhdrq4 - derivatives of the shape functions w.r.t. r
%
dhdsq4 - derivatives of the shape functions w.r.t. s
%
rvalue - r coordinate value of the selected point
%
svalue - s coordinate value of the selected point
%
% Notes:
%
1st node at (-1,-1), 2nd node at (1,-1)
%
3rd node at (1,1), 4th node at (-1,1)
%-----------------------------------------------------------------------% shape functions
shapeq4(1)=0.25*(1-rvalue)*(1-svalue);
shapeq4(2)=0.25*(1+rvalue)*(1-svalue);
shapeq4(3)=0.25*(1+rvalue)*(1+svalue);
shapeq4(4)=0.25*(1-rvalue)*(1+svalue);
% derivatives
dhdrq4(1)=-0.25*(1-svalue);
dhdrq4(2)=0.25*(1-svalue);
dhdrq4(3)=0.25*(1+svalue);
dhdrq4(4)=-0.25*(1+svalue);
dhdsq4(1)=-0.25*(1-rvalue);
dhdsq4(2)=-0.25*(1+rvalue);
dhdsq4(3)=0.25*(1+rvalue);
dhdsq4(4)=0.25*(1-rvalue);
%-------------------------------------------------------------------

function [dhdx,dhdy]=federiv2(nnel,dhdr,dhds,invjacob)
%-----------------------------------------------------------------------% Purpose:
%
determine derivatives of 2-D isoparametric shape functions with
%
respect to physical coordinate system
%
% Synopsis:
%
[dhdx,dhdy]=federiv2(nnel,dhdr,dhds,invjacob)
%
% Variable Description:
%
dhdx - derivative of shape function w.r.t. physical coordinate x
%
dhdy - derivative of shape function w.r.t. physical coordinate y
%
nnel - number of nodes per element
%
dhdr - derivative of shape functions w.r.t. natural coordinate r
%
dhds - derivative of shape functions w.r.t. natural coordinate s
%
invjacob - inverse of 2-D Jacobian matrix
%-----------------------------------------------------------------------for i=1:nnel
dhdx(i)=invjacob(1,1)*dhdr(i)+invjacob(1,2)*dhds(i);
dhdy(i)=invjacob(2,1)*dhdr(i)+invjacob(2,2)*dhds(i);
end
%-------------------------------------------------------------------

function [jacob2]=fejacob2(nnel,dhdr,dhds,xcoord,ycoord)
%-----------------------------------------------------------------------% Purpose:
%
determine the Jacobian for two-dimensional mapping
%
% Synopsis:
%
[jacob2]=fejacob2(nnel,dhdr,dhds,xcoord,ycoord)
%
% Variable Description:
%
jacob2 - Jacobian for one-dimension
%
nnel - number of nodes per element
%
dhdr - derivative of shape functions w.r.t. natural coordinate r
%
dhds - derivative of shape functions w.r.t. natural coordinate s
%
xcoord - x axis coordinate values of nodes
%
ycoord - y axis coordinate values of nodes
%-----------------------------------------------------------------------jacob2=zeros(2,2);
for i=1:nnel
jacob2(1,1)=jacob2(1,1)+dhdr(i)*xcoord(i);

jacob2(1,2)=jacob2(1,2)+dhdr(i)*ycoord(i);
jacob2(2,1)=jacob2(2,1)+dhds(i)*xcoord(i);
jacob2(2,2)=jacob2(2,2)+dhds(i)*ycoord(i);
end
%-------------------------------------------------------------------

function [kk]=feasmbl1(kk,k,index)
%---------------------------------------------------------% Purpose:
%
Assembly of element matrices into the system matrix
%
% Synopsis:
%
[kk]=feasmbl1(kk,k,index)
%
% Variable Description:
%
kk - system matrix
%
k - element matri
%
index - d.o.f. vector associated with an element
%-----------------------------------------------------------

edof = length(index);
for i=1:edof
ii=index(i);
for j=1:edof
jj=index(j);
kk(ii,jj)=kk(ii,jj)+k(i,j);
end
end
%-------------------------------------------------------------------

function [kk,ff]=feaplyc2(kk,ff,bcdof,bcval)
%---------------------------------------------------------% Purpose:
%
Apply constraints to matrix equation [kk]{x}={ff}
%
% Synopsis:
%
[kk,ff]=feaplybc(kk,ff,bcdof,bcval)
%
% Variable Description:
%
kk - system matrix before applying constraints
%
ff - system vector before applying constraints
%
bcdof - a vector containging constrained d.o.f
%
bcval - a vector containing contained value
%
%
For example, there are constraints at d.o.f=2 and 10

%
and their constrained values are 0.0 and 2.5,
%
respectively. Then, bcdof(1)=2 and bcdof(2)=10; and
%
bcval(1)=1.0 and bcval(2)=2.5.
%----------------------------------------------------------n=length(bcdof);
sdof=size(kk);
for i=1:n
c=bcdof(i);
for j=1:sdof
kk(c,j)=0;
end
kk(c,c)=1;
ff(c)=bcval(i);
end
%-------------------------------------------------------------------

function [index]=feeldof(nd,nnel,ndof)
%---------------------------------------------------------% Purpose:
%
Compute system dofs associated with each element
%
% Synopsis:
%
[index]=feeldof(nd,nnel,ndof)
%
% Variable Description:
%
index - system dof vector associated with element "iel"
%
iel - element number whose system dofs are to be determined
%
nnel - number of nodes per element
%
ndof - number of dofs per node
%----------------------------------------------------------edof = nnel*ndof;
k=0;
for i=1:nnel
start = (nd(i)-1)*ndof;
for j=1:ndof
k=k+1;
index(k)=start+j;
end
end
%------------------------------------------------------------------function [jacob1]=fejacob1(nnel,dhdr,xcoord)
%-------------------------------------------------------------------

% Purpose:
%
determine the Jacobian for one-dimensional mapping
%
% Synopsis:
%
[jacob1]=fejacob1(nnel,dhdr,xcoord)
%
% Variable Description:
%
jacob1 - Jacobian for one-dimension
%
nnel - number of nodes per element
%
dhdr - derivative of shape functions w.r.t. natural coordinate
%
xcoord - x axis coordinate values of nodes
%------------------------------------------------------------------jacob1=0.0;
for i=1:nnel
jacob1=jacob1+dhdr(i)*xcoord(i);
end
%-------------------------------------------------------------------function [shape,dhdr]=feisol2(rvalue)
%-------------------------------------------------------%Purpose
%
Compute isoparametric 2-node shape functions
%
and their derivatives at the selected
%
point in terms of the natural coordinate.
%
%Synopsis:
%
[shape,dhdr]=kwisol2(rvalue)
%
%Variable Description:
%
shape - shape functions for the linear element
%
dhdr - derivatives of shape functions
%
rvalue - r coordinate valute of the selected point
%
%Notes:
%
1st node at rvalue=-1
%
2nd node at rvalue=1
%-------------------------------------------------------shape(1)=0.5*(1.0-rvalue);
shape(2)=0.5*(1.0+rvalue);

% first shape function


% second shape function

dhdr(1)=-0.5; % derivative of the first shape function


dhdr(2)=0.5; % derivative of the second shape function
%--------------------------------------------------------function t=trans(z,t,n)
sgn=-1;
sum=0;
for k=1:n

lambda=(2*k-1)*pi/2; lamsq=lambda*lambda;
sine=sin(lambda*z);
expfnc=exp(-lamsq*t);
sum=sum+sgn*sine*expfnc/lamsq;
sgn=-sgn;
end;
t=2*sum;
%----------------------------------------------------------