Preface  
 Vibration ODEs 
       Finite difference discretization 
             A basic model for vibrations 
             A centered finite difference scheme 
       Implementation 
             Making a solver function 
             Verification 
             Scaled model 
       Long time simulations 
             Using a moving plot window 
             Making animations 
             Using Bokeh to compare graphs 
             Using a line-by-line ascii plotter 
             Empirical analysis of the solution 
       Analysis of the numerical scheme 
             Deriving a solution of the numerical scheme 
             Exact discrete solution 
             Convergence 
             The global error 
             Stability 
             About the accuracy at the stability limit 
       Alternative schemes based on 1st-order equations 
             The Forward Euler scheme 
             The Backward Euler scheme 
             The Crank-Nicolson scheme 
             Comparison of schemes 
             Runge-Kutta methods 
             Analysis of the Forward Euler scheme 
       Energy considerations 
             Derivation of the energy expression 
             An error measure based on energy 
       The Euler-Cromer method 
             Forward-backward discretization 
             Equivalence with the scheme for the second-order ODE 
             Implementation 
             The velocity Verlet algorithm 
       Generalization: damping, nonlinear spring, and external excitation 
             A centered scheme for linear damping 
             A centered scheme for quadratic damping 
             A forward-backward discretization of the quadratic damping term 
             Implementation 
             Verification 
             Visualization 
             User interface 
             The Euler-Cromer scheme for the generalized model 
       Exercises and Problems 
             Problem 1: Use linear/quadratic functions for verification 
             Exercise 2: Show linear growth of the phase with time 
             Exercise 3: Improve the accuracy by adjusting the frequency 
             Exercise 4: See if adaptive methods improve the phase error 
             Exercise 5: Use a Taylor polynomial to compute \( u^1 \) 
             Exercise 6: Find the minimal resolution of an oscillatory function 
             Exercise 7: Visualize the accuracy of finite differences for a cosine function 
             Exercise 8: Verify convergence rates of the error in energy 
             Exercise 9: Use linear/quadratic functions for verification 
             Exercise 10: Use an exact discrete solution for verification 
             Exercise 11: Use analytical solution for convergence rate tests 
             Exercise 12: Investigate the amplitude errors of many solvers 
             Exercise 13: Minimize memory usage of a vibration solver 
             Exercise 14: Implement the solver via classes 
             Exercise 15: Interpret \( [D_tD_t u]^n \) as a forward-backward difference 
             Exercise 16: Use a backward difference for the damping term 
             Exercise 17: Analysis of the Euler-Cromer scheme 
 Wave equations 
       Simulation of waves on a string 
             Discretizing the domain 
             The discrete solution 
             Fulfilling the equation at the mesh points 
             Replacing derivatives by finite differences 
             Formulating a recursive algorithm 
             Sketch of an implementation 
       Verification 
             A slightly generalized model problem 
             Using an analytical solution of physical significance 
             Manufactured solution 
             Constructing an exact solution of the discrete equations 
       Implementation 
             Callback function for user-specific actions 
             The solver function 
             Verification: exact quadratic solution 
             Visualization: animating the solution 
             Running a case 
             Working with a scaled PDE model 
       Vectorization 
             Operations on slices of arrays 
             Finite difference schemes expressed as slices 
             Verification 
             Efficiency measurements 
             Remark on the updating of arrays 
       Exercises 
             Exercise 18: Simulate a standing wave 
             Exercise 19: Add storage of solution in a user action function 
             Exercise 20: Use a class for the user action function 
             Exercise 21: Compare several Courant numbers in one movie 
             Project 22: Calculus with 1D mesh functions 
       Generalization: reflecting boundaries 
             Neumann boundary condition 
             Discretization of derivatives at the boundary 
             Implementation of Neumann conditions 
             Index set notation 
             Verifying the implementation of Neumann conditions 
             Alternative implementation via ghost cells 
       Generalization: variable wave velocity 
             The model PDE with a variable coefficient 
             Discretizing the variable coefficient 
             Computing the coefficient between mesh points 
             How a variable coefficient affects the stability 
             Neumann condition and a variable coefficient 
             Implementation of variable coefficients 
             A more general PDE model with variable coefficients 
             Generalization: damping 
       Building a general 1D wave equation solver 
             User action function as a class 
             Pulse propagation in two media 
       Exercises 
             Exercise 23: Find the analytical solution to a damped wave equation 
             Problem 24: Explore symmetry boundary conditions 
             Exercise 25: Send pulse waves through a layered medium 
             Exercise 26: Explain why numerical noise occurs 
             Exercise 27: Investigate harmonic averaging in a 1D model 
             Problem 28: Implement open boundary conditions 
             Exercise 29: Implement periodic boundary conditions 
             Exercise 30: Compare discretizations of a Neumann condition 
             Exercise 31: Verification by a cubic polynomial in space 
       Analysis of the difference equations 
             Properties of the solution of the wave equation 
             More precise definition of Fourier representations 
             Stability 
             Numerical dispersion relation 
             Extending the analysis to 2D and 3D 
       Finite difference methods for 2D and 3D wave equations 
             Multi-dimensional wave equations 
             Mesh 
             Discretization 
       Implementation 
             Scalar computations 
             Vectorized computations 
             Verification 
       Using classes to implement a simulator 
       Exercises 
             Exercise 32: Check that a solution fulfills the discrete model 
             Project 33: Calculus with 2D mesh functions 
             Exercise 34: Implement Neumann conditions in 2D 
             Exercise 35: Test the efficiency of compiled loops in 3D 
       Applications of wave equations 
             Waves on a string 
             Waves on a membrane 
             Elastic waves in a rod 
             The acoustic model for seismic waves 
             Sound waves in liquids and gases 
             Spherical waves 
             The linear shallow water equations 
             Waves in blood vessels 
             Electromagnetic waves 
       Exercises 
             Exercise 36: Simulate waves on a non-homogeneous string 
             Exercise 37: Simulate damped waves on a string 
             Exercise 38: Simulate elastic waves in a rod 
             Exercise 39: Simulate spherical waves 
             Problem 40: Earthquake-generated tsunami over a subsea hill 
             Problem 41: Earthquake-generated tsunami over a 3D hill 
             Problem 42: Investigate Matplotlib for visualization 
             Problem 43: Investigate visualization packages 
             Problem 44: Implement loops in compiled languages 
             Exercise 45: Simulate seismic waves in 2D 
             Project 46: Model 3D acoustic waves in a room 
             Project 47: Solve a 1D transport equation 
             Problem 48: General analytical solution of a 1D damped wave equation 
             Problem 49: General analytical solution of a 2D damped wave equation 
 Diffusion equations 
       The 1D diffusion equation 
             The initial-boundary value problem for 1D diffusion 
             Forward Euler scheme 
             Backward Euler scheme 
             Sparse matrix implementation 
             Crank-Nicolson scheme 
             The \( \theta \) rule 
             The Laplace and Poisson equation 
             Extensions 
       Analysis of schemes for the diffusion equation 
             Properties of the solution 
             Example: Diffusion of a discontinues profile 
             Analysis of discrete equations 
             Analysis of the finite difference schemes 
             Analysis of the Forward Euler scheme 
             Analysis of the Backward Euler scheme 
             Analysis of the Crank-Nicolson scheme 
             Summary of accuracy of amplification factors 
             Exercise 50: Explore symmetry in a 1D problem 
             Exercise 51: Investigate approximation errors from a \( u_x=0 \) boundary condition 
             Exercise 52: Experiment with open boundary conditions in 1D 
             Exercise 53: Simulate a diffused Gaussian peak in 2D/3D 
             Exercise 54: Examine stability of a diffusion model with a source term 
       Diffusion in heterogeneous media 
             Stationary solution 
             Piecewise constant medium 
             Implementation 
             Diffusion equation in axi-symmetric geometries 
             Diffusion equation in spherically-symmetric geometries 
       Exercises 
             Exercise 55: Stabilizing the Crank-Nicolson method by Rannacher time stepping 
             Project 56: Energy estimates for diffusion problems 
 Staggered mesh discretization 
             The Euler-Cromer scheme on a standard mesh 
             The Euler-Cromer scheme on a staggered mesh 
             Implementation of the scheme on a staggered mesh 
             A staggered Euler-Cromer scheme for a generalized model 
       Exercises 
             Exercise 57: Use the forward-backward scheme with quadratic damping 
 Appendix: Useful formulas 
       Finite difference operator notation 
       Truncation errors of finite difference approximations 
       Finite differences of exponential functions 
       Finite differences of \( t^n \) 
 Appendix: Truncation error analysis 
       Overview of truncation error analysis 
             Abstract problem setting 
             Error measures 
       Truncation errors in finite difference formulas 
             Example: The backward difference for \( u'(t) \) 
             Example: The forward difference for \( u'(t) \) 
             Example: The central difference for \( u'(t) \) 
             Overview of leading-order error terms in finite difference formulas 
             Software for computing truncation errors 
       Truncation errors in exponential decay ODE 
             Truncation error of the Forward Euler scheme 
             Truncation error of the Crank-Nicolson scheme 
             Truncation error of the \( \theta \)-rule 
             Using symbolic software 
             Empirical verification of the truncation error 
             Increasing the accuracy by adding correction terms 
             Extension to variable coefficients 
             Exact solutions of the finite difference equations 
             Computing truncation errors in nonlinear problems 
       Truncation errors in vibration ODEs 
             Linear model without damping 
             Model with damping and nonlinearity 
             Extension to quadratic damping 
             The general model formulated as first-order ODEs 
       Truncation errors in wave equations 
             Linear wave equation in 1D 
             Finding correction terms 
             Extension to variable coefficients 
             1D wave equation on a staggered mesh 
             Linear wave equation in 2D/3D 
       Truncation errors in diffusion equations 
             Linear diffusion equation in 1D 
             Linear diffusion equation in 2D/3D 
             A nonlinear diffusion equation in 2D 
       Exercises 
             Exercise 58: Truncation error of a weighted mean 
             Exercise 59: Simulate the error of a weighted mean 
             Exercise 60: Verify a truncation error formula 
             Exercise 61: Truncation error of the Backward Euler scheme 
             Exercise 62: Empirical estimation of truncation errors 
             Exercise 63: Correction term for a Backward Euler scheme 
             Exercise 64: Verify the effect of correction terms 
             Exercise 65: Truncation error of the Crank-Nicolson scheme 
             Exercise 66: Truncation error of \( u'=f(u,t) \) 
             Exercise 67: Truncation error of \( [D_t D_tu]^n \) 
             Exercise 68: Investigate the impact of approximating \( u'(0) \) 
             Exercise 69: Investigate the accuracy of a simplified scheme 
 Appendix: Software engineering; wave equation model 
       A 1D wave equation simulator 
             Mathematical model 
             Numerical discretization 
             A solver function 
       Saving large arrays in files 
             Using savez to store arrays in files 
             Using joblib to store arrays in files 
             Using a hash to create a file or directory name 
       Software for the 1D wave equation 
             Making hash strings from input data 
             Avoiding rerunning previously run cases 
             Verification 
       Programming the solver with classes 
             Class Problem 
             Class Mesh 
             Class Function 
             Class Solver 
       Migrating loops to Cython 
             Declaring variables and annotating the code 
             Visual inspection of the C translation 
             Building the extension module 
             Calling the Cython function from Python 
       Migrating loops to Fortran 
             The Fortran subroutine 
             Building the Fortran module with f2py 
             How to avoid array copying 
       Migrating loops to C via Cython 
             Translating index pairs to single indices 
             The complete C code 
             The Cython interface file 
             Building the extension module 
       Migrating loops to C via f2py 
             Migrating loops to C++ via f2py 
       Exercises 
             Exercise 70: Make an improved numpy.savez function 
       References