522
u 1 u 0 u 4 u 5 u 2 u 3 Hans Petter Langtangen · Svein Linge Finite Difference Computing with PDEs A Modern Software Approach Editorial Board T. J. Barth M. Griebel D. E. Keyes R. M. Nieminen D. Roose T. Schlick 16

Hans Petter Langtangen · Svein Linge Finite Diff erence Computing … · Hans Petter Langtangen Lysaker, Norway Svein Linge Process, Energy & Environmental Technology University

  • Upload
    others

  • View
    9

  • Download
    0

Embed Size (px)

Citation preview

Hans Petter Langtangen · Svein Linge
Finite Diff erence Computing with PDEs A Modern Software Approach Editorial Board
T. J. Barth M. Griebel D. E. Keyes
R. M. Nieminen D. Roose
T. Schlick
Editors
Timothy J. Barth Michael Griebel David E. Keyes Risto M. Nieminen Dirk Roose Tamar Schlick
More information about this series at http://www.springer.com/series/5151
AModern Software Approach
Svein Linge Process, Energy & Environmental Technology University College of Southeast Norway Porsgrunn, Norway
ISSN 1611-0994 Texts in Computational Science and Engineering ISBN 978-3-319-55455-6 ISBN 978-3-319-55456-3 (eBook) DOI 10.1007/978-3-319-55456-3
Library of Congress Control Number: 2017942747
Mathematic Subject Classification (2010): 34, 35, 65, 68
© The Editor(s) (if applicable) and The Author(s) 2017 This book is an open access publication Open Access This book is distributed under the terms of the Creative Commons Attribution 4.0 Interna- tional License (http://creativecommons.org/licenses/by/4.0/),which permits use, duplication, adaptation, distribution and reproduction in any medium or format, as long as you give appropriate credit to the orig- inal author(s) and the source, provide a link to the Creative Commons license and indicate if changes were made. The images or other third party material in this book are included in the work’s Creative Commons li- cense, unless indicated otherwise in the credit line; if such material is not included in the work’s Creative Commons license and the respective action is not permitted by statutory regulation, users will need to obtain permission from the license holder to duplicate, adapt or reproduce the material. The use of general descriptive names, registered names, trademarks, service marks, etc. in this publica- tion does not imply, even in the absence of a specific statement, that such names are exempt from the relevant protective laws and regulations and therefore free for general use. The publisher, the authors and the editors are safe to assume that the advice and information in this book are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or the editors give a warranty, express or implied, with respect to the material contained herein or for any errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional claims in published maps and institutional affiliations.
Printed on acid-free paper
This Springer imprint is published by Springer Nature The registered company is Springer International Publishing AG The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
There are so many excellent books on finite difference methods for ordinary and partial differential equations that writing yet another one requires a different view on the topic. The present book is not so concerned with the traditional academic presentation of the topic, but is focused at teaching the practitioner how to obtain reliable computations involving finite difference methods. This focus is based on a set of learning outcomes:
1. understanding of the ideas behind finite difference methods, 2. understanding how to transform an algorithm to a well-designed computer code, 3. understanding how to test (verify) the code, 4. understanding potential artifacts in simulation results.
Compared to other textbooks, the present one has a particularly strong emphasis on computer implementation and verification. It also has a strong emphasis on an intuitive understanding of constructing finite difference methods. To learn about the potential non-physical artifacts of various methods, we study exact solutions of finite difference schemes as these give deeper insight into the physical behavior of the numerical methods than the traditional (and more general) asymptotic error analysis. However, asymptotic results regarding convergence rates, typically trun- cation errors, are crucial for testing implementations, so an extensive appendix is devoted to the computation of truncation errors.
Why finite differences? One may ask why we do finite differences when finite element and finite volume methods have been developed to greater generality and sophistication than finite differences and can cover more problems. The finite ele- ment and finite volume methods are also the industry standard nowadays. Why not just those methods? The reason for finite differences is the method’s simplicity, both from a mathematical and coding perspective. Especially in academia, where simple model problems are used a lot for teaching and in research (e.g., for verification of advanced implementations), there is a constant need to solve the model problems from scratch with easy-to-verify computer codes. Here, finite differences are ideal. A simple 1D heat equation can of course be solved by a finite element package, but a 20-line code with a difference scheme is just right to the point and provides an
v
vi Preface
understanding of all details involved in the model and the solution method. Every- body nowadays has a laptop and the natural method to attack a 1D heat equation is a simple Python or Matlab program with a difference scheme. The conclusion goes for other fundamental PDEs like the wave equation and Poisson equation as long as the geometry of the domain is a hypercube. The present book contains all the practical information needed to use the finite difference tool in a safe way.
Various pedagogical elements are utilized to reach the learning outcomes, and these are commented upon next.
Simplify, understand, generalize The book’s overall pedagogical philosophy is the three-step process of first simplifying the problem to something we can under- stand in detail, and when that understanding is in place, we can generalize and hopefully address real-world applications with a sound scientific problem-solving approach. For example, in the chapter on a particular family of equations we first simplify the problem in question to a 1D, constant-coefficient equation with simple boundary conditions. We learn how to construct a finite difference method, how to implement it, and how to understand the behavior of the numerical solution. Then we can generalize to higher dimensions, variable coefficients, a source term, and more complicated boundary conditions. The solution of a compound problem is in this way an assembly of elements that are well understood in simpler settings.
Constructive mathematics This text favors a constructive approach to mathemat- ics. Instead of a set of definitions followed by popping up a method, we emphasize how to think about the construction of a method. The aim is to obtain a good intu- itive understanding of the mathematical methods.
The text is written in an easy-to-read style much inspired by the following quote.
Some people think that stiff challenges are the best device to induce learning, but I am not one of them. The natural way to learn something is by spending vast amounts of easy, enjoyable time at it. This goes whether you want to speak German, sight-read at the piano, type, or do mathematics. Give me the German storybook for fifth graders that I feel like reading in bed, not Goethe and a dictionary. The latter will bring rapid progress at first, then exhaustion and failure to resolve.
The main thing to be said for stiff challenges is that inevitably we will encounter them, so we had better learn to face them boldly. Putting them in the curriculum can help teach us to do so. But for teaching the skill or subject matter itself, they are overrated. [18, p. 86] Lloyd N. Trefethen, Applied Mathematician, 1955-.
This book assumes some basic knowledge of finite difference approximations, differential equations, and scientific Python or MATLAB programming, as often met in an introductory numerical methods course. Readers without this background may start with the light companion book “Finite Difference Computing with Expo- nential Decay Models” [9]. That book will in particular be a useful resource for the programming parts of the present book. Since the present book deals with partial differential equations, the reader is assumed to master multi-variable calculus and linear algebra.
Fundamental ideas and their associated scientific details are first introduced in the simplest possible differential equation setting, often an ordinary differential equation, but in a way that easily allows reuse in more complex settings with par- tial differential equations. With this approach, new concepts are introduced with a
Preface vii
minimum of mathematical details. The text should therefore have a potential for use early in undergraduate student programs.
All nuts and bolts Many have experienced that “vast amounts of easy, enjoyable time”, as stated in the quote above, arises when mathematics is implemented on a computer. The implementation process triggers understanding, creativity, and curiosity, but many students find the transition from a mathematical algorithm to a working code difficult and spend a lot of time on “programming issues”.
Most books on numerical methods concentrate on the mathematics of the subject while details on going from the mathematics to a computer implementation are less in focus. A major purpose of this text is therefore to help the practitioner by providing all nuts and bolts necessary for safely going from the mathematics to a well-designed and well-tested computer code. A significant portion of the text is consequently devoted to programming details.
Python as programming language While MATLAB enjoys widespread popular- ity in books on numerical methods, we have chosen to use the Python programming language. Python is very similar to MATLAB, but contains a lot of modern soft- ware engineering tools that have become standard in the software industry and that should be adopted also for numerical computing projects. Python is at present also experiencing an exponential growth in popularity within the scientific computing community. One of the book’s goals is to present an up-to-date Python eco system for implementing finite difference methods.
Program verification Program testing, called verification, is a key topic of the book. Good verification techniques are indispensable when debugging computer code, but also fundamental for achieving reliable simulations. Two verification techniques saturate the book: exact solution of discrete equations (where the ap- proximation error vanishes) and empirical estimation of convergence rates in prob- lems with exact (analytical or manufactured) solutions of the differential equa- tion(s).
Vectorized code Finite difference methods lead to code with loops over large ar- rays. Such code in plain Python is known to run slowly. We demonstrate, especially in Appendix C, how to port loops to fast, compiled code in C or Fortran. However, an alternative is to vectorize the code to get rid of explicit Python loops, and this technique is met throughout the book. Vectorization becomes closely connected to the underlying array library, here numpy, and is often thought of as a difficult sub- ject by students. Through numerous examples in different contexts, we hope that the present book provides a substantial contribution to explaining how algorithms can be vectorized. Not only will this speed up serial code, but with a library that can produce parallel code from numpy commands (such as Numba1), vectorized code can be automatically turned into parallel code and utilize multi-core processors and GPUs. Also when creating tailored parallel code for today’s supercomputers, vec- torization is useful as it emphasizes splitting up an algorithm into plain and simple
1 http://numba.pydata.org
array operations, where each operation is trivial to parallelize efficiently, rather than trying to develop a “smart” overall parallelization strategy.
Analysis via exact solutions of discrete equations Traditional asymptotic analy- sis of errors is important for verification of code using convergence rates, but gives a limited understanding of how and why a correctly implemented numerical method may give non-physical results. By developing exact solutions, usually based on Fourier methods, of the discrete equations, one can obtain a physical understanding of the behavior of a numerical method. This approach is favored for analysis of methods in this book.
Code-inspired mathematical notation Our primary aim is to have a clean and easy-to-read computer code, and we want a close one-to-one relationship between the computer code and mathematical description of the algorithm. This principle calls for a mathematical notation that is governed by the natural notation in the computer code. The unknown is mostly called u, but the meaning of the symbol u in the mathematical description changes as we go from the exact solution fulfilling the differential equation to the symbol u that is naturally used for the associated data structure in the code.
Limited scope The aim of this book is not to give an overview of a lot of methods for a wide range of mathematical models. Such information can be found in numer- ous existing, more advanced books. The aim is rather to introduce basic concepts and a thorough understanding of how to think about computing with finite differ- ence methods. We therefore go in depth with only the most fundamental methods and equations. However, we have a multi-disciplinary scope and address the inter- play of mathematics, numerics, computer science, and physics.
Focus on wave phenomena Most books on finite difference methods, or books on theory with computer examples, have their emphasis on diffusion phenomena. Half of this book (Chap. 1, 2, and Appendix C) is devoted to wave phenomena. Extended material on this topic is not so easy find in the literature, so the book should be a valuable contribution in this respect. Wave phenomena is also a good topic in general for choosing the finite difference method over other discretization methods since one quickly needs fine resolution over the entire mesh and uniform meshes are most natural.
Instead of introducing the finite difference method for diffusion problems, where one soon ends up with matrix systems, we do the introduction in a wave phenomena setting where explicit schemes are most relevant. This slows down the learning curve since we can introduce a lot of theory for differences and for software aspects in a context with simple, explicit stencils for updating the solution.
Independent chapters Most book authors are careful with avoiding repetitions of material. The chapters in this book, however, contain some overlap, because we want the chapters to appear meaningful on their own. Modern publishing technol- ogy makes it easy to take selected chapters from different books to make a new book tailored to a specific course. The more a chapter builds on details in other chapters, the more difficult it is to reuse chapters in new contexts. Also, most readers find it
Preface ix
convenient that important information is explicitly stated, even if it was already met in another chapter.
Supplementary materials All program and data files referred to in this book are available from the book’s primary web site: URL: http://github.com/hplgit/fdm- book/.
Acknowledgments Professor Kent-Andre Mardal at the University of Oslo has kindly contributed to enlightening discussions on several issues. Many students have provided lots of useful feedback on the exposition and found many errors in the text. Special efforts in this regard were made by Imran Ali, Shirin Fallahi, Anders Hafreager, Daniel Alexander Mo Søreide Houshmand, Kristian Gregorius Hustad, Mathilde Nygaard Kamperud, and Fatemeh Miri. The collaboration with the Springer team, with Dr. Martin Peters, Thanh-Ha Le Thi, and their production staff has always been a great pleasure and a very efficient process.
Finally, want really appreciate the strong push from the COE of Simula Research Laboratory, Aslak Tveito, for publishing and financing books in open access format, including this one. We are grateful for the laboratory’s financial contribution as well as to the financial contribution from the Department of Process, Energy and Environmental Technology at the University College of Southeast Norway.
Oslo, July 2016 Hans Petter Langtangen, Svein Linge
1 Vibration ODEs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1 Finite Difference Discretization . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 A Basic Model for Vibrations . . . . . . . . . . . . . . . . . 1 1.1.2 A Centered Finite Difference Scheme . . . . . . . . . . . . 2
1.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2.1 Making a Solver Function . . . . . . . . . . . . . . . . . . . . 4 1.2.2 Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.2.3 Scaled Model . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3 Visualization of Long Time Simulations . . . . . . . . . . . . . . . . 11 1.3.1 Using a Moving Plot Window . . . . . . . . . . . . . . . . . 11 1.3.2 Making Animations . . . . . . . . . . . . . . . . . . . . . . . . 13 1.3.3 Using Bokeh to Compare Graphs . . . . . . . . . . . . . . . 15 1.3.4 Using a Line-by-Line Ascii Plotter . . . . . . . . . . . . . . 18 1.3.5 Empirical Analysis of the Solution . . . . . . . . . . . . . . 19
1.4 Analysis of the Numerical Scheme . . . . . . . . . . . . . . . . . . . . 21 1.4.1 Deriving a Solution of the Numerical Scheme . . . . . . . 21 1.4.2 The Error in the Numerical Frequency . . . . . . . . . . . . 22 1.4.3 Empirical Convergence Rates and Adjusted ! . . . . . . . 24 1.4.4 Exact Discrete Solution . . . . . . . . . . . . . . . . . . . . . 24 1.4.5 Convergence . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 1.4.6 The Global Error . . . . . . . . . . . . . . . . . . . . . . . . . 25 1.4.7 Stability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.4.8 About the Accuracy at the Stability Limit . . . . . . . . . . 27
1.5 Alternative Schemes Based on 1st-Order Equations . . . . . . . . . 29 1.5.1 The Forward Euler Scheme . . . . . . . . . . . . . . . . . . . 29 1.5.2 The Backward Euler Scheme . . . . . . . . . . . . . . . . . . 30 1.5.3 The Crank-Nicolson Scheme . . . . . . . . . . . . . . . . . . 30 1.5.4 Comparison of Schemes . . . . . . . . . . . . . . . . . . . . . 32 1.5.5 Runge-Kutta Methods . . . . . . . . . . . . . . . . . . . . . . 33 1.5.6 Analysis of the Forward Euler Scheme . . . . . . . . . . . . 34
1.6 Energy Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 1.6.1 Derivation of the Energy Expression . . . . . . . . . . . . . 36 1.6.2 An Error Measure Based on Energy . . . . . . . . . . . . . . 38
xi
xii Contents
1.7 The Euler-Cromer Method . . . . . . . . . . . . . . . . . . . . . . . . . 40 1.7.1 Forward-Backward Discretization . . . . . . . . . . . . . . . 40 1.7.2 Equivalence with the Scheme for the Second-Order ODE 42 1.7.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . 43 1.7.4 The Störmer-Verlet Algorithm . . . . . . . . . . . . . . . . . 45
1.8 Staggered Mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 1.8.1 The Euler-Cromer Scheme on a Staggered Mesh . . . . . . 46 1.8.2 Implementation of the Scheme on a Staggered Mesh . . . 48
1.9 Exercises and Problems . . . . . . . . . . . . . . . . . . . . . . . . . . 50 1.10 Generalization: Damping, Nonlinearities, and Excitation . . . . . . 57
1.10.1 A Centered Scheme for Linear Damping . . . . . . . . . . . 57 1.10.2 A Centered Scheme for Quadratic Damping . . . . . . . . . 58 1.10.3 A Forward-Backward Discretization of the Quadratic
Damping Term . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 1.10.4 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . 59 1.10.5 Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 1.10.6 Visualization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 1.10.7 User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 1.10.8 The Euler-Cromer Scheme for the Generalized Model . . 63 1.10.9 The Störmer-Verlet Algorithm for the Generalized Model 64 1.10.10 A Staggered Euler-Cromer Scheme for a Generalized
Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 1.10.11 The PEFRL 4th-Order Accurate Algorithm . . . . . . . . . 65
1.11 Exercises and Problems . . . . . . . . . . . . . . . . . . . . . . . . . . 66 1.12 Applications of Vibration Models . . . . . . . . . . . . . . . . . . . . 67
1.12.1 Oscillating Mass Attached to a Spring . . . . . . . . . . . . 67 1.12.2 General Mechanical Vibrating System . . . . . . . . . . . . 69 1.12.3 A Sliding Mass Attached to a Spring . . . . . . . . . . . . . 70 1.12.4 A Jumping Washing Machine . . . . . . . . . . . . . . . . . 71 1.12.5 Motion of a Pendulum . . . . . . . . . . . . . . . . . . . . . . 71 1.12.6 Dynamic Free Body Diagram During Pendulum Motion . 74 1.12.7 Motion of an Elastic Pendulum . . . . . . . . . . . . . . . . . 79 1.12.8 Vehicle on a Bumpy Road . . . . . . . . . . . . . . . . . . . . 83 1.12.9 Bouncing Ball . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 1.12.10 Two-Body Gravitational Problem . . . . . . . . . . . . . . . 85 1.12.11 Electric Circuits . . . . . . . . . . . . . . . . . . . . . . . . . . 88
1.13 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
2 Wave Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 2.1 Simulation of Waves on a String . . . . . . . . . . . . . . . . . . . . . 93
2.1.1 Discretizing the Domain . . . . . . . . . . . . . . . . . . . . . 94 2.1.2 The Discrete Solution . . . . . . . . . . . . . . . . . . . . . . 94 2.1.3 Fulfilling the Equation at the Mesh Points . . . . . . . . . . 94 2.1.4 Replacing Derivatives by Finite Differences . . . . . . . . . 95 2.1.5 Formulating a Recursive Algorithm . . . . . . . . . . . . . . 96 2.1.6 Sketch of an Implementation . . . . . . . . . . . . . . . . . . 98
2.2 Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 2.2.1 A Slightly Generalized Model Problem . . . . . . . . . . . 99 2.2.2 Using an Analytical Solution of Physical Significance . . 99
Contents xiii
2.2.3 Manufactured Solution and Estimation of Convergence Rates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
2.2.4 Constructing an Exact Solution of the Discrete Equations 102 2.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
2.3.1 Callback Function for User-Specific Actions . . . . . . . . 104 2.3.2 The Solver Function . . . . . . . . . . . . . . . . . . . . . . . 105 2.3.3 Verification: Exact Quadratic Solution . . . . . . . . . . . . 106 2.3.4 Verification: Convergence Rates . . . . . . . . . . . . . . . . 107 2.3.5 Visualization: Animating the Solution . . . . . . . . . . . . 108 2.3.6 Running a Case . . . . . . . . . . . . . . . . . . . . . . . . . . 112 2.3.7 Working with a Scaled PDE Model . . . . . . . . . . . . . . 113
2.4 Vectorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 2.4.1 Operations on Slices of Arrays . . . . . . . . . . . . . . . . . 115 2.4.2 Finite Difference Schemes Expressed as Slices . . . . . . . 117 2.4.3 Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 2.4.4 Efficiency Measurements . . . . . . . . . . . . . . . . . . . . 119 2.4.5 Remark on the Updating of Arrays . . . . . . . . . . . . . . 121
2.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 2.6 Generalization: Reflecting Boundaries . . . . . . . . . . . . . . . . . 125
2.6.1 Neumann Boundary Condition . . . . . . . . . . . . . . . . . 126 2.6.2 Discretization of Derivatives at the Boundary . . . . . . . . 126 2.6.3 Implementation of Neumann Conditions . . . . . . . . . . . 127 2.6.4 Index Set Notation . . . . . . . . . . . . . . . . . . . . . . . . 128 2.6.5 Verifying the Implementation of Neumann Conditions . . 130 2.6.6 Alternative Implementation via Ghost Cells . . . . . . . . . 132
2.7 Generalization: Variable Wave Velocity . . . . . . . . . . . . . . . . . 135 2.7.1 The Model PDE with a Variable Coefficient . . . . . . . . . 135 2.7.2 Discretizing the Variable Coefficient . . . . . . . . . . . . . 136 2.7.3 Computing the Coefficient Between Mesh Points . . . . . 137 2.7.4 How a Variable Coefficient Affects the Stability . . . . . . 138 2.7.5 Neumann Condition and a Variable Coefficient . . . . . . . 138 2.7.6 Implementation of Variable Coefficients . . . . . . . . . . . 139 2.7.7 A More General PDE Model with Variable Coefficients . 140 2.7.8 Generalization: Damping . . . . . . . . . . . . . . . . . . . . 140
2.8 Building a General 1D Wave Equation Solver . . . . . . . . . . . . . 141 2.8.1 User Action Function as a Class . . . . . . . . . . . . . . . . 142 2.8.2 Pulse Propagation in Two Media . . . . . . . . . . . . . . . . 144
2.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 2.10 Analysis of the Difference Equations . . . . . . . . . . . . . . . . . . 155
2.10.1 Properties of the Solution of the Wave Equation . . . . . . 155 2.10.2 More Precise Definition of Fourier Representations . . . . 157 2.10.3 Stability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 2.10.4 Numerical Dispersion Relation . . . . . . . . . . . . . . . . . 160 2.10.5 Extending the Analysis to 2D and 3D . . . . . . . . . . . . . 163
2.11 Finite Difference Methods for 2D and 3D Wave Equations . . . . . 167 2.11.1 Multi-Dimensional Wave Equations . . . . . . . . . . . . . . 167 2.11.2 Mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 2.11.3 Discretization . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
xiv Contents
2.12 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 2.12.1 Scalar Computations . . . . . . . . . . . . . . . . . . . . . . . 172 2.12.2 Vectorized Computations . . . . . . . . . . . . . . . . . . . . 174 2.12.3 Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 2.12.4 Visualization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
2.13 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 2.14 Applications of Wave Equations . . . . . . . . . . . . . . . . . . . . . 183
2.14.1 Waves on a String . . . . . . . . . . . . . . . . . . . . . . . . . 183 2.14.2 Elastic Waves in a Rod . . . . . . . . . . . . . . . . . . . . . . 186 2.14.3 Waves on a Membrane . . . . . . . . . . . . . . . . . . . . . . 186 2.14.4 The Acoustic Model for Seismic Waves . . . . . . . . . . . 186 2.14.5 Sound Waves in Liquids and Gases . . . . . . . . . . . . . . 188 2.14.6 Spherical Waves . . . . . . . . . . . . . . . . . . . . . . . . . . 189 2.14.7 The Linear Shallow Water Equations . . . . . . . . . . . . . 190 2.14.8 Waves in Blood Vessels . . . . . . . . . . . . . . . . . . . . . 192 2.14.9 Electromagnetic Waves . . . . . . . . . . . . . . . . . . . . . 194
2.15 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
3 Diffusion Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 3.1 An Explicit Method for the 1D Diffusion Equation . . . . . . . . . . 208
3.1.1 The Initial-Boundary Value Problem for 1D Diffusion . . 208 3.1.2 Forward Euler Scheme . . . . . . . . . . . . . . . . . . . . . . 208 3.1.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . 210 3.1.4 Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 3.1.5 Numerical Experiments . . . . . . . . . . . . . . . . . . . . . 215
3.2 Implicit Methods for the 1D Diffusion Equation . . . . . . . . . . . 218 3.2.1 Backward Euler Scheme . . . . . . . . . . . . . . . . . . . . . 219 3.2.2 Sparse Matrix Implementation . . . . . . . . . . . . . . . . . 223 3.2.3 Crank-Nicolson Scheme . . . . . . . . . . . . . . . . . . . . . 224 3.2.4 The Unifying Rule . . . . . . . . . . . . . . . . . . . . . . . 226 3.2.5 Experiments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 3.2.6 The Laplace and Poisson Equation . . . . . . . . . . . . . . 227
3.3 Analysis of Schemes for the Diffusion Equation . . . . . . . . . . . 229 3.3.1 Properties of the Solution . . . . . . . . . . . . . . . . . . . . 229 3.3.2 Analysis of Discrete Equations . . . . . . . . . . . . . . . . . 233 3.3.3 Analysis of the Finite Difference Schemes . . . . . . . . . . 233 3.3.4 Analysis of the Forward Euler Scheme . . . . . . . . . . . . 234 3.3.5 Analysis of the Backward Euler Scheme . . . . . . . . . . . 236 3.3.6 Analysis of the Crank-Nicolson Scheme . . . . . . . . . . . 237 3.3.7 Analysis of the Leapfrog Scheme . . . . . . . . . . . . . . . 237 3.3.8 Summary of Accuracy of Amplification Factors . . . . . . 238 3.3.9 Analysis of the 2D Diffusion Equation . . . . . . . . . . . . 239 3.3.10 Explanation of Numerical Artifacts . . . . . . . . . . . . . . 241
3.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 3.5 Diffusion in Heterogeneous Media . . . . . . . . . . . . . . . . . . . . 245
3.5.1 Discretization . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 3.5.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . 246 3.5.3 Stationary Solution . . . . . . . . . . . . . . . . . . . . . . . . 247
Contents xv
3.5.4 Piecewise Constant Medium . . . . . . . . . . . . . . . . . . 247 3.5.5 Implementation of Diffusion in a Piecewise Constant
Medium . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 3.5.6 Axi-Symmetric Diffusion . . . . . . . . . . . . . . . . . . . . 251 3.5.7 Spherically-Symmetric Diffusion . . . . . . . . . . . . . . . 252
3.6 Diffusion in 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 3.6.1 Discretization . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 3.6.2 Numbering of Mesh Points Versus Equations and
Unknowns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 3.6.3 Algorithm for Setting Up the Coefficient Matrix . . . . . . 259 3.6.4 Implementation with a Dense Coefficient Matrix . . . . . . 260 3.6.5 Verification: Exact Numerical Solution . . . . . . . . . . . . 264 3.6.6 Verification: Convergence Rates . . . . . . . . . . . . . . . . 265 3.6.7 Implementation with a Sparse Coefficient Matrix . . . . . 266 3.6.8 The Jacobi Iterative Method . . . . . . . . . . . . . . . . . . 270 3.6.9 Implementation of the Jacobi Method . . . . . . . . . . . . . 273 3.6.10 Test Problem: Diffusion of a Sine Hill . . . . . . . . . . . . 274 3.6.11 The Relaxed Jacobi Method and Its Relation to the
Forward Euler Method . . . . . . . . . . . . . . . . . . . . . . 276 3.6.12 The Gauss-Seidel and SOR Methods . . . . . . . . . . . . . 277 3.6.13 Scalar Implementation of the SOR Method . . . . . . . . . 277 3.6.14 Vectorized Implementation of the SOR Method . . . . . . 278 3.6.15 Direct Versus Iterative Methods . . . . . . . . . . . . . . . . 282 3.6.16 The Conjugate Gradient Method . . . . . . . . . . . . . . . . 285 3.6.17 What Is the Recommended Method for Solving Linear
Systems? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 3.7 RandomWalk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
3.7.1 RandomWalk in 1D . . . . . . . . . . . . . . . . . . . . . . . 288 3.7.2 Statistical Considerations . . . . . . . . . . . . . . . . . . . . 288 3.7.3 Playing Around with Some Code . . . . . . . . . . . . . . . 290 3.7.4 Equivalence with Diffusion . . . . . . . . . . . . . . . . . . . 293 3.7.5 Implementation of Multiple Walks . . . . . . . . . . . . . . 294 3.7.6 Demonstration of Multiple Walks . . . . . . . . . . . . . . . 300 3.7.7 Ascii Visualization of 1D RandomWalk . . . . . . . . . . . 300 3.7.8 RandomWalk as a Stochastic Equation . . . . . . . . . . . 303 3.7.9 RandomWalk in 2D . . . . . . . . . . . . . . . . . . . . . . . 304 3.7.10 RandomWalk in Any Number of Space Dimensions . . . 305 3.7.11 Multiple Random Walks in Any Number of Space
Dimensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 3.8 Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
3.8.1 Diffusion of a Substance . . . . . . . . . . . . . . . . . . . . . 308 3.8.2 Heat Conduction . . . . . . . . . . . . . . . . . . . . . . . . . 309 3.8.3 Porous Media Flow . . . . . . . . . . . . . . . . . . . . . . . . 312 3.8.4 Potential Fluid Flow . . . . . . . . . . . . . . . . . . . . . . . 312 3.8.5 Streamlines for 2D Fluid Flow . . . . . . . . . . . . . . . . . 313 3.8.6 The Potential of an Electric Field . . . . . . . . . . . . . . . 313 3.8.7 Development of Flow Between Two Flat Plates . . . . . . 313 3.8.8 Flow in a Straight Tube . . . . . . . . . . . . . . . . . . . . . 314
xvi Contents
3.8.9 Tribology: Thin Film Fluid Flow . . . . . . . . . . . . . . . 315 3.8.10 Propagation of Electrical Signals in the Brain . . . . . . . . 316
3.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
4 Advection-Dominated Equations . . . . . . . . . . . . . . . . . . . . . . . 323 4.1 One-Dimensional Time-Dependent Advection Equations . . . . . . 323
4.1.1 Simplest Scheme: Forward in Time, Centered in Space . . 324 4.1.2 Analysis of the Scheme . . . . . . . . . . . . . . . . . . . . . 327 4.1.3 Leapfrog in Time, Centered Differences in Space . . . . . 328 4.1.4 Upwind Differences in Space . . . . . . . . . . . . . . . . . . 331 4.1.5 Periodic Boundary Conditions . . . . . . . . . . . . . . . . . 333 4.1.6 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . 333 4.1.7 A Crank-Nicolson Discretization in Time and Centered
Differences in Space . . . . . . . . . . . . . . . . . . . . . . . 337 4.1.8 The Lax-Wendroff Method . . . . . . . . . . . . . . . . . . . 339 4.1.9 Analysis of Dispersion Relations . . . . . . . . . . . . . . . 340
4.2 One-Dimensional Stationary Advection-Diffusion Equation . . . . 344 4.2.1 A Simple Model Problem . . . . . . . . . . . . . . . . . . . . 344 4.2.2 A Centered Finite Difference Scheme . . . . . . . . . . . . 345 4.2.3 Remedy: Upwind Finite Difference Scheme . . . . . . . . 347
4.3 Time-dependent Convection-Diffusion Equations . . . . . . . . . . . 349 4.3.1 Forward in Time, Centered in Space Scheme . . . . . . . . 349 4.3.2 Forward in Time, Upwind in Space Scheme . . . . . . . . . 349
4.4 Applications of Advection Equations . . . . . . . . . . . . . . . . . . 350 4.4.1 Transport of a Substance . . . . . . . . . . . . . . . . . . . . . 350 4.4.2 Transport of Heat in Fluids . . . . . . . . . . . . . . . . . . . 350
4.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
5 Nonlinear Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 5.1 Introduction of Basic Concepts . . . . . . . . . . . . . . . . . . . . . . 353
5.1.1 Linear Versus Nonlinear Equations . . . . . . . . . . . . . . 353 5.1.2 A Simple Model Problem . . . . . . . . . . . . . . . . . . . . 354 5.1.3 Linearization by Explicit Time Discretization . . . . . . . . 355 5.1.4 Exact Solution of Nonlinear Algebraic Equations . . . . . 356 5.1.5 Linearization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 5.1.6 Picard Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . 357 5.1.7 Linearization by a Geometric Mean . . . . . . . . . . . . . . 359 5.1.8 Newton’s Method . . . . . . . . . . . . . . . . . . . . . . . . . 360 5.1.9 Relaxation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361 5.1.10 Implementation and Experiments . . . . . . . . . . . . . . . 362 5.1.11 Generalization to a General Nonlinear ODE . . . . . . . . . 365 5.1.12 Systems of ODEs . . . . . . . . . . . . . . . . . . . . . . . . . 367
5.2 Systems of Nonlinear Algebraic Equations . . . . . . . . . . . . . . . 368 5.2.1 Picard Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . 369 5.2.2 Newton’s Method . . . . . . . . . . . . . . . . . . . . . . . . . 369 5.2.3 Stopping Criteria . . . . . . . . . . . . . . . . . . . . . . . . . 371 5.2.4 Example: A Nonlinear ODE Model from Epidemiology . 372
Contents xvii
5.3 Linearization at the Differential Equation Level . . . . . . . . . . . . 373 5.3.1 Explicit Time Integration . . . . . . . . . . . . . . . . . . . . 373 5.3.2 Backward Euler Scheme and Picard Iteration . . . . . . . . 374 5.3.3 Backward Euler Scheme and Newton’s Method . . . . . . 375 5.3.4 Crank-Nicolson Discretization . . . . . . . . . . . . . . . . . 377
5.4 1D Stationary Nonlinear Differential Equations . . . . . . . . . . . . 378 5.4.1 Finite Difference Discretization . . . . . . . . . . . . . . . . 378 5.4.2 Solution of Algebraic Equations . . . . . . . . . . . . . . . . 379
5.5 Multi-Dimensional Nonlinear PDE Problems . . . . . . . . . . . . . 384 5.5.1 Finite Difference Discretization . . . . . . . . . . . . . . . . 384 5.5.2 Continuation Methods . . . . . . . . . . . . . . . . . . . . . . 386
5.6 Operator Splitting Methods . . . . . . . . . . . . . . . . . . . . . . . . 387 5.6.1 Ordinary Operator Splitting for ODEs . . . . . . . . . . . . 387 5.6.2 Strang Splitting for ODEs . . . . . . . . . . . . . . . . . . . . 388 5.6.3 Example: Logistic Growth . . . . . . . . . . . . . . . . . . . 388 5.6.4 Reaction-Diffusion Equation . . . . . . . . . . . . . . . . . . 391 5.6.5 Example: Reaction-Diffusion with Linear Reaction Term 392 5.6.6 Analysis of the Splitting Method . . . . . . . . . . . . . . . . 400
5.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
A Useful Formulas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 A.1 Finite Difference Operator Notation . . . . . . . . . . . . . . . . . . . 409 A.2 Truncation Errors of Finite Difference Approximations . . . . . . . 410 A.3 Finite Differences of Exponential Functions . . . . . . . . . . . . . . 411 A.4 Finite Differences of tn . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
A.4.1 Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412
B Truncation Error Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 B.1 Overview of Truncation Error Analysis . . . . . . . . . . . . . . . . . 415
B.1.1 Abstract Problem Setting . . . . . . . . . . . . . . . . . . . . 415 B.1.2 Error Measures . . . . . . . . . . . . . . . . . . . . . . . . . . 416
B.2 Truncation Errors in Finite Difference Formulas . . . . . . . . . . . 417 B.2.1 Example: The Backward Difference for u0.t/ . . . . . . . . 417 B.2.2 Example: The Forward Difference for u0.t/ . . . . . . . . . 418 B.2.3 Example: The Central Difference for u0.t/ . . . . . . . . . 419 B.2.4 Overview of Leading-Order Error Terms in Finite
Difference Formulas . . . . . . . . . . . . . . . . . . . . . . . 420 B.2.5 Software for Computing Truncation Errors . . . . . . . . . 421
B.3 Exponential Decay ODEs . . . . . . . . . . . . . . . . . . . . . . . . . 422 B.3.1 Forward Euler Scheme . . . . . . . . . . . . . . . . . . . . . . 422 B.3.2 Crank-Nicolson Scheme . . . . . . . . . . . . . . . . . . . . . 423 B.3.3 The -Rule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424 B.3.4 Using Symbolic Software . . . . . . . . . . . . . . . . . . . . 424 B.3.5 Empirical Verification of the Truncation Error . . . . . . . 425 B.3.6 Increasing the Accuracy by Adding Correction Terms . . 430 B.3.7 Extension to Variable Coefficients . . . . . . . . . . . . . . . 432 B.3.8 Exact Solutions of the Finite Difference Equations . . . . 433 B.3.9 Computing Truncation Errors in Nonlinear Problems . . . 434
xviii Contents
B.4 Vibration ODEs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434 B.4.1 Linear Model Without Damping . . . . . . . . . . . . . . . . 434 B.4.2 Model with Damping and Nonlinearity . . . . . . . . . . . . 437 B.4.3 Extension to Quadratic Damping . . . . . . . . . . . . . . . 438 B.4.4 The General Model Formulated as First-Order ODEs . . . 439
B.5 Wave Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440 B.5.1 Linear Wave Equation in 1D . . . . . . . . . . . . . . . . . . 440 B.5.2 Finding Correction Terms . . . . . . . . . . . . . . . . . . . . 441 B.5.3 Extension to Variable Coefficients . . . . . . . . . . . . . . . 442 B.5.4 Linear Wave Equation in 2D/3D . . . . . . . . . . . . . . . . 444
B.6 Diffusion Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 B.6.1 Linear Diffusion Equation in 1D . . . . . . . . . . . . . . . . 445 B.6.2 Nonlinear Diffusion Equation in 1D . . . . . . . . . . . . . . 446
B.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
C Software Engineering; Wave Equation Model . . . . . . . . . . . . . . . 451 C.1 A 1D Wave Equation Simulator . . . . . . . . . . . . . . . . . . . . . 451
C.1.1 Mathematical Model . . . . . . . . . . . . . . . . . . . . . . . 451 C.1.2 Numerical Discretization . . . . . . . . . . . . . . . . . . . . 451 C.1.3 A Solver Function . . . . . . . . . . . . . . . . . . . . . . . . . 452
C.2 Saving Large Arrays in Files . . . . . . . . . . . . . . . . . . . . . . . 455 C.2.1 Using savez to Store Arrays in Files . . . . . . . . . . . . . 455 C.2.2 Using joblib to Store Arrays in Files . . . . . . . . . . . . 457 C.2.3 Using a Hash to Create a File or Directory Name . . . . . 458
C.3 Software for the 1D Wave Equation . . . . . . . . . . . . . . . . . . . 459 C.3.1 Making Hash Strings from Input Data . . . . . . . . . . . . 460 C.3.2 Avoiding Rerunning Previously Run Cases . . . . . . . . . 460 C.3.3 Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
C.4 Programming the Solver with Classes . . . . . . . . . . . . . . . . . . 462 C.4.1 Class Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 463 C.4.2 Class Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . 465 C.4.3 Class Mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465 C.4.4 Class Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 468 C.4.5 Class Solver . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
C.5 Migrating Loops to Cython . . . . . . . . . . . . . . . . . . . . . . . . 475 C.5.1 Declaring Variables and Annotating the Code . . . . . . . . 476 C.5.2 Visual Inspection of the C Translation . . . . . . . . . . . . 478 C.5.3 Building the Extension Module . . . . . . . . . . . . . . . . 479 C.5.4 Calling the Cython Function from Python . . . . . . . . . . 480
C.6 Migrating Loops to Fortran . . . . . . . . . . . . . . . . . . . . . . . . 480 C.6.1 The Fortran Subroutine . . . . . . . . . . . . . . . . . . . . . 481 C.6.2 Building the Fortran Module with f2py . . . . . . . . . . . . 482 C.6.3 How to Avoid Array Copying . . . . . . . . . . . . . . . . . . 483
C.7 Migrating Loops to C via Cython . . . . . . . . . . . . . . . . . . . . 485 C.7.1 Translating Index Pairs to Single Indices . . . . . . . . . . . 485 C.7.2 The Complete C Code . . . . . . . . . . . . . . . . . . . . . . 486 C.7.3 The Cython Interface File . . . . . . . . . . . . . . . . . . . . 486 C.7.4 Building the Extension Module . . . . . . . . . . . . . . . . 487
Contents xix
C.8 Migrating Loops to C via f2py . . . . . . . . . . . . . . . . . . . . . . 488 C.8.1 Migrating Loops to C++ via f2py . . . . . . . . . . . . . . . 489
C.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
List of Exercises, Problems and Projects
Problem 1.1: Use linear/quadratic functions for verification . . . . . . . . . . . 50 Exercise 1.2: Show linear growth of the phase with time . . . . . . . . . . . . . 51 Exercise 1.3: Improve the accuracy by adjusting the frequency . . . . . . . . . 51 Exercise 1.4: See if adaptive methods improve the phase error . . . . . . . . . . 52 Exercise 1.5: Use a Taylor polynomial to compute u1 . . . . . . . . . . . . . . . 52 Problem 1.6: Derive and investigate the velocity Verlet method . . . . . . . . . 52 Problem 1.7: Find the minimal resolution of an oscillatory function . . . . . . 52 Exercise 1.8: Visualize the accuracy of finite differences for a cosine function 53 Exercise 1.9: Verify convergence rates of the error in energy . . . . . . . . . . . 53 Exercise 1.10: Use linear/quadratic functions for verification . . . . . . . . . . . 53 Exercise 1.11: Use an exact discrete solution for verification . . . . . . . . . . . 53 Exercise 1.12: Use analytical solution for convergence rate tests . . . . . . . . 53 Exercise 1.13: Investigate the amplitude errors of many solvers . . . . . . . . . 54 Problem 1.14: Minimize memory usage of a simple vibration solver . . . . . . 54 Problem 1.15: Minimize memory usage of a general vibration solver . . . . . 56 Exercise 1.16: Implement the Euler-Cromer scheme for the generalized model 56 Problem 1.17: Interpret ŒDtDtu
n as a forward-backward difference . . . . . . 56 Exercise 1.18: Analysis of the Euler-Cromer scheme . . . . . . . . . . . . . . . 56 Exercise 1.19: Implement the solver via classes . . . . . . . . . . . . . . . . . . . 66 Problem 1.20: Use a backward difference for the damping term . . . . . . . . . 66 Exercise 1.21: Use the forward-backward scheme with quadratic damping . . 67 Exercise 1.22: Simulate resonance . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Exercise 1.23: Simulate oscillations of a sliding box . . . . . . . . . . . . . . . . 88 Exercise 1.24: Simulate a bouncing ball . . . . . . . . . . . . . . . . . . . . . . . 88 Exercise 1.25: Simulate a simple pendulum . . . . . . . . . . . . . . . . . . . . . 89 Exercise 1.26: Simulate an elastic pendulum . . . . . . . . . . . . . . . . . . . . . 89 Exercise 1.27: Simulate an elastic pendulum with air resistance . . . . . . . . . 90 Exercise 1.28: Implement the PEFRL algorithm . . . . . . . . . . . . . . . . . . 91 Exercise 2.1: Simulate a standing wave . . . . . . . . . . . . . . . . . . . . . . . . 122 Exercise 2.2: Add storage of solution in a user action function . . . . . . . . . . 123 Exercise 2.3: Use a class for the user action function . . . . . . . . . . . . . . . . 123 Exercise 2.4: Compare several Courant numbers in one movie . . . . . . . . . . 123 Exercise 2.5: Implementing the solver function as a generator . . . . . . . . . . 124 Project 2.6: Calculus with 1D mesh functions . . . . . . . . . . . . . . . . . . . . 124
xxi
xxii List of Exercises, Problems and Projects
Exercise 2.7: Find the analytical solution to a damped wave equation . . . . . 148 Problem 2.8: Explore symmetry boundary conditions . . . . . . . . . . . . . . . 148 Exercise 2.9: Send pulse waves through a layered medium . . . . . . . . . . . . 148 Exercise 2.10: Explain why numerical noise occurs . . . . . . . . . . . . . . . . 149 Exercise 2.11: Investigate harmonic averaging in a 1D model . . . . . . . . . . 149 Problem 2.12: Implement open boundary conditions . . . . . . . . . . . . . . . . 149 Exercise 2.13: Implement periodic boundary conditions . . . . . . . . . . . . . . 151 Exercise 2.14: Compare discretizations of a Neumann condition . . . . . . . . 151 Exercise 2.15: Verification by a cubic polynomial in space . . . . . . . . . . . . 152 Exercise 2.16: Check that a solution fulfills the discrete model . . . . . . . . . 181 Project 2.17: Calculus with 2D mesh functions . . . . . . . . . . . . . . . . . . . 181 Exercise 2.18: Implement Neumann conditions in 2D . . . . . . . . . . . . . . . 182 Exercise 2.19: Test the efficiency of compiled loops in 3D . . . . . . . . . . . . 182 Exercise 2.20: Simulate waves on a non-homogeneous string . . . . . . . . . . 195 Exercise 2.21: Simulate damped waves on a string . . . . . . . . . . . . . . . . . 195 Exercise 2.22: Simulate elastic waves in a rod . . . . . . . . . . . . . . . . . . . . 195 Exercise 2.23: Simulate spherical waves . . . . . . . . . . . . . . . . . . . . . . . 195 Problem 2.24: Earthquake-generated tsunami over a subsea hill . . . . . . . . . 196 Problem 2.25: Earthquake-generated tsunami over a 3D hill . . . . . . . . . . . 198 Problem 2.26: Investigate Mayavi for visualization . . . . . . . . . . . . . . . . . 199 Problem 2.27: Investigate visualization packages . . . . . . . . . . . . . . . . . . 199 Problem 2.28: Implement loops in compiled languages . . . . . . . . . . . . . . 199 Exercise 2.29: Simulate seismic waves in 2D . . . . . . . . . . . . . . . . . . . . 200 Project 2.30: Model 3D acoustic waves in a room . . . . . . . . . . . . . . . . . 200 Project 2.31: Solve a 1D transport equation . . . . . . . . . . . . . . . . . . . . . 201 Problem 2.32: General analytical solution of a 1D damped wave equation . . 204 Problem 2.33: General analytical solution of a 2D damped wave equation . . 205 Exercise 3.1: Explore symmetry in a 1D problem . . . . . . . . . . . . . . . . . . 242 Exercise 3.2: Investigate approximation errors from a ux D 0 boundary
condition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Exercise 3.3: Experiment with open boundary conditions in 1D . . . . . . . . . 243 Exercise 3.4: Simulate a diffused Gaussian peak in 2D/3D . . . . . . . . . . . . 244 Exercise 3.5: Examine stability of a diffusion model with a source term . . . . 245 Exercise 3.6: Stabilizing the Crank-Nicolson method by Rannacher time
stepping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 Project 3.7: Energy estimates for diffusion problems . . . . . . . . . . . . . . . . 316 Exercise 3.8: Splitting methods and preconditioning . . . . . . . . . . . . . . . . 318 Problem 3.9: Oscillating surface temperature of the earth . . . . . . . . . . . . . 319 Problem 3.10: Oscillating and pulsating flow in tubes . . . . . . . . . . . . . . . 320 Problem 3.11: Scaling a welding problem . . . . . . . . . . . . . . . . . . . . . . 320 Exercise 3.12: Implement a Forward Euler scheme for axi-symmetric diffusion 322 Exercise 4.1: Analyze 1D stationary convection-diffusion problem . . . . . . . 351 Exercise 4.2: Interpret upwind difference as artificial diffusion . . . . . . . . . 351 Problem 5.1: Determine if equations are nonlinear or not . . . . . . . . . . . . . 401 Problem 5.2: Derive and investigate a generalized logistic model . . . . . . . . 401 Problem 5.3: Experience the behavior of Newton’s method . . . . . . . . . . . . 402 Exercise 5.4: Compute the Jacobian of a 2 2 system . . . . . . . . . . . . . . . 402 Problem 5.5: Solve nonlinear equations arising from a vibration ODE . . . . . 402
List of Exercises, Problems and Projects xxiii
Exercise 5.6: Find the truncation error of arithmetic mean of products . . . . . 402 Problem 5.7: Newton’s method for linear problems . . . . . . . . . . . . . . . . 404 Problem 5.8: Discretize a 1D problem with a nonlinear coefficient . . . . . . . 404 Problem 5.9: Linearize a 1D problem with a nonlinear coefficient . . . . . . . 404 Problem 5.10: Finite differences for the 1D Bratu problem . . . . . . . . . . . . 404 Problem 5.11: Discretize a nonlinear 1D heat conduction PDE by finite
differences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 Problem 5.12: Differentiate a highly nonlinear term . . . . . . . . . . . . . . . . 405 Exercise 5.13: Crank-Nicolson for a nonlinear 3D diffusion equation . . . . . 406 Problem 5.14: Find the sparsity of the Jacobian . . . . . . . . . . . . . . . . . . . 406 Problem 5.15: Investigate a 1D problem with a continuation method . . . . . . 406 Exercise B.1: Truncation error of a weighted mean . . . . . . . . . . . . . . . . . 447 Exercise B.2: Simulate the error of a weighted mean . . . . . . . . . . . . . . . . 447 Exercise B.3: Verify a truncation error formula . . . . . . . . . . . . . . . . . . . 447 Problem B.4: Truncation error of the Backward Euler scheme . . . . . . . . . . 447 Exercise B.5: Empirical estimation of truncation errors . . . . . . . . . . . . . . 448 Exercise B.6: Correction term for a Backward Euler scheme . . . . . . . . . . . 448 Problem B.7: Verify the effect of correction terms . . . . . . . . . . . . . . . . . 448 Problem B.8: Truncation error of the Crank-Nicolson scheme . . . . . . . . . . 448 Problem B.9: Truncation error of u0 D f .u; t/ . . . . . . . . . . . . . . . . . . . 448 Exercise B.10: Truncation error of ŒDtDtu
n . . . . . . . . . . . . . . . . . . . . 449 Exercise B.11: Investigate the impact of approximating u0.0/ . . . . . . . . . . 449 Problem B.12: Investigate the accuracy of a simplified scheme . . . . . . . . . 449 Exercise C.1: Explore computational efficiency of numpy.sum versus built-in
sum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490 Exercise C.2: Make an improved numpy.savez function . . . . . . . . . . . . . 490 Exercise C.3: Visualize the impact of the Courant number . . . . . . . . . . . . 491 Exercise C.4: Visualize the impact of the resolution . . . . . . . . . . . . . . . . 491
1Vibration ODEs
Vibration problems lead to differential equations with solutions that oscillate in time, typically in a damped or undamped sinusoidal fashion. Such solutions put certain demands on the numerical methods compared to other phenomena whose solutions are monotone or very smooth. Both the frequency and amplitude of the oscillations need to be accurately handled by the numerical schemes. The forthcom- ing text presents a range of different methods, from classical ones (Runge-Kutta and midpoint/Crank-Nicolson methods), to more modern and popular symplectic (ge- ometric) integration schemes (Leapfrog, Euler-Cromer, and Störmer-Verlet meth- ods), but with a clear emphasis on the latter. Vibration problems occur throughout mechanics and physics, but the methods discussed in this text are also fundamen- tal for constructing successful algorithms for partial differential equations of wave nature in multiple spatial dimensions.
1.1 Finite Difference Discretization
Many of the numerical challenges faced when computing oscillatory solutions to ODEs and PDEs can be captured by the very simple ODE u00 C u D 0. This ODE is thus chosen as our starting point for method development, implementation, and analysis.
1.1.1 A Basic Model for Vibrations
The simplest model of a vibrating mechanical system has the following form:
u00 C !2u D 0; u.0/ D I; u0.0/ D 0; t 2 .0; T : (1.1)
Here, ! and I are given constants. Section 1.12.1 derives (1.1) from physical prin- ciples and explains what the constants mean.
The exact solution of (1.1) is
u.t/ D I cos.!t/ : (1.2)
1© The Author(s) 2017 H.P. Langtangen, S. Linge, Finite Difference Computing with PDEs, Texts in Computational Science and Engineering 16, DOI 10.1007/978-3-319-55456-3_1
2 1 Vibration ODEs
That is, u oscillates with constant amplitude I and angular frequency !. The corre- sponding period of oscillations (i.e., the time between two neighboring peaks in the cosine function) is P D 2=!. The number of periods per second is f D !=.2/ and measured in the unit Hz. Both f and ! are referred to as frequency, but ! is more precisely named angular frequency, measured in rad/s.
In vibrating mechanical systems modeled by (1.1), u.t/ very often represents a position or a displacement of a particular point in the system. The derivative u0.t/ then has the interpretation of velocity, and u00.t/ is the associated acceleration. The model (1.1) is not only applicable to vibrating mechanical systems, but also to oscillations in electrical circuits.
1.1.2 A Centered Finite Difference Scheme
To formulate a finite difference method for the model problem (1.1), we follow the four steps explained in Section 1.1.2 in [9].
Step 1: Discretizing the domain The domain is discretized by introducing a uniformly partitioned time mesh. The points in the mesh are tn D nt , n D 0; 1; : : : ; Nt , where t D T=Nt is the constant length of the time steps. We in- troduce a mesh function un for n D 0; 1; : : : ; Nt , which approximates the exact solution at the mesh points. (Note that n D 0 is the known initial condition, so un is identical to the mathematical u at this point.) The mesh function un will be computed from algebraic equations derived from the differential equation problem.
Step 2: Fulfilling the equation at discrete time points The ODE is to be satisfied at each mesh point where the solution must be found:
u00.tn/C !2u.tn/ D 0; n D 1; : : : ; Nt : (1.3)
Step 3: Replacing derivatives by finite differences The derivative u00.tn/ is to be replaced by a finite difference approximation. A common second-order accurate approximation to the second-order derivative is
u00.tn/ unC1 2un C un1 t2
: (1.4)
unC1 2un C un1 t2
D !2un : (1.5)
We also need to replace the derivative in the initial condition by a finite dif- ference. Here we choose a centered difference, whose accuracy is similar to the centered difference we used for u00:
u1 u1 2t
D 0 : (1.6)
1.1 Finite Difference Discretization 3
Step 4: Formulating a recursive algorithm To formulate the computational al- gorithm, we assume that we have already computed un1 and un, such that unC1 is the unknown value to be solved for:
unC1 D 2un un1 t2!2un : (1.7)
The computational algorithm is simply to apply (1.7) successively for n D 1; 2; : : : ; Nt 1. This numerical scheme sometimes goes under the name Störmer’s method, Verlet integration1, or the Leapfrog method (one should note that Leapfrog is used for many quite different methods for quite different differential equations!).
Computing the first step We observe that (1.7) cannot be used for n D 0 since the computation of u1 then involves the undefined value u1 at t D t . The discretization of the initial condition then comes to our rescue: (1.6) implies u1 D u1 and this relation can be combined with (1.7) for n D 0 to yield a value for u1:
u1 D 2u0 u1 t2!2u0;
which reduces to
u1 D u0 1 2 t2!2u0 : (1.8)
Exercise 1.5 asks you to perform an alternative derivation and also to generalize the initial condition to u0.0/ D V ¤ 0.
The computational algorithm The steps for solving (1.1) become
1. u0 D I 2. compute u1 from (1.8) 3. for n D 1; 2; : : : ; Nt 1: compute unC1 from (1.7)
The algorithm is more precisely expressed directly in Python:
t = linspace(0, T, Nt+1) # mesh points in time dt = t[1] - t[0] # constant time step u = zeros(Nt+1) # solution
u[0] = I u[1] = u[0] - 0.5*dt**2*w**2*u[0] for n in range(1, Nt):
u[n+1] = 2*u[n] - u[n-1] - dt**2*w**2*u[n]
Remark on using w for ! in computer code In the code, we use w as the symbol for !. The reason is that the authors prefer w for readability and comparison with the mathematical ! instead of the full word omega as variable name.
1 http://en.wikipedia.org/wiki/Verlet_integration
4 1 Vibration ODEs
Operator notation We may write the scheme using a compact difference notation listed in Appendix A.1 (see also Section 1.1.8 in [9]). The difference (1.4) has the operator notation ŒDtDtu
n such that we can write:
ŒDtDtuC !2u D 0n : (1.9)
Note that ŒDtDtu n means applying a central difference with step t=2 twice:
ŒDt.Dtu/ n D ŒDtu
nC 1 2 ŒDtu
1
t
t2 :
The discretization of initial conditions can in the operator notation be expressed as
Œu D I 0; ŒD2tu D 00; (1.10)
where the operator ŒD2tu n is defined as
ŒD2tu n D unC1 un1
2t : (1.11)
1.2.1 Making a Solver Function
The algorithm from the previous section is readily translated to a complete Python function for computing and returning u0; u1; : : : ; uNt and t0; t1; : : : ; tNt , given the input I , !, t , and T :
import numpy as np import matplotlib.pyplot as plt
def solver(I, w, dt, T): """ Solve u’’ + w**2*u = 0 for t in (0,T], u(0)=I and u’(0)=0, by a central finite difference method with time step dt. """ dt = float(dt) Nt = int(round(T/dt)) u = np.zeros(Nt+1) t = np.linspace(0, Nt*dt, Nt+1)
u[0] = I u[1] = u[0] - 0.5*dt**2*w**2*u[0] for n in range(1, Nt):
u[n+1] = 2*u[n] - u[n-1] - dt**2*w**2*u[n] return u, t
1.2 Implementation 5
We have imported numpy and matplotlib under the names np and plt, respec- tively, as this is very common in the Python scientific computing community and a good programming habit (since we explicitly see where the different functions come from). An alternative is to do from numpy import * and a similar “import all” for Matplotlib to avoid the np and plt prefixes and make the code as close as possible to MATLAB. (See Section 5.1.4 in [9] for a discussion of the two types of import in Python.)
A function for plotting the numerical and the exact solution is also convenient to have:
def u_exact(t, I, w): return I*np.cos(w*t)
def visualize(u, t, I, w): plt.plot(t, u, ’r--o’) t_fine = np.linspace(0, t[-1], 1001) # very fine mesh for u_e u_e = u_exact(t_fine, I, w) plt.hold(’on’) plt.plot(t_fine, u_e, ’b-’) plt.legend([’numerical’, ’exact’], loc=’upper left’) plt.xlabel(’t’) plt.ylabel(’u’) dt = t[1] - t[0] plt.title(’dt=%g’ % dt) umin = 1.2*u.min(); umax = -umin plt.axis([t[0], t[-1], umin, umax]) plt.savefig(’tmp1.png’); plt.savefig(’tmp1.pdf’)
A corresponding main program calling these functions to simulate a given number of periods (num_periods) may take the form
I = 1 w = 2*pi dt = 0.05 num_periods = 5 P = 2*pi/w # one period T = P*num_periods u, t = solver(I, w, dt, T) visualize(u, t, I, w, dt)
Adjusting some of the input parameters via the command line can be handy. Here is a code segment using the ArgumentParser tool in the argparse module to define option value (–option value) pairs on the command line:
import argparse parser = argparse.ArgumentParser() parser.add_argument(’--I’, type=float, default=1.0) parser.add_argument(’--w’, type=float, default=2*pi) parser.add_argument(’--dt’, type=float, default=0.05) parser.add_argument(’--num_periods’, type=int, default=5) a = parser.parse_args() I, w, dt, num_periods = a.I, a.w, a.dt, a.num_periods
6 1 Vibration ODEs
Such parsing of the command line is explained in more detail in Section 5.2.3 in [9].
A typical execution goes like
Terminal
Terminal> python vib_undamped.py --num_periods 20 --dt 0.1
Computing u0 In mechanical vibration applications one is often interested in com- puting the velocity v.t/ D u0.t/ after u.t/ has been computed. This can be done by a central difference,
v.tn/ D u0.tn/ vn D unC1 un1 2t
D ŒD2tu n : (1.12)
This formula applies for all inner mesh points, n D 1; : : : ; Nt 1. For n D 0, v.0/ is given by the initial condition on u0.0/, and for n D Nt we can use a one-sided, backward difference:
vn D ŒDt un D un un1
t :
v = np.zeros_like(u) # or v = np.zeros(len(u)) # Use central difference for internal points for i in range(1, len(u)-1):
v[i] = (u[i+1] - u[i-1])/(2*dt) # Use initial condition for u’(0) when i=0 v[0] = 0 # Use backward difference at the final mesh point v[-1] = (u[-1] - u[-2])/dt
Since the loop is slow for large Nt , we can get rid of the loop by vectorizing the central difference. The above code segment goes as follows in its vectorized version (see Problem 1.2 in [9] for explanation of details):
v = np.zeros_like(u) v[1:-1] = (u[2:] - u[:-2])/(2*dt) # central difference v[0] = 0 # boundary condition u’(0) v[-1] = (u[-1] - u[-2])/dt # backward difference
1.2.2 Verification
Manual calculation The simplest type of verification, which is also instructive for understanding the algorithm, is to compute u1, u2, and u3 with the aid of a calculator and make a function for comparing these results with those from the solver function. The test_three_steps function in the file vib_undamped.py shows the details of how we use the hand calculations to test the code:
1.2 Implementation 7
def test_three_steps(): from math import pi I = 1; w = 2*pi; dt = 0.1; T = 1 u_by_hand = np.array([1.000000000000000,
0.802607911978213, 0.288358920740053])
u, t = solver(I, w, dt, T) diff = np.abs(u_by_hand - u[:3]).max() tol = 1E-14 assert diff < tol
This function is a proper test function, compliant with the pytest and nose testing framework for Python code, because
the function name begins with test_ the function takes no arguments the test is formulated as a boolean condition and executed by assert
We shall in this book implement all software verification via such proper test func- tions, also known as unit testing. See Section 5.3.2 in [9] for more details on how to construct test functions and utilize nose or pytest for automatic execution of tests. Our recommendation is to use pytest. With this choice, you can run all test functions in vib_undamped.py by
Terminal
Terminal> py.test -s -v vib_undamped.py ============================= test session starts ======... platform linux2 -- Python 2.7.9 -- ... collected 2 items
vib_undamped.py::test_three_steps PASSED vib_undamped.py::test_convergence_rates PASSED
=========================== 2 passed in 0.19 seconds ===...
Testing very simple polynomial solutions Constructing test problems where the exact solution is constant or linear helps initial debugging and verification as one expects any reasonable numerical method to reproduce such solutions to machine precision. Second-order accurate methods will often also reproduce a quadratic solution. Here ŒDtDt t
2n D 2, which is the exact result. A solution u D t2
leads to u00 C !2u D 2 C .!t/2 ¤ 0. We must therefore add a source in the equation: u00 C !2u D f to allow a solution u D t2 for f D 2 C .!t/2. By simple insertion we can show that the mesh function un D t2n is also a solution of the discrete equations. Problem 1.1 asks you to carry out all details to show that linear and quadratic solutions are solutions of the discrete equations. Such results are very useful for debugging and verification. You are strongly encouraged to do this problem now!
Checking convergence rates Empirical computation of convergence rates yields a good method for verification. The method and its computational details are ex-
8 1 Vibration ODEs
plained in detail in Section 3.1.6 in [9]. Readers not familiar with the concept should look up this reference before proceeding.
In the present problem, computing convergence rates means that we must
perform m simulations, halving the time steps as: ti D 2it0, i D 1; : : : ;
m 1, and ti is the time step used in simulation i ;
compute the L2 norm of the error, Ei D q ti
PNt1 nD0 .un ue.tn//2 in each
case; estimate the convergence rates ri based on two consecutive experiments .ti1; Ei1/ and .ti ; Ei /, assuming Ei D C.ti /
r and Ei1 D C.ti1/r , where C is a constant. From these equations it follows that r D ln.Ei1=Ei /= ln.ti1=ti /. Since this r will vary with i , we equip it with an index and call it ri1, where i runs from 1 to m 1.
The computed rates r0; r1; : : : ; rm2 hopefully converge to the number 2 in the present problem, because theory (from Sect. 1.4) shows that the error of the numerical method we use behaves like t2. The convergence of the sequence r0; r1; : : : ; rm2 demands that the time steps ti are sufficiently small for the error model Ei D C.ti /r to be valid.
All the implementational details of computing the sequence r0; r1; : : : ; rm2 ap- pear below.
def convergence_rates(m, solver_function, num_periods=8): """ Return m-1 empirical estimates of the convergence rate based on m simulations, where the time step is halved for each simulation. solver_function(I, w, dt, T) solves each problem, where T is based on simulation for num_periods periods. """ from math import pi w = 0.35; I = 0.3 # just chosen values P = 2*pi/w # period dt = P/30 # 30 time step per period 2*pi/w T = P*num_periods
dt_values = [] E_values = [] for i in range(m):
u, t = solver_function(I, w, dt, T) u_e = u_exact(t, I, w) E = np.sqrt(dt*np.sum((u_e-u)**2)) dt_values.append(dt) E_values.append(E) dt = dt/2
r = [np.log(E_values[i-1]/E_values[i])/ np.log(dt_values[i-1]/dt_values[i]) for i in range(1, m, 1)]
return r, E_values, dt_values
The error analysis in Sect. 1.4 is quite detailed and suggests that r D 2. It is also a intuitively reasonable result, since we used a second-order accurate finite
1.2 Implementation 9
difference approximation ŒDtDtu n to the ODE and a second-order accurate finite
difference formula for the initial condition for u0. In the present problem, when t0 corresponds to 30 time steps per period, the
returned r list has all its values equal to 2.00 (if rounded to two decimals). This amazingly accurate result means that all ti values are well into the asymptotic regime where the error model Ei D C.ti /r is valid.
We can now construct a proper test function that computes convergence rates and checks that the final (and usually the best) estimate is sufficiently close to 2. Here, a rough tolerance of 0.1 is enough. Later, we will argue for an improvement by adjusting omega and include also that case in our test function here. The unit test goes like
def test_convergence_rates(): r, E, dt = convergence_rates(
m=5, solver_function=solver, num_periods=8) # Accept rate to 1 decimal place tol = 0.1 assert abs(r[-1] - 2.0) < tol # Test that adjusted w obtains 4th order convergence r, E, dt = convergence_rates(
m=5, solver_function=solver_adjust_w, num_periods=8) print ’adjust w rates:’, r assert abs(r[-1] - 4.0) < tol
The complete code appears in the file vib_undamped.py.
Visualizing convergence rates with slope markers Tony S. Yu has written a script plotslopes.py2 that is very useful to indicate the slope of a graph, es- pecially a graph like lnE D r lnt C lnC arising from the model E D Ctr . A copy of the script resides in the src/vib3 directory. Let us use it to compare the original method for u00 C !2u D 0 with the same method applied to the equa- tion with a modified !. We make log-log plots of the error versus t . For each curve we attach a slope marker using the slope_marker((x,y), r) function from plotslopes.py, where (x,y) is the position of the marker and r and the slope (.r; 1/), here (2,1) and (4,1).
def plot_convergence_rates(): r2, E2, dt2 = convergence_rates(
m=5, solver_function=solver, num_periods=8) plt.loglog(dt2, E2) r4, E4, dt4 = convergence_rates(
m=5, solver_function=solver_adjust_w, num_periods=8) plt.loglog(dt4, E4) plt.legend([’original scheme’, r’adjusted $\omega$’],
loc=’upper left’) plt.title(’Convergence of finite difference methods’) from plotslopes import slope_marker slope_marker((dt2[1], E2[1]), (2,1)) slope_marker((dt4[1], E4[1]), (4,1))
2 http://goo.gl/A4Utm7 3 http://tinyurl.com/nu656p2/vib
Fig. 1.1 Empirical convergence rate curves with special slope marker
Figure 1.1 displays the two curves with the markers. The match of the curve slope and the marker slope is excellent.
1.2.3 Scaled Model
It is advantageous to use dimensionless variables in simulations, because fewer pa- rameters need to be set. The present problem is made dimensionless by introducing dimensionless variables Nt D t=tc and Nu D u=uc, where tc and uc are characteristic scales for t and u, respectively. We refer to Section 2.2.1 in [11] for all details about this scaling.
The scaled ODE problem reads
uc
t2c
d 2 Nu d Nt2 C uc Nu D 0; uc Nu.0/ D I; uc
tc
d Nu d Nt .0/ D 0 :
A common choice is to take tc as one period of the oscillations, tc D 2=w, and uc D I . This gives the dimensionless model
d2 Nu d Nt2 C 4
2 Nu D 0; Nu.0/ D 1; Nu0.0/ D 0 : (1.13)
Observe that there are no physical parameters in (1.13)! We can therefore perform a single numerical simulation Nu.Nt / and afterwards recover any u.t I!; I / by
u.t I!; I / D uc Nu.t=tc/ D I Nu.!t=.2// : We can easily check this assertion: the solution of the scaled problem is Nu.Nt / D
cos.2 Nt/. The formula for u in terms of Nu gives u D I cos.!t/, which is nothing but the solution of the original problem with dimensions.
1.3 Visualization of Long Time Simulations 11
The scaled model can be run by calling solver(I=1, w=2*pi, dt, T). Each period is now 1 and T simply counts the number of periods. Choosing dt as 1./M gives M time steps per period.
1.3 Visualization of Long Time Simulations
Figure 1.2 shows a comparison of the exact and numerical solution for the scaled model (1.13) with t D 0:1; 0:05. From the plot we make the following observa- tions:
The numerical solution seems to have correct amplitude. There is an angular frequency error which is reduced by decreasing the time step. The total angular frequency error grows with time.
By angular frequency error we mean that the numerical angular frequency differs from the exact !. This is evident by looking at the peaks of the numerical solution: these have incorrect positions compared with the peaks of the exact cosine solution. The effect can be mathematically expressed by writing the numerical solution as I cos Q!t , where Q! is not exactly equal to !. Later, we shall mathematically quantify this numerical angular frequency Q!.
1.3.1 Using aMoving Plot Window
In vibration problems it is often of interest to investigate the system’s behavior over long time intervals. Errors in the angular frequency accumulate and become more visible as time grows. We can investigate long time series by introducing a moving plot window that can move along with the p most recently computed periods of the solution. The SciTools4 package contains a convenient tool for this: MovingPlotWindow. Typing pydoc scitools.MovingPlotWindow shows a demo and a description of its use. The function below utilizes the moving plot
Fig. 1.2 Effect of halving the time step
4 https://github.com/hplgit/scitools
12 1 Vibration ODEs
window and is in fact called by the main function in the vib_undampedmodule if the number of periods in the simulation exceeds 10.
def visualize_front(u, t, I, w, savefig=False, skip_frames=1): """ Visualize u and the exact solution vs t, using a moving plot window and continuous drawing of the curves as they evolve in time. Makes it easy to plot very long time series. Plots are saved to files if savefig is True. Only each skip_frames-th plot is saved (e.g., if skip_frame=10, only each 10th plot is saved to file; this is convenient if plot files corresponding to different time steps are to be compared). """ import scitools.std as st from scitools.MovingPlotWindow import MovingPlotWindow from math import pi
# Remove all old plot files tmp_*.png import glob, os for filename in glob.glob(’tmp_*.png’):
os.remove(filename)
P = 2*pi/w # one period umin = 1.2*u.min(); umax = -umin dt = t[1] - t[0] plot_manager = MovingPlotWindow(
window_width=8*P, dt=dt, yaxis=[umin, umax], mode=’continuous drawing’)
frame_counter = 0 for n in range(1,len(u)):
if plot_manager.plot(n): s = plot_manager.first_index_in_plot st.plot(t[s:n+1], u[s:n+1], ’r-1’,
t[s:n+1], I*cos(w*t)[s:n+1], ’b-1’, title=’t=%6.3f’ % t[n], axis=plot_manager.axis(), show=not savefig) # drop window if savefig
if savefig and n % skip_frames == 0: filename = ’tmp_%04d.png’ % frame_counter st.savefig(filename) print ’making plot file’, filename, ’at t=%g’ % t[n] frame_counter += 1
plot_manager.update(n)
We run the scaled problem (the default values for the command-line arguments –I and –w correspond to the scaled problem) for 40 periods with 20 time steps per period:
Terminal
Terminal> python vib_undamped.py --dt 0.05 --num_periods 40
1.3 Visualization of Long Time Simulations 13
The moving plot window is invoked, and we can follow the numerical and exact solutions as time progresses. From this demo we see that the angular frequency error is small in the beginning, and that it becomes more prominent with time. A new run with t D 0:1 (i.e., only 10 time steps per period) clearly shows that the phase errors become significant even earlier in the time series, deteriorating the solution further.
1.3.2 Making Animations
Producing standard video formats The visualize_front function stores all the plots in files whose names are numbered: tmp_0000.png, tmp_0001.png, tmp_0002.png, and so on. From these files we may make a movie. The Flash format is popular,
Terminal
Terminal> ffmpeg -r 25 -i tmp_%04d.png -c:v flv movie.flv
The ffmpeg program can be replaced by the avconv program in the above com- mand if desired (but at the time of this writing it seems to be more momentum in the ffmpeg project). The -r option should come first and describes the number of frames per second in the movie (even if we would like to have slow movies, keep this number as large as 25, otherwise files are skipped from the movie). The -i option describes the name of the plot files. Other formats can be generated by changing the video codec and equipping the video file with the right extension:
Format Codec and filename Flash -c:v flv movie.flv MP4 -c:v libx264 movie.mp4 WebM -c:v libvpx movie.webm Ogg -c:v libtheora movie.ogg
The video file can be played by some video player like vlc, mplayer, gxine, or totem, e.g.,
Terminal
Terminal> vlc movie.webm
A web page can also be used to play the movie. Today’s standard is to use the HTML5 video tag:
<video autoplay loop controls width=’640’ height=’365’ preload=’none’>
<source src=’movie.webm’ type=’video/webm; codecs="vp8, vorbis"’> </video>
14 1 Vibration ODEs
Modern browsers do not support all of the video formats. MP4 is needed to suc- cessfully play the videos on Apple devices that use the Safari browser. WebM is the preferred format for Chrome, Opera, Firefox, and Internet Explorer v9+. Flash was a popular format, but older browsers that required Flash can play MP4. All browsers that work with Ogg can also work with WebM. This means that to have a video work in all browsers, the video should be available in the MP4 and WebM formats. The proper HTML code reads
<video autoplay loop controls width=’640’ height=’365’ preload=’none’>
<source src=’movie.mp4’ type=’video/mp4; codecs="avc1.42E01E, mp4a.40.2"’>
<source src=’movie.webm’ type=’video/webm; codecs="vp8, vorbis"’>
</video>
The MP4 format should appear first to ensure that Apple devices will load the video correctly.
Caution: number the plot files correctly To ensure that the individual plot frames are shown in correct order, it is im- portant to number the files with zero-padded numbers (0000, 0001, 0002, etc.). The printf format %04d specifies an integer in a field of width 4, padded with zeros from the left. A simple Unix wildcard file specification like tmp_*.png will then list the frames in the right order. If the numbers in the filenames were not zero-padded, the frame tmp_11.pngwould appear before tmp_2.png in the movie.
Playing PNG files in a web browser The scitools movie command can create a movie player for a set of PNG files such that a web browser can be used to watch the movie. This interface has the advantage that the speed of the movie can easily be controlled, a feature that scientists often appreciate. The command for creating an HTML with a player for a set of PNG files tmp_*.png goes like
Terminal
Terminal> scitools movie output_file=vib.html fps=4 tmp_*.png
The fps argument controls the speed of the movie (“frames per second”). To watch the movie, load the video file vib.html into some browser, e.g.,
Terminal
1.3 Visualization of Long Time Simulations 15
Click on Start movie to see the result. Moving this movie to some other place requires moving vib.html and all the PNG files tmp_*.png:
Terminal
Terminal> mkdir vib_dt0.1 Terminal> mv tmp_*.png vib_dt0.1 Terminal> mv vib.html vib_dt0.1/index.html
Making animated GIF files The convert program from the ImageMagick soft- ware suite can be used to produce animated GIF files from a set of PNG files:
Terminal
Terminal> convert -delay 25 tmp_vib*.png tmp_vib.gif
The -delay option needs an argument of the delay between each frame, measured in 1/100 s, so 4 frames/s here gives 25/100 s delay. Note, however, that in this particular example with t D 0:05 and 40 periods, making an animated GIF file out of the large number of PNG files is a very heavy process and not considered feasible. Animated GIFs are best suited for animations with not so many frames and where you want to see each frame and play them slowly.
1.3.3 Using Bokeh to Compare Graphs
Instead of a moving plot frame, one can use tools that allow panning by the mouse. For example, we can show four periods of several signals in several plots and then scroll with the mouse through the rest of the simulation simultaneously in all the plot windows. The Bokeh5 plotting library offers such tools, but the plots must be displayed in a web browser. The documentation of Bokeh is excellent, so here we just show how the library can be used to compare a set of u curves corresponding to long time simulations. (By the way, the guidance to correct pronunciation of Bokeh in the documentation6 and onWikipedia7 is not directly compatible with a YouTube video8 . . . ).
Imagine we have performed experiments for a set of t values. We want each curve, together with the exact solution, to appear in a plot, and then arrange all plots in a grid-like fashion:
5 http://bokeh.pydata.org/en/latest 6 http://bokeh.pydata.org/en/0.10.0/docs/faq.html#how-do-you-pronounce-bokeh 7 https://en.wikipedia.org/wiki/Bokeh 8 https://www.youtube.com/watch?v=OR8HSHevQTM
16 1 Vibration ODEs
Furthermore, we want the axes to couple such that if we move into the future in one plot, all the other plots follows (note the displaced t axes!):
A function for creating a Bokeh plot, given a list of u arrays and corresponding t arrays, is implemented below. The code combines data from different simulations, described compactly in a list of strings legends.
1.3 Visualization of Long Time Simulations 17
def bokeh_plot(u, t, legends, I, w, t_range, filename): """ Make plots for u vs t using the Bokeh library. u and t are lists (several experiments can be compared). legens contain legend strings for the various u,t pairs. """ if not isinstance(u, (list,tuple)):
u = [u] # wrap in list if not isinstance(t, (list,tuple)):
t = [t] # wrap in list if not isinstance(legends, (list,tuple)):
legends = [legends] # wrap in list
import bokeh.plotting as plt plt.output_file(filename, mode=’cdn’, title=’Comparison’) # Assume that all t arrays have the same range t_fine = np.linspace(0, t[0][-1], 1001) # fine mesh for u_e tools = ’pan,wheel_zoom,box_zoom,reset,’\
’save,box_select,lasso_select’ u_range = [-1.2*I, 1.2*I] font_size = ’8pt’ p = [] # list of plot objects # Make the first figure p_ = plt.figure(
width=300, plot_height=250, title=legends[0], x_axis_label=’t’, y_axis_label=’u’, x_range=t_range, y_range=u_range, tools=tools, title_text_font_size=font_size)
p_.xaxis.axis_label_text_font_size=font_size p_.yaxis.axis_label_text_font_size=font_size p_.line(t[0], u[0], line_color=’blue’) # Add exact solution u_e = u_exact(t_fine, I, w) p_.line(t_fine, u_e, line_color=’red’, line_dash=’4 4’) p.append(p_) # Make the rest of the figures and attach their axes to # the first figure’s axes for i in range(1, len(t)):
p_ = plt.figure( width=300, plot_height=250, title=legends[i], x_axis_label=’t’, y_axis_label=’u’, x_range=p[0].x_range, y_range=p[0].y_range, tools=tools, title_text_font_size=font_size)
p_.xaxis.axis_label_text_font_size = font_size p_.yaxis.axis_label_text_font_size = font_size p_.line(t[i], u[i], line_color=’blue’) p_.line(t_fine, u_e, line_color=’red’, line_dash=’4 4’) p.append(p_)
# Arrange all plots in a grid with 3 plots per row grid = [[]] for i, p_ in enumerate(p):
grid[-1].append(p_) if (i+1) % 3 == 0:
# New row grid.append([])
18 1 Vibration ODEs
A particular example using the bokeh_plot function appears below.
def demo_bokeh(): """Solve a scaled ODE u’’ + u = 0.""" from math import pi w = 1.0 # Scaled problem (frequency) P = 2*np.pi/w # Period num_steps_per_period = [5, 10, 20, 40, 80] T = 40*P # Simulation time: 40 periods u = [] # List of numerical solutions t = [] # List of corresponding meshes legends = [] for n in num_steps_per_period:
dt = P/n u_, t_ = solver(I=1, w=w, dt=dt, T=T) u.append(u_) t.append(t_) legends.append(’# time steps per period: %d’ % n)
bokeh_plot(u, t, legends, I=1, w=w, t_range=[0, 4*P], filename=’tmp.html’)
1.3.4 Using a Line-by-Line Ascii Plotter
Plotting functions vertically, line by line, in the terminal window using ascii char- acters only is a simple, fast, and convenient visualization technique for long time series. Note that the time axis then is positive downwards on the screen, so we can let the solution be visualized “forever”. The tool scitools.avplotter.Plotter makes it easy to create such plots:
def visualize_front_ascii(u, t, I, w, fps=10): """ Plot u and the exact solution vs t line by line in a terminal window (only using ascii characters). Makes it easy to plot very long time series. """ from scitools.avplotter import Plotter import time from math import pi P = 2*pi/w umin = 1.2*u.min(); umax = -umin
p = Plotter(ymin=umin, ymax=umax, width=60, symbols=’+o’) for n in range(len(u)):
print p.plot(t[n], u[n], I*cos(w*t[n])), \ ’%.1f’ % (t[n]/P)
time.sleep(1/float(fps))
The call p.plot returns a line of text, with the t axis marked and a symbol + for the first function (u) and o for the second function (the exact solution). Here we append to this text a time counter reflecting how many periods the current time point corresponds to. A typical output (! D 2 , t D 0:05) looks like this:
1.3 Visualization of Long Time Simulations 19
| o+ 14.0 | + o 14.0 | + o 14.1 | + o 14.1 | + o 14.2
+| o 14.2 + | 14.2
o + | 14.6 o + | 14.7
o | + 14.7 | + 14.8 | o + 14.8 | o + 14.9 | o + 14.9 | o+ 15.0
1.3.5 Empirical Analysis of the Solution
For oscillating functions like those in Fig. 1.2 we may compute the amplitude and frequency (or period) empirically. That is, we run through the discrete solution points .tn; un/ and find all maxima and minima points. The distance between two consecutive maxima (or minima) points can be used as estimate of the local period, while half the difference between the u value at a maximum and a nearby minimum gives an estimate of the local amplitude.
The local maxima are the points where
un1 < un > unC1; n D 1; : : : ; Nt 1; (1.14)
and the local minima are recognized by
un1 > un < unC1; n D 1; : : : ; Nt 1 : (1.15)
In computer code this becomes
def minmax(t, u): minima = []; maxima = [] for n in range(1, len(u)-1, 1):
if u[n-1] > u[n] < u[n+1]: minima.append((t[n], u[n]))
if u[n-1] < u[n] > u[n+1]: maxima.append((t[n], u[n]))
return minima, maxima
Note that the two returned objects are lists of tuples.
20 1 Vibration ODEs
Let .ti ; ei /, i