Practice heat1d: Heat Conduction

You write the 1D heat conduction computation described in Chapter 10 yourself. You extend the program from the previous assignment into the next one.

  1. Serial Version: Solving Heat Conduction on the CPU

  2. MPI Version: Dividing the Domain

  3. GPU Version: Moving Arrays and Loops to the GPU

For the ideas behind the equations and the checks, see Chapter 10; for arrays, for_each, and reduce, see Chapter 7; for MPI, see Chapter 8; and for the GPU, see Chapter 9. With only the CPU on Ubuntu or Mac, you can work through Assignments 1 and 2, and the CPU build of Assignment 3.

Common setup

The three assignments use the following problem and inputs.

Item

Value

Equation

\(\partial u/\partial t = \kappa\,\partial^2 u/\partial x^2\)、\(\kappa = 1\)

Domain and boundary conditions

\(0 < x < 1\), \(u = 0\) at both ends

Initial condition

\(u(x, 0) = \sin(\pi x)\)

Analytical solution

\(u(x, t) = e^{-\pi^2\kappa t}\sin(\pi x)\)

End time

\(t_\mathrm{end} = 0.1\)

Grid

Number of cells \(N\) (default 64), \(\Delta x = 1/N\), cell centers \(x_j = (j + 1/2)\Delta x\)

Ghost cells

One at each end (the array size is the number of physical cells + 2)

Time step

\(n_\mathrm{steps} = \lceil t_\mathrm{end}/(r_\mathrm{max}\Delta x^2/\kappa)\rceil\), \(\Delta t = t_\mathrm{end}/n_\mathrm{steps}\), default \(r_\mathrm{max}\) is 0.4

Value type

using Real = double;

Make the program accept \(N\) and \(r_\mathrm{max}\) as command-line arguments (defaulting to 64 and 0.4 if omitted). Convert argv[1] of main(int argc, char **argv) to a number with std::atoi, and argv[2] with std::atof (<cstdlib>).

./heat1d_serial          # N = 64, r_max = 0.4
./heat1d_serial 128      # N = 128
./heat1d_serial 64 0.6   # try an r that exceeds the stability condition

At the end, the program of each assignment prints the following.

N = 64, steps = 1024, r = 0.4000
max error (discrete) = ...
max error (exact)    = ...

max error (discrete) is the maximum difference over all physical cells from the discrete solution \(G^{n}\sin(\pi x_j)\) (\(G = 1 - 4r\sin^2(\pi\Delta x/2)\)), and max error (exact) is the maximum difference from the analytical solution.

In addition, write \(x_j\) and \(u_j\) of all physical cells to a file, one cell per line, separated by a space. To compare files bit by bit, write them with 17 digits. If you set std::scientific and std::setprecision(17) (<iomanip>) on a std::ofstream (<fstream>), it writes in the form 1.23456789012345678e-01.

Build setup

Use the “minimal CMake configuration for using MISO from your own program” in Chapter 1. Put CMakeLists.txt and the sources in a working folder (for example heat1d/), and pass the location of MISO with -DMISO_DIR=/path/to/MISO.

cmake -B build -S . -DMISO_DIR=/path/to/MISO
cmake --build build -j

Build one executable per assignment (heat1d_serial, heat1d_mpi, heat1d_gpu), and link each to MISO::MISO. When you bring in MISO with add_subdirectory, MPI and yaml-cpp are linked together with it, so you do not need to add any separate configuration for MPI. The extra settings needed for the GPU build are explained in Assignment 3.

Run the MPI program like mpiexec -np 2 ./build/heat1d_mpi. If OpenMPI reports errors, for example inside a container, set the environment variables described in Chapter 8 (demo/shared/openmpi_config.env).

What to record

For each assignment, record the following so that you can compare them in later assignments.

  • max error (exact) for each \(N\), and the order of convergence computed from it

  • The size of max error (discrete)

  • The files you wrote (use the results of the serial version when comparing with the MPI and GPU versions)