Solving the heat equation numerically using Python

In summary, the conversation discusses implementing an explicit algorithm to solve the heat equation numerically. The conversation also mentions a sample problem given by a college professor and a comparison of the numerical and analytical solutions. The issue of a discrepancy between the two solutions is raised and it is discovered that the analytical solution does not contain a value for k, which results in varying temperatures when k = 0.05.
  • #1
Wrichik Basu
Science Advisor
Insights Author
Gold Member
2,116
2,691
I want to solve the heat equation numerically. The equation is: $$k \dfrac{\partial^2 T}{\partial x^2} = \dfrac{\partial T}{\partial t}.$$ This is a parabolic PDE.

Following this pdf (specifically, equation 7 given on page 3), I wrote the following Python function to implement the explicit algorithm:
Python:
import numpy as np

def heat_equation_explicit(t0, t_end, dt, dx, k, initial_profile):
    """
    Solves the heat equation using explicit algorithm.

    Parameters
    ----------
    t0 : float
        The start of time.
    t_end : float
        The end of time.
    dt : float
        Time step.
    dx : float
        Step size on x-axis.
    k : float
        Diffusivity.
    initial_profile : numpy.ndarray
        The initial heat profile for all values of x over which the solution has to be calculated,
        (i.e. T(x, 0) ∀ x ∈ np.arange(x0, x_end, dx)). The first and the  last elements should be the
        boundary values, i.e. T(x0, t) and T(x_end, t), which will remain constant with time.

    Returns
    -------
    numpy.ndarray
        The heat profile at t = t_end.

    """

    # Number of steps:
    num_t = round((t_end - t0) / dt)
    num_x = np.size(initial_profile)

    old_profile = initial_profile

    global finalProfile_numerical

    lamb = (k * dt) / (dx ** 2)

    for j in range(0, num_t):

        # Initialise the variable:
        finalProfile_numerical = np.zeros(num_x)

        # Keep the boundary values at the two ends:
        finalProfile_numerical[0] = initial_profile[0]
        finalProfile_numerical[-1] = initial_profile[-1]

        # Compute the new profile:
        for i in range(1, num_x - 1):

            u_old_iPlus1 = old_profile[i + 1]
            u_old_iMinus1 = old_profile[i - 1]

            finalProfile_numerical[i] = old_profile[i] + lamb * (u_old_iPlus1 - 2 * old_profile[i] + u_old_iMinus1)

        old_profile = finalProfile_numerical

    return finalProfile_numerical
Our college Professor gave us a sample problem to test our programs. The given values are as follows:
  • ##x \in [0, \pi]##
  • ##T(0, t) = T(\pi,t) = 0##
  • ##T(x,0) = \sin x##
  • ##k = 0.05##
  • Analytical solution: ##T(x,t) = \exp(-t) \sin x##
  • I have to compute the final profile at ##t = 0.5s.##
Well and good. I called my function with the necessary values:
Python:
import math
import numpy as np
import matplotlib.pyplot as plt

x0 = 0
xEnd = math.pi
dx = math.pi / 100

t0 = 0
tEnd = 0.5
dt = 0.01

k = 0.05

xVal = np.arange(x0, xEnd, dx)

# Values of T(x, 0) at all x. Includes T(x0, t) at the beginning, and T(x_end, t) at the end.
initialProfile = np.sin(xVal)

finalProfile_numerical = heat_equation_explicit(t0, tEnd, dt, dx, k, initialProfile)
finalProfile_analytic = math.exp(-0.5) * np.sin(xVal)

# Plot the numerical solution:
plt.plot(xVal, finalProfile_numerical, '-o', label="Numerical", markevery=2)

# Plot the analytical solution:
plt.plot(xVal, finalProfile_analytic, '-o', label='Analytic', markevery=2)

plt.xlabel(r'x$\rightarrow$')
plt.ylabel(r'$T(x)\rightarrow$')
plt.title("Temperature profile at t = " + f'{tEnd:.2f}' + "s")
plt.legend(loc='best')
plt.show()
And I get this graph:

1625414250129.png

Obviously, the numerical solution doesn't match the analytic solution.

I double-checked my function, and there seems to be no error. But there is an error somewhere, right?

If I print final_profile_numerical / final_profile_analytic, I get:
Code:
[       nan 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745 1.60800745
 1.60800745 1.60800745 1.60800745 1.60800745 1.60800746 1.60800746
 1.60800747 1.60800748 1.60800752 1.60800757 1.60800769 1.60800788
 1.60800825 1.60800886 1.60800999 1.60801179 1.60801496 1.60801993
 1.6080283  1.60804126 1.60806232 1.60809452 1.60814542 1.60822265
 1.60834263 1.60852485 1.60880718 1.60924297 1.60993333 1.61105178
 1.61296191 1.61650076 1.6242027  1.64872127]
Ignore the nan in the front. Interestingly, note that ##1 / \exp(-0.5) = 1.648##.

Any idea where the problem is occurring?
 
Technology news on Phys.org
  • #2
Wrichik Basu said:
Any idea where the problem is occurring?
The analytical solution doesn't contain a k. It's only valid if k=1. With k = 0.05 the temperatures will vary much more slowly than with k=1.

If you want to compute k=1 with your python program you need to set dt much smaller. For larger values of k*dt, the solution will become unstable and will produce large heatwaves with wavelength dt.
 
  • Like
Likes pbuk
  • #3
I don't think line 58 of your code does what you think it does:
Python:
        old_profile = finalProfile_numerical
Do you want to do this instead?
Edit:
Python:
        old_profile = finalProfile_numerical.copy()
(Before the edit this showed the following, which is not as good a recommendation).
Python:
        old_profile = numpy.copy(finalProfile_numerical)

You need to develop some techniques for debugging numerical methods; one common technique is to run for a range of step sizes and see if the solution converges to the analytical solution at a rate you would expect.
 
Last edited:
  • #4
pbuk said:
I don't think line 58 of your code does what you think it does:
Python:
        old_profile = finalProfile_numerical
Do you want to do this instead?
Python:
        old_profile = numpy.copy(finalProfile_numerical)
Unfortunately, that doesn't change the graph.
willem2 said:
The analytical solution doesn't contain a k. It's only valid if k=1. With k = 0.05 the temperatures will vary much more slowly than with k=1.
That does it. I changed k = 1, tEnd = 1e-9, dt = 1e-10, and updated the analytic solution accordingly: finalProfile_analytic = math.exp(-tEnd) * np.sin(xVal) The graphs coincided. Thanks!
 
  • Like
Likes pbuk
  • #5
Wrichik Basu said:
Unfortunately, that doesn't change the graph.
Ah yes, the assignment to old_profile of the reference to finalProfile_numerical was not a problem because you were replacing the reference with finalProfile_numerical = np.zeros().
 
  • Like
Likes Wrichik Basu

What is the heat equation and why is it important in science?

The heat equation is a mathematical representation of how heat is transferred in a given system. It is important in science because it allows us to understand and predict the behavior of heat in various physical systems, such as heat conduction in a solid object or heat transfer in a fluid.

What is Python and why is it commonly used for solving the heat equation numerically?

Python is a high-level programming language that is widely used in scientific computing due to its simplicity, flexibility, and large collection of libraries. It is commonly used for solving the heat equation numerically because it has powerful tools for numerical computation and visualization, making it well-suited for scientific simulations.

How is the heat equation solved numerically using Python?

The heat equation can be solved numerically using Python by discretizing the equation into smaller time and space steps, and then using numerical methods such as finite differences or finite element methods to solve the resulting system of equations. The Python code will involve defining the initial and boundary conditions, setting up the discretization, and iterating through the time steps until a solution is reached.

What are the benefits of solving the heat equation numerically using Python?

Solving the heat equation numerically using Python allows for a more accurate and efficient solution compared to analytical methods. It also allows for more complex and realistic boundary conditions, making it a useful tool for studying real-world heat transfer problems. Additionally, the flexibility of Python allows for easy customization and integration with other scientific tools.

Are there any limitations to solving the heat equation numerically using Python?

There are a few limitations to solving the heat equation numerically using Python. The accuracy of the solution depends on the choice of time and space steps, and the complexity of the problem may require a large number of iterations, leading to longer computation times. Additionally, the numerical solution may be sensitive to errors in the input parameters or assumptions made in the model.

Similar threads

  • Programming and Computer Science
Replies
2
Views
895
  • Programming and Computer Science
Replies
21
Views
4K
  • Programming and Computer Science
Replies
5
Views
2K
  • Thermodynamics
Replies
3
Views
1K
  • Programming and Computer Science
Replies
6
Views
1K
  • Programming and Computer Science
Replies
1
Views
1K
  • Advanced Physics Homework Help
Replies
7
Views
975
  • Programming and Computer Science
Replies
1
Views
1K
Replies
4
Views
1K
  • Programming and Computer Science
Replies
2
Views
1K
Back
Top