Skip to content

Heat Equation

Background knowledge

A. The Heat Equation in 1D

1. The differential equation

The heat equation in one dimension is given by:

utx(αux)=fforx(0,L)andt>0

where:

  • x is the spatial coordinate,

  • t is the time,

  • α(x) is the spatially-varying thermal diffusivity of the material,

  • u(x,t) is the temperature distribution function,

  • f(x,t) is a time dependent and spatially varying heat source.

2. Initial and boundary conditions

To solve the heat equation, we must specify initial and boundary conditions:

  1. Initial Condition: This refers to the temperature distribution at the initial time t=0. We need to know this temperature distribution in our entire domain (0,L).
u(x,0)=u0(x)
  1. Boundary Conditions: We can specify different types of boundary conditions, i.e., conditions on the boundaries of our domain, x=0 and x=L.
  • Dirichlet Boundary Conditions: This boundary condition means that the temperature is specified at the boundaries of the domain.

    u(0,t)=u0andu(L,t)=uL
  • Neumann Boundary Conditions: This boundary condition means that, instead of the temperature, the derivative of the temperature (which is called the heat flux) is specified at the boundaries of the domain.

    α(0)ux(0,t)=g0andα(L)ux(L,t)=gL

3. Applications

A simplified example where the heat equation can be used is to find out how the temperature is distributed through the outside, insulating walls of your apartment. Look at the image below (source).

The insulation wall is made up of several materials, each with their own thermal diffusivities αi(x). Imagine that the temperature outside is 0 degrees, and your heating system holds the temperature inside your house at 18 degrees. Then, these are the boundary conditions for the heat equation. Given an initial temperature distribution through the insulation wall, you could use the heat equation to find out how the temperature varies inside the insulation wall.

B. Solving the Heat Equation

1. Disadvantages of the above formulation

Now, if we want to compute the solution of the heat equation as stated above, we run into two difficulties:

  1. Lack of exact solutions: For a general function f, finding out the exact, analytical solution u is not an easy task. Well, this is not entirely true: finding the solution can be easy enough in one dimension on a domain as simple as (0,L), but in higher dimensions and on more complicated geometries (e.g., imagine the insulation wall of the Guggenheim museum) it is not possible.

  2. A restrictive set of solutions: For the above form of the heat equation to make sense, we must also assume that the second-derivatives of the solution u(x) should exist, and that the first derivatives of the thermal diffusivity α(x) should exist. It turns out that this is too strong of a requirement that it not satisfied by many physical systems.

For example, think of the insulation wall - each material in the insulation wall has its own thermal diffusivity which is completely unrelated to the diffusivities of the other materials. As a result, α(x) is a discontinuous function and its first derivatives do not make sense.

2. Tackling the above disadvantages using a discrete & weaker formulation

The above disadvantages are the reason why, in practice, the above strong formulation of the heat equation is not useful. Instead, we formulate a discrete, weak version of the equation which is much more useful in practice. The motivation is:

  1. Discrete approximation of unknown exact solutions: Since we don't know the exact solution in general, we try to approximate it. This is the process called discretization. In this process, we fix a finite-dimensional vector space of spatially-varying functions Vn and say that, for any given time t, we want to find a function un(,t)Vn which approximates the exact solution u(,t). Here, n denotes the dimension of the vector space Vn. We expect that as n, the solution un(,t)u(,t).

  2. Weak version of the equation: Since the original equation imposes too strong requirements on the smoothness of u(x,t) and α(x), we instead work with an integral formulation where only the first derivatives of u(x,t) should make sense, and where α(x) is allowed to be discontinuous.

ASSUMPTION: For the sake of simplifying the discussion, from now on we will assume that we are imposing Dirichlet boundary conditions at x=0 and x=L.

This discrete, weak version of the problem at a fixed time t is stated as: find un(,t)Sn such that

0Lwnuntdx+0Lαunxwnxdx=0Lfwndx,wnWn,

where:

  • Sn:={vn(x)Vn : vn(0)=u0,vn(L)=uL},

  • Wn:={vn(x)Vn : vn(0)=0,vn(L)=0}.

Note the following important things:

  1. The above problem tries to find the solution un(,t) at the fixed time instant t.

  2. Sn consists of spatially-varying functions in Vn that satisfy the boundary conditions.

  3. We want the integral equation above to be satisfied for all functions wnWn, where the function space Wn consists of spatially-varying functions in Vn that satisfy homogeneous (or, equivalently, zero) boundary conditions.

The finite element method

Now we are at a stage where, if we make a choice for Vn, we can convert the discrete weak problem into a system of ODEs. This section will explain how.

A. How to choose Vn?

1. Choosing Vn

In the finite element method, we choose Vn as the space of piecewise-polynomial functions of degree p on a mesh of the domain (0,L).

Meshing the domain

We choose a set of N+1 points, 0=x1<x1<x2<<xN+1=L, and these points divide the domain (0,L) into smaller subdomains, (xi,xi+1) with xi(0,L), called elements. That is, we assume that there are N elements in our mesh.

ASSUMPTION: In the following code, we will always assume that the mesh is uniform. In other words, xi+1xi is equal to L/N for all i.

Defining Vn

The space Vn is defined as the space of functions vn such that:

  • on any element (i.e., on the interval (xi,xi+1) withi=1,,N) it is a polynomial of degree p,

  • at each xi, i=2,,N, the function vn is Ck smooth for some k0.

Once we do this, the vector-space dimension of Vn can be related to the parameters N,p,k as follows:

n=(p+1)N(k+1)(N1).

In other words, there are n basis functions ϕi(x), i=1,,n, such that any arbitrary vnVn can be represented as:

vn(x)=i=1nciϕi(x),

for some numbers ciR.

EXAMPLE: Vn with (N,p,k)=(4,1,0).

Consider the space of functions that are linear polynomials over each mesh element, and which are C0 smooth (or, equivalently, continuous) at the interfaces xi between the elements. This space of functions has dimension:

n=(p+1)N(k+1)(N1)=2×41×3=5.

So, we can find 5 basis functions, ϕ1,ϕ2,ϕ5, that span the space Vn. Run the code below to create such a Vn and look at one such choice of the basis functions called hat functions. Convince yourself that linear combinations of these functions can be used to represent any piecewise-linear polynomial function on the mesh. (Each function is plotted in a different color.)

julia
using Mantis
using GLMakie

# The size of the domain where to solve our problem
L = 1.0

# The degree of the piecewise-polynomial basis functions
p = 1
# The number of elements in the mesh
N = 4
# The smoothness of the basis functions (must be smaller than the polynomial degree, and
# larger than -1)
k = 0

# The number of basis functions in the piecewise-polynomial function space
n = N * (p + 1) - (k + 1) * (N - 1)

# Create the mesh and the function space
breakpoints = LinRange(0.0, L, N+1)
line_geo = Geometry.CartesianGeometry((breakpoints,))
B = FunctionSpaces.BSplineSpace(line_geo, p, k)

# Create a Form Space.
BF = Forms.FormSpace(0, B, "b")

# Plot the basis functions.
n_plot_points_per_element = 25

fig = Figure()
ax = Axis(fig[1, 1],
    title = "Basis functions of V_n",
    xlabel = "x",
    ylabel = "b_i(x)",
)

n_elements = Geometry.get_num_elements(line_geo)
xi = Points.CartesianPoints((LinRange(0.0, 1.0, n_plot_points_per_element),))
BFF = Forms.FormField(BF, " ")

dim_V = Forms.get_num_basis(BF)
colors = [:blue, :green, :red, :purple, :orange]
for basis_idx in 1:dim_V

    BFF.coefficients[basis_idx] = 1.0
    if basis_idx > 1
        BFF.coefficients[basis_idx - 1] = 0.0
    end

    color_i = colors[basis_idx]

    for element_idx in 1:n_elements
        form_eval, _ = Forms.evaluate(BFF, element_idx, xi)
        x = Geometry.evaluate(Forms.get_geometry(BF), element_idx, xi)

        lines!(ax, x[:], form_eval[1], color=color_i, label=L"\phi_{%$basis_idx}")

        scatter!(ax, x[:][[1, end]], [0.0, 0.0], color=:tomato)
    end
end
fig[1, 2] = Legend(fig, ax, marge=true, unique=true)

fig = DisplayAs.Text(DisplayAs.PNG(fig))

EXAMPLE: Vn with (N,p,k)=(4,2,1).

Consider now the space of functions that are quadratic polynomials over each mesh element, and which are C1 smooth (or, equivalently, continuous and continuously differentiable) at the interfaces xi between the elements. This space of functions has dimension:

n=(p+1)N(k+1)(N1)=3×42×3=6.

So, we can find 6 basis functions, ϕ1,ϕ2,ϕ6, that span the space Vn. Run the code below to create such a Vn and look at one such choice of the basis functions called B-splines. (Each function is plotted in a different color.)

julia
p = 2
k = 1
n = N * (p + 1) - (k + 1) * (N - 1)

B = FunctionSpaces.BSplineSpace(line_geo, p, k)

# Create a Form Space.
BF = Forms.FormSpace(0, B, "b")

fig = Figure()
ax = Axis(fig[1, 1],
    title = "Basis functions of V_n",
    xlabel = "x",
    ylabel = "b_i(x)",
)

n_elements = Geometry.get_num_elements(line_geo)
xi = Points.CartesianPoints((LinRange(0.0, 1.0, n_plot_points_per_element),))
BFF = Forms.FormField(BF, " ")

dim_V = Forms.get_num_basis(BF)
colors = [:blue, :green, :red, :purple, :orange, :black]
for basis_idx in 1:dim_V

    BFF.coefficients[basis_idx] = 1.0
    if basis_idx > 1
        BFF.coefficients[basis_idx - 1] = 0.0
    end

    color_i = colors[basis_idx]

    for element_idx in 1:n_elements
        form_eval, _ = Forms.evaluate(BFF, element_idx, xi)
        x = Geometry.evaluate(Forms.get_geometry(BF), element_idx, xi)

        lines!(ax, x[:], form_eval[1], color=color_i, label=L"\phi_{%$basis_idx}")

        scatter!(ax, x[:][[1, end]], [0.0, 0.0], color=:tomato)
    end
end
fig[1, 2] = Legend(fig, ax, marge=true, unique=true)

fig = DisplayAs.Text(DisplayAs.PNG(fig))

Note: In both of the above examples, the only functions non-zero at x=0 and x=L are ϕ1 and ϕn. This means that, in particular, the functions ϕ2,,ϕn1 form a basis for Wn. We will use this fact later on.

Since, at each time instant t, our approximate solution un(x,t) is represented as a linear combination of the basis functions ϕi, i=1,,n, that span Vn, this means that our approximate solution has the following form:

un(x,t)=i=1nci(t)ϕi(x).

In other words, the coefficients of the linear combination are time-dependent. But we can say more! Since un(0,t)=u0 and un(L,t)=uL are the boundary conditions, then we must have:

un(x,t)=u0ϕ1(x)+i=2n1ci(t)ϕi(x)+uLϕn(x).

That is, the only unknown coefficients in the above expression are ci(t), i=2,,n1.

ASSUMPTION: For simplicity, we assume that u0 and uL are constants.

B. Assembling the System of ODEs

Now that we have arrived at an explicit form of our approximate solution to the weak problem, let us see how the discrete weak problem leads to a system of ODEs for the coefficients ci(t). This process is called assembly and it leads to a system of ODEs that looks like:

MdCdt+KC=Fu0Fb,0uLFb,L,

where we have arranged the unknown coefficients ci(t) in a vector C(t):=[c2(t),c3(t),,cn1(t)].

Some terminology: in the above system of ODEs, M is called the mass matrix, K is called the stiffness matrix, F is called the load vector, Fb,0 and Fb,L are the contributions of the known coefficients (c1 and cn) to the loading, respectively, and C is the vector of unknown coefficients that define the solution.

The idea behind assembly is simple. We substitute the assumed form of our discrete solution un into the discrete weak problem. This gives us:

0Lwnt(j=1ncjϕj)dx+0Lαwnxx(j=1ncjϕj)dx=0Lfwndx,wnWn,

Since we need to satisfy the above equation for all wnWn, and since the above equation is linear in wn, it is actually enough if we satisfy the above equation for the basis functions that span Wn, i.e., ϕi, i=2,,n1. Then, choosing wn=ϕi gives us the following equation, and we get one such equation for each i=2,,n1,

0Lϕit(j=1ncjϕj)dx+0Lαϕixx(j=1ncjϕj)dx=0Lfϕidx.

We can rearrange this equation as:

j=2n1dcjdt0Lϕiϕjdx+j=2n1cj0Lαdϕidxdϕjdxdx=0Lfϕiu00Lαdϕidxdϕ1dxdxuL0Lαdϕidxdϕndxdx.

Then, it is easy to see that this equation represents the ODE system at the beginning of this section by defining:

  • Mij=0Lϕiϕjdx,

  • Kij=0Ldϕidxdϕjdxdx,

  • Fi=0Lϕifdx,

  • Fib,0=0Lαdϕidxdϕ1dxdx,

  • Fib,L=0Lαdϕidxdϕndxdx.

To assemble the matrices M and K and the vectors F, Fb,0 and Fb,L, we first must define α and f.

Before choosing our forcing term, it is relevant to briefly analyse the behavior of our solution. We saw that our weak form of the equation is

0Lwnuntdx+0Lαunxwnxdx=0Lfwndx,wnWn,

Since we have Dirichlet boundary conditions (i.e., we enforce the value of the temperature on both sides of our interval), if we prescribe a stationary heat source, the solution will evolve to a stationary state. This stationary state, uhs will be the one that satisfies

0Lαunxwnxdx=0Lfwndx,wnWn,

or in matrix form

KC=Fu0Fb,0uLFb,L.

Additionally, if α is constant, and if the heat source f is smooth, then we can easily construct analytical solutions to the stationary state. For example,

us(x,t)=1+12cos(2πLx),

if the heat source is

f(x,t)=2απ2L2cos(2πLx).

We choose a finite element space with (N,p,k)=(10,2,1), i.e., with more elements compared to the last example. This is to ensure that we have sufficient accuracy for computing a decent solution.


This page was generated using Literate.jl.