This is a diffusion equation solver written in R
HEqSolver is a Finite Element Solver written in R for solving the diffusion equation. HEqSolver employes piecewise linear basis functions on uniform triangulation. It solves the diffusion equation on a two dimensional rectangular domain with homogeneous boundary conditions of Dirichlet type. We illustrate HEqSolver through an example of the diffusion equation posed on a rectangular domain in which we present both the relevant theory of the finite element method a long with the time-stepping scheme. All this is illustrated through the presentation of the mathematical theory of the finite element method on an example, for which the solution is obtained by HEqSolver.
Consider , a rectangular open bounded domain with
denoting its boundary. We define the initial conditions on each point in space
at time
and hence consider the diffusion equation in two space and one time dimension for
, where
denotes the final time. Let
satisfy the probelm
for
and
for
and
0"/> denotes the diffusion coefficient. Initial conditions for the problem are prescribed such that
, where
, which means that it is a square integrable function of
and
. The approximate solution of time-dependent problems through numerical methods can in general be achieved through two different types of approaches. The two approaches mainly depend on whether the scheme is formulated to discretise time first followed by the space discretisation or vice vera. We adopt the approach in which we apply Galerkin finite element method to implement the space discretisation first and then we proceed with time-stepping using the implicit Euler scheme. Consider the diffusion problem to be posed on a space-time cylinder
, in the form of a sequence of Poisson’s equations, that are all well-posed on
, i.e. satisfying all the requirements stated by the Lax-Milgram Theorem at each time point in the interval
.
This allows to introduce at each time point , the solution and test spaces of functions for the corresponding sequence of Poisson equations to be denoted by
and
respectively, where
and
are a special class of Sobelov spaces. Assuming that the diffusion problem is well-posed on
for all
</t\leq\,T”>, then we multiply both sides of the diffusion equation by a test function
and integrate by parts with application of Green’s Theorem. Using the prescribed boundary conditions lead to vanish the boundary terms in the application of integration by parts to the right hand-side of the equation, which results in the weak formulation of the diffusion problem and that is to find some
at each time point
such that
for all
. Given that the problem is well-posed in the continuous space of functions of which both
and
are subsets, we define the finite dimensional solution and test spaces namely
and
respectively for each time point
. Let
be a triangulated approximation of
, containing a discrete integer number of nodes and
triangles, then using the finite dimentional solution and test spaces, the finite element formulation of the problem is to find
such that
for all
. We expand
and
in terms of its finite i.e.
dimensional basis functions in the form
and
. Substituting these in the finite element formulation we obtain a discrete set of continuous oridnary differential equations in the form
. We use the commutative property of summation and integration to write the semi-discrete system of differential equations in matrix notation in the form
, where
and
respectively denote the stiffness and mass matrices. The vector
contains the unknown approximate solution values at each node in the domain
at time
. The entries of
and
are given by
and
respectively. The entries of
are the finite element approximate solution values to be found from the system of ordinary differential equations.
In order to solve the semi-discrete problem we introduce a uniform mesh of discrete number of time points in the form
, which is equally spaced by time step-size
. We use the Implicit Euler Method, to fully discretise the semi-discrete system of equations. Let
denote the finite element approximate solution at the time-step
, then full discretisation of the problem is achieved by writing
, which can be rearranged in the form of a system of
linear equations for each time-step written as
.
Let be discretised by
uniform triangles connected through
nodes. Let
denote the uniform triangulation of
, consisting of all triangles. The algorithm is programmed to compute locally on each triangle
, the entries of the mass and stiffness matrices namely
and
. The entries of the global mass and stiffness matrices are computed from contributions by the local
mass and stiffness matrices namely
and
on each triangle. The global mass and stiffness matrices are therefore, given by the formulea
and
respectively.
Recall the problem formulated in terms of satisfying the diffusion equation
on
. It satisfies homogeneous Dirichlet type boundary conditions for all
, which is formally written as
. The initial conditions are prescribed such that
.
We present the code in the form of a serie of enumerated documentations for each block of code:
Variable
L = 1
stores the value for the side length of the two-dimensional square domain .
Variables
tm = 1
dt = 0.001
store the values respectively for the final time and the time step-size
.
The number of time points on the time interval
are stored by
M = tm/dt
The number of spatial uniform mesh points that discretises L
is stored by
N = 50
The side length L
is discretised by N+1
equally spaced points using
X = seq(0,L,len=N+1)
The time interval is also uniformly discretised by M+1
points using
T = seq(0,tm,len=M+1)
This step is to compute and store the matrices containing the values for the two dimensional spatial coordinates of such discretisation, which is achieved by
m = length(X); n=length(X);
x = matrix(rep(X,each=n),nrow=n);
y = matrix(rep(X,m),nrow=n)
Reshape the data structure of the spatial coordinates from matrices into vector by
x = c(x)
y = c(y)
where x
and y
now store all the values for the x and y coordinates for all the global nodes, therefore, each one is now a vector of entries.
Store the number of global nodes in the discretised domain by
GNodes = (N+1)^2
Use U
to store the approximate discrete solution values at each time step and we define the initial state of U
to be a vector of constant values of 1 at each note in the domain and this is achieved by
U = matrix(1, GNodes, 1)
Triangulation of a quadrilateral mesh by drawing a line of slope -1 diangonally through each square leads to the construction of a uniform triangulated domain , which consists of
NumTRI
triangles, which is defined in terms of N
by
NumTRI = 2*N^2
The connectivity array LocNodes
is a matrix that stores the global counting of all the nodes with a local structure in the sense that it must have NumTRI
rows and three columns for each vertix of each triangle. The code to achieve this is
LocNodes = matrix(0,NumTRI,3)
Triangulation of the domain is obtained such that the vertices of each triangle is locally counted in anti-clockwise orientation and such that the local counting of vertices of each triangle fills the global connectivity array LocNodes
in the correct order. Note that we must fill in 4+2=6
vertices for each square, because each square is divided into two triangles by a diagonal line, however, each triangle has one distinct but two shared vertices. Therefore, it can be noted that the first three lines inside the nested for loop correspond to the three vertices of all the lower triangles on each square and the latter three lines correspond to all the three vertices of all the upper triangles. The nested loop that distributes such order of counting within the connectivity array is given by
for (i in 1:N){
for (j in 1:N){
LocNodes[i+2*(j-1)*N,1] = i+(j-1)*(N+1)
LocNodes[i+2*(j-1)*N,2] = i+j*(N+1)
LocNodes[i+2*(j-1)*N,3] = (i+1)+(j-1)*(N+1)
LocNodes[i+N+2*(j-1)*N,1] = i+1+j*(N+1)
LocNodes[i+N+2*(j-1)*N,2] = (i+1)+(j-1)*(N+1)
LocNodes[i+N+2*(j-1)*N,3] = i+j*(N+1)
}
}
Introduce the global stiffness and mass matrices filled with zeros each of size GNodes x GNodes
SP_Stiff <- matrix(0, GNodes, GNodes)
SP_Mass <- matrix(0, GNodes, GNodes)
for (n in 1:NumTRI)
{# This is the start of the for loop on all triangles
r1
, r2
, and r3
in terms of x
and y
coordinate values through which we refer to different vertices of each triangle.
r1 = matrix(c(x[LocNodes[n,1]],y[LocNodes[n,1]]),nrow=2, byrow=FALSE)
r2 = matrix(c(x[LocNodes[n,2]],y[LocNodes[n,2]]),nrow=2, byrow=FALSE);
r3 = matrix(c(x[LocNodes[n,3]],y[LocNodes[n,3]]),nrow=2, byrow=FALSE);
J
for the mapping from an arbitrary triangle in The Jacobian of the mapping namely
J = matrix(c(r2[1]-r1[1],r2[2]-r1[2]
,r3[1]-r1[1],r3[2]-r1[2]), nrow=2, byrow=TRUE)
J
serves to reduce the computational cost by a significant amount, particularly due to a property of integration for computing the integral of a function on a reference domain with a given mapping between the arbitrary domain and the reference domain. Further details on this topic can be found on Integral domain transformation. Here is the animated solution of the diffusion equation .
…work in progress…