├── .gitignore
├── 00_intro.ipynb
├── 01_linear_hyperbolic.ipynb
├── 02_finite_volume.ipynb
├── 03_high_resolution.ipynb
├── 04_bc.ipynb
├── 05_convergence.ipynb
├── 06_nonlinear_scalar.ipynb
├── 07_nonlinear_scalar_FVM.ipynb
├── 08_nonlinear_systems.ipynb
├── 09_fv_nonlinear.ipynb
├── 10_balance_laws.ipynb
├── 11_multidimension.ipynb
├── LICENSE
├── MIT_LICENSE
├── README.md
└── images
└── CC-BY.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/python
2 | # Edit at https://www.gitignore.io/?templates=python
3 |
4 | ### Python ###
5 | # Byte-compiled / optimized / DLL files
6 | __pycache__/
7 | *.py[cod]
8 | *$py.class
9 |
10 | # C extensions
11 | *.so
12 |
13 | # Distribution / packaging
14 | .Python
15 | build/
16 | develop-eggs/
17 | dist/
18 | downloads/
19 | eggs/
20 | .eggs/
21 | lib/
22 | lib64/
23 | parts/
24 | sdist/
25 | var/
26 | wheels/
27 | pip-wheel-metadata/
28 | share/python-wheels/
29 | *.egg-info/
30 | .installed.cfg
31 | *.egg
32 | MANIFEST
33 |
34 | # PyInstaller
35 | # Usually these files are written by a python script from a template
36 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
37 | *.manifest
38 | *.spec
39 |
40 | # Installer logs
41 | pip-log.txt
42 | pip-delete-this-directory.txt
43 |
44 | # Unit test / coverage reports
45 | htmlcov/
46 | .tox/
47 | .nox/
48 | .coverage
49 | .coverage.*
50 | .cache
51 | nosetests.xml
52 | coverage.xml
53 | *.cover
54 | .hypothesis/
55 | .pytest_cache/
56 |
57 | # Translations
58 | *.mo
59 | *.pot
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # pyenv
71 | .python-version
72 |
73 | # pipenv
74 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
75 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
76 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
77 | # install all needed dependencies.
78 | #Pipfile.lock
79 |
80 | # celery beat schedule file
81 | celerybeat-schedule
82 |
83 | # SageMath parsed files
84 | *.sage.py
85 |
86 | # Spyder project settings
87 | .spyderproject
88 | .spyproject
89 |
90 | # Rope project settings
91 | .ropeproject
92 |
93 | # Mr Developer
94 | .mr.developer.cfg
95 | .project
96 | .pydevproject
97 |
98 | # mkdocs documentation
99 | /site
100 |
101 | # mypy
102 | .mypy_cache/
103 | .dmypy.json
104 | dmypy.json
105 |
106 | # Pyre type checker
107 | .pyre/
108 |
109 | # End of https://www.gitignore.io/api/python
110 |
111 | *.slides.html
112 | .ipynb_checkpoints/
--------------------------------------------------------------------------------
/00_intro.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "skip"
8 | }
9 | },
10 | "source": [
11 | "
\n",
12 | " \n",
13 | " | Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli | \n",
14 | "
"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "slideshow": {
22 | "slide_type": "skip"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "from __future__ import print_function\n",
28 | "\n",
29 | "%matplotlib inline\n",
30 | "import numpy\n",
31 | "import matplotlib.pyplot as plt"
32 | ]
33 | },
34 | {
35 | "cell_type": "markdown",
36 | "metadata": {
37 | "slideshow": {
38 | "slide_type": "slide"
39 | }
40 | },
41 | "source": [
42 | "# Finite Volume Methods for Hyperbolic Partial Differential Equations"
43 | ]
44 | },
45 | {
46 | "cell_type": "markdown",
47 | "metadata": {
48 | "slideshow": {
49 | "slide_type": "slide"
50 | }
51 | },
52 | "source": [
53 | "## What are Hyperbolic PDEs?"
54 | ]
55 | },
56 | {
57 | "cell_type": "markdown",
58 | "metadata": {
59 | "slideshow": {
60 | "slide_type": "subslide"
61 | }
62 | },
63 | "source": [
64 | "### PDE Classification - Traditional View\n",
65 | "\n",
66 | "As you may know there are a number of classifications for PDEs, the best known are elliptic, parabolic and hyperbolic. These classifications are based on a canonical linear, second order PDE of the form\n",
67 | "$$\n",
68 | " A u_{xx} + 2 B u_{xy} + C u_{yy} + \\cdots = 0.\n",
69 | "$$"
70 | ]
71 | },
72 | {
73 | "cell_type": "markdown",
74 | "metadata": {
75 | "slideshow": {
76 | "slide_type": "subslide"
77 | }
78 | },
79 | "source": [
80 | "The names of the classification come from the an analogy to the equation for a conic section\n",
81 | "$$\n",
82 | " A x^2 + 2 B x y + C y^2 + \\cdots = 0\n",
83 | "$$\n",
84 | "where the **discriminant**, defined as\n",
85 | "$$\n",
86 | " d \\equiv B^2 - 4 A C,\n",
87 | "$$\n",
88 | "determines the classification:\n",
89 | " - if $d < 0$ then the equation is **elliptic**,\n",
90 | " - if $d = 0$ then the equation is **parabolic** and\n",
91 | " - if $d > 0$ then the equation is **hyperbolic**."
92 | ]
93 | },
94 | {
95 | "cell_type": "markdown",
96 | "metadata": {
97 | "slideshow": {
98 | "slide_type": "subslide"
99 | }
100 | },
101 | "source": [
102 | "We can generalize this further if we define the general linear operator\n",
103 | "$$\n",
104 | " L u = \\sum^n_{i=1} \\sum^n_{j=1} a_{ij} \\frac{\\partial^2 u}{\\partial x_i \\partial x_j} + \\cdots.\n",
105 | "$$\n",
106 | "where now the classification is based on the eigenvalues $\\lambda$ as follows:\n",
107 | " - if all $\\lambda$ are either positive or negative then operator is **elliptic**,\n",
108 | " - if all $\\lambda$ are either positive or negative except for one that is zero the operator is **parabolic**,\n",
109 | " - if all $\\lambda$ are either positive save for one negative or all negative save for one positive then the operator is **hyperbolic** and\n",
110 | " - if some $\\lambda$ are either positive or negative then the operator is **ultrahyperbolic**."
111 | ]
112 | },
113 | {
114 | "cell_type": "markdown",
115 | "metadata": {
116 | "slideshow": {
117 | "slide_type": "subslide"
118 | }
119 | },
120 | "source": [
121 | "### PDE Classification - A More Useful View\n",
122 | "\n",
123 | "Most of the different classifications above have properties to them that are more useful to think about:\n",
124 | " - Elliptic PDEs, such as $\\nabla^2 u = f$, describe purely spatial problems.\n",
125 | " - Parabolic PDEs, such as $\\nabla^2 u = u_t$, describe time dependent diffusion moving the quantity $u$ at infinite speed across the domain.\n",
126 | " - Hyperbolic PDEs, such as $u_t + u_x = 0$ describe the movement of the quantity $u$ from one place to another at a finite speed.\n",
127 | " "
128 | ]
129 | },
130 | {
131 | "cell_type": "markdown",
132 | "metadata": {
133 | "slideshow": {
134 | "slide_type": "subslide"
135 | }
136 | },
137 | "source": [
138 | "This speed of propagation is quintessential for our discussion regarding hyperbolic PDEs and will form arguably a more useful definition later."
139 | ]
140 | },
141 | {
142 | "cell_type": "markdown",
143 | "metadata": {
144 | "slideshow": {
145 | "slide_type": "subslide"
146 | }
147 | },
148 | "source": [
149 | "In general a linear system of first order PDEs can be written as:\n",
150 | "$$\n",
151 | " q_t(x, t) + A q_x(x, t) = 0\n",
152 | "$$\n",
153 | "where $A \\in \\mathbb R^{m \\times m}$ and therefore $q: \\mathbb R \\times \\mathbb R \\rightarrow \\mathbb R^m$. For the system to be hyperbolic the matrix $A$ must satisfy certain properties that we will mention later."
154 | ]
155 | },
156 | {
157 | "cell_type": "markdown",
158 | "metadata": {
159 | "slideshow": {
160 | "slide_type": "subslide"
161 | }
162 | },
163 | "source": [
164 | "In the simplest case the matrix $A$ is a scalar value. If that value is real then the scalar PDE is considered hyperbolic."
165 | ]
166 | },
167 | {
168 | "cell_type": "markdown",
169 | "metadata": {
170 | "slideshow": {
171 | "slide_type": "subslide"
172 | }
173 | },
174 | "source": [
175 | "#### General Hyperbolicity of a System\n",
176 | "\n",
177 | "A linear system of the form\n",
178 | "$$\n",
179 | " q_t + A q_x = 0\n",
180 | "$$\n",
181 | "is called **hyperbolic** if the $m \\times m$ matrix $A$ is diagonalizable with real eigenvalues. This requirement is equivalent to saying the eigenspace of $A$ is full."
182 | ]
183 | },
184 | {
185 | "cell_type": "markdown",
186 | "metadata": {
187 | "slideshow": {
188 | "slide_type": "subslide"
189 | }
190 | },
191 | "source": [
192 | "### Examples:\n",
193 | "\n",
194 | "*Advective Transport*: The equation\n",
195 | "$$\n",
196 | " q_t + u q_x = 0\n",
197 | "$$\n",
198 | "where $u \\in \\mathbb R$ describes the transport of the quantity $q$ at a speed $u$. This is analogous to wave motion."
199 | ]
200 | },
201 | {
202 | "cell_type": "markdown",
203 | "metadata": {
204 | "slideshow": {
205 | "slide_type": "subslide"
206 | }
207 | },
208 | "source": [
209 | "*Wave Equation*: The wave equation is generally written as\n",
210 | "$$\n",
211 | " q_{tt} + u^2 q_{xx} = 0,\n",
212 | "$$\n",
213 | "which clearly breaks our classification view. Instead we can rewrite the above equations as two first order PDEs such that\n",
214 | "$$\\begin{aligned}\n",
215 | " &(q_1)_t + u (q_1)_x = 0,\\\\\n",
216 | " &(q_2)_t - u (q_2)_x = 0.\n",
217 | "\\end{aligned}$$"
218 | ]
219 | },
220 | {
221 | "cell_type": "markdown",
222 | "metadata": {
223 | "slideshow": {
224 | "slide_type": "subslide"
225 | }
226 | },
227 | "source": [
228 | "One common system like this is the linear acoustics equations that can be written in this second form as\n",
229 | "$$\\begin{aligned}\n",
230 | " &p_t + K u_x = 0,\\\\\n",
231 | " &u_t + \\frac{1}{\\rho} p_x = 0\n",
232 | "\\end{aligned}$$\n",
233 | "where $p$ is the pressure, $K$ the bulk modulus, $u$ the velocity and $\\rho$ the density. Note that if we write this as a second order, single equation with\n",
234 | "$$\n",
235 | " w_1 = p + \\rho c u \\quad \\quad w_2 = p - \\rho c u\n",
236 | "$$\n",
237 | "then we have\n",
238 | "$$\n",
239 | " (w_2)_t - c (w_2)_x = 0\n",
240 | "$$\n",
241 | "where $c = \\sqrt{K / \\rho}$, the speed of sound. Even more simply we can also write\n",
242 | "$$\n",
243 | " p_{tt} - c^2 p_{xx} = 0.\n",
244 | "$$"
245 | ]
246 | },
247 | {
248 | "cell_type": "markdown",
249 | "metadata": {
250 | "slideshow": {
251 | "slide_type": "subslide"
252 | }
253 | },
254 | "source": [
255 | "### Conservation Laws\n",
256 | "\n",
257 | "One of the most important types of hyperbolic PDEs are called **conservation laws**. These equations describe the conservation of the quantity represented by the unknown function and are homogeneous. They take the general form\n",
258 | "$$\n",
259 | " q_t(x, t) + f(q(x, t))_x = 0\n",
260 | "$$\n",
261 | "or in the quasi-linear form\n",
262 | "$$\n",
263 | " q_t + f'(q) q_x = 0\n",
264 | "$$\n",
265 | "where $f$ is the **flux function** and $f'(q)$ is the Jacobian with respect to the variable $q$."
266 | ]
267 | },
268 | {
269 | "cell_type": "markdown",
270 | "metadata": {
271 | "slideshow": {
272 | "slide_type": "subslide"
273 | }
274 | },
275 | "source": [
276 | "#### Integral Forms\n",
277 | "\n",
278 | "The more fundamental version of a conservation law is the integral form that can be stated as\n",
279 | "$$\n",
280 | " \\frac{\\text{d}}{\\text{d} t} \\int^{x_2}_{x_1} q(x, t) dx = f(q(x_1, t)) - f(q(x_2, t)). \n",
281 | "$$\n",
282 | "where $x_2 > x_1 \\in \\Omega$ and $\\Omega$ is some domain. In words this is saying that if we integrate over the interval $[x_1, x_2]$ that the time rate of change on that interval is determined by the flux function evaluated at the ends of the interval."
283 | ]
284 | },
285 | {
286 | "cell_type": "markdown",
287 | "metadata": {
288 | "slideshow": {
289 | "slide_type": "subslide"
290 | }
291 | },
292 | "source": [
293 | "If $q$ and $f(q)$ are sufficiently smooth we can manipulate the integral form to the differential form as follows:\n",
294 | "$$\\begin{aligned}\n",
295 | " \\frac{\\text{d}}{\\text{d} t} \\int^{x_2}_{x_1} q(x, t) dx &= f(q(x_1, t)) - f(q(x_2, t)) && \\text{Original}\\\\\n",
296 | " \\frac{\\text{d}}{\\text{d} t} \\int^{x_2}_{x_1} q(x, t) dx &= -\\frac{\\partial}{\\partial x} \\int^{x_2}_{x_1} f(q(x, t)) dx && \\text{?} \\\\\n",
297 | " \\int^{x_2}_{x_1} \\left[ q_t(x, t) + f_x(q(x, t)) \\right] dx &=0 && \\text{?} \\\\\n",
298 | " q_t(x, t) + f_x(q(x, t)) &= 0. && \\text{?}\n",
299 | "\\end{aligned}$$"
300 | ]
301 | },
302 | {
303 | "cell_type": "markdown",
304 | "metadata": {
305 | "slideshow": {
306 | "slide_type": "slide"
307 | }
308 | },
309 | "source": [
310 | "## Where do Hyperbolic PDEs Arise?"
311 | ]
312 | },
313 | {
314 | "cell_type": "markdown",
315 | "metadata": {
316 | "slideshow": {
317 | "slide_type": "subslide"
318 | }
319 | },
320 | "source": [
321 | "### Advection\n",
322 | "\n",
323 | "$$\n",
324 | " q_t + u q_x = 0\n",
325 | "$$"
326 | ]
327 | },
328 | {
329 | "cell_type": "markdown",
330 | "metadata": {
331 | "slideshow": {
332 | "slide_type": "subslide"
333 | }
334 | },
335 | "source": [
336 | "#### Pipes\n",
337 | "\n",
338 | "1. Try to draw and derive the equation for a quantity of fluid going through a pipe that has length $L$ with known fluxes through each end of the pipe.\n",
339 | "1. Say we knew that the velocity of fluid at both ends of the pipe and this did not depend on the quantity $q$. What are the equations now?"
340 | ]
341 | },
342 | {
343 | "cell_type": "markdown",
344 | "metadata": {
345 | "slideshow": {
346 | "slide_type": "subslide"
347 | }
348 | },
349 | "source": [
350 | "### Fluid Dynamics\n",
351 | "\n",
352 | "Fluids are generally governed fundamentally by a set of conservation laws and then a number of assumptions applied which may or may not cause them to become non-hyperbolic."
353 | ]
354 | },
355 | {
356 | "cell_type": "markdown",
357 | "metadata": {
358 | "slideshow": {
359 | "slide_type": "subslide"
360 | }
361 | },
362 | "source": [
363 | "#### Mass\n",
364 | "\n",
365 | "The first equation is for the conservation of mass. In this case, as our equations are coming from a more fundamental integral conservation law, we care about the density $\\rho$. We can then write the conservation of mass in its differential form as\n",
366 | "$$\n",
367 | " \\rho_t + u \\rho_x = 0\n",
368 | "$$\n",
369 | "This is exactly our equation for advection of a quantity and assumes that $u$ is constant."
370 | ]
371 | },
372 | {
373 | "cell_type": "markdown",
374 | "metadata": {
375 | "slideshow": {
376 | "slide_type": "subslide"
377 | }
378 | },
379 | "source": [
380 | "If $u(x, t)$ is varying and dependent on $\\rho$, which in general it is, we write\n",
381 | "$$\n",
382 | " \\rho_t + (u \\rho)_x = 0.\n",
383 | "$$\n",
384 | "Note that now the equations are non-linear if we added an equation for $u$ or as we will in a second for the momentum $\\rho u$."
385 | ]
386 | },
387 | {
388 | "cell_type": "markdown",
389 | "metadata": {
390 | "slideshow": {
391 | "slide_type": "fragment"
392 | }
393 | },
394 | "source": [
395 | "#### Momentum\n",
396 | "\n",
397 | "We now turn to Newton's second law\n",
398 | "$$\n",
399 | " \\frac{\\text{D}}{\\text{D} t} (\\rho u) = \\sum forces.\n",
400 | "$$\n",
401 | "Note that the right hand side of the equation no longer has an ordinary or partial derivative but instead has a **total derivative** or **material derivative**. In a *Lagrangian coordinate systems* (our coordinate system moves with the fluid) this is identical to an ordinary derivative in time. In *Eulerian coordinate systems* (we are fixed in space and the fluid moves past us) this is more complex. Instead we have\n",
402 | "$$\n",
403 | " \\frac{\\text{D}}{\\text{D} t} q = q_t + (u q)_x.\n",
404 | "$$\n",
405 | "In our case this amounts to \n",
406 | "$$\n",
407 | " \\frac{\\text{D}}{\\text{D} t} (\\rho u) = (\\rho u)_t + (\\rho u^2)_x.\n",
408 | "$$"
409 | ]
410 | },
411 | {
412 | "cell_type": "markdown",
413 | "metadata": {
414 | "slideshow": {
415 | "slide_type": "subslide"
416 | }
417 | },
418 | "source": [
419 | "Unfortunately we are not quite done. We also know that a fluid has a pressure associated with it whose gradient can be thought of as acting as a force. Since this term is of the form $p_x$ we can combine this and write the momentum conservation as\n",
420 | "$$\n",
421 | " (\\rho u)_t + (\\rho u^2 + p)_x.\n",
422 | "$$"
423 | ]
424 | },
425 | {
426 | "cell_type": "markdown",
427 | "metadata": {
428 | "slideshow": {
429 | "slide_type": "subslide"
430 | }
431 | },
432 | "source": [
433 | "We have two equations but three unknowns now. Usually to close the system something must be assumed by the relationship between pressure and the other two quantities. Sometimes we must also add an energy conservation equation often written as\n",
434 | "$$\n",
435 | " E_t + (Eu + p)_x = 0\n",
436 | "$$"
437 | ]
438 | },
439 | {
440 | "cell_type": "markdown",
441 | "metadata": {
442 | "slideshow": {
443 | "slide_type": "subslide"
444 | }
445 | },
446 | "source": [
447 | "Note that this system will often have outside influences on it so strictly speaking this may not be conservative. That being said we may want to still make sure our system is conservative except for these outside sources."
448 | ]
449 | },
450 | {
451 | "cell_type": "markdown",
452 | "metadata": {
453 | "slideshow": {
454 | "slide_type": "subslide"
455 | }
456 | },
457 | "source": [
458 | "### Linear Acoustics\n",
459 | "\n",
460 | "One nice example of how to go about dealing with hyperbolic systems of PDEs is the derivation of linear acoustics and therefore sound waves. Here we will **linearize** the equations around some background state and remove higher-order terms as we go."
461 | ]
462 | },
463 | {
464 | "cell_type": "markdown",
465 | "metadata": {
466 | "slideshow": {
467 | "slide_type": "subslide"
468 | }
469 | },
470 | "source": [
471 | "#### Derivation of Linear Acoustics\n",
472 | "\n",
473 | "The general approach will be to assume that $q$ can be written as\n",
474 | "$$\n",
475 | " q(x, t) = q_0 + \\widetilde{q}(x, t)\n",
476 | "$$\n",
477 | "where $q_0$ is some large constant representing the background state and $\\widetilde{q}$ some small perturbation to that state that can be space and time dependent."
478 | ]
479 | },
480 | {
481 | "cell_type": "markdown",
482 | "metadata": {
483 | "slideshow": {
484 | "slide_type": "subslide"
485 | }
486 | },
487 | "source": [
488 | "Plugging $q_0 + \\widetilde{q}(x, t)$ in for $q$ in the original conservation law will give us\n",
489 | "$$\\begin{aligned}\n",
490 | " &(q_0 + \\widetilde{q})_t + f(q_0 + \\widetilde{q}(x, t))_x = 0 \\\\\n",
491 | " &\\widetilde{q}_t + f'(q_0) \\widetilde{q}_x = 0.\n",
492 | "\\end{aligned}$$"
493 | ]
494 | },
495 | {
496 | "cell_type": "markdown",
497 | "metadata": {
498 | "slideshow": {
499 | "slide_type": "subslide"
500 | }
501 | },
502 | "source": [
503 | "Now turning to our derivation we start with the fluid conservation laws we derived before\n",
504 | "$$\\begin{aligned}\n",
505 | " &\\rho_t + (\\rho u)_x = 0 \\\\\n",
506 | " &(\\rho u)_t + (\\rho u^2 + p)_x = 0.\n",
507 | "\\end{aligned}$$\n",
508 | "Here the flux function can be written as\n",
509 | "$$\n",
510 | " f(q) = \\begin{bmatrix} \\rho u \\\\ \\rho u^2 + p \\end{bmatrix}\n",
511 | "$$\n",
512 | "See if you can compute the flux Jacobian $f'(q)$ from the flux function above."
513 | ]
514 | },
515 | {
516 | "cell_type": "markdown",
517 | "metadata": {
518 | "slideshow": {
519 | "slide_type": "subslide"
520 | }
521 | },
522 | "source": [
523 | "Solution:\n",
524 | "\n",
525 | "1. Write $f(q)$ in terms of $q$:\n",
526 | "$$\\begin{aligned}\n",
527 | " f(q) &= \\begin{bmatrix} \\rho u \\\\ \\rho u^2 + p \\end{bmatrix}\\\\\n",
528 | " &=\\begin{bmatrix} q^2 \\\\ \\frac{(q^2)^2}{q^1} + p(q^1) \\end{bmatrix}\n",
529 | "\\end{aligned}$$\n",
530 | "1. Compute the Jacobian:\n",
531 | "$$\\begin{aligned}\n",
532 | " f'(q) &= \\begin{bmatrix} \\partial f^1 / \\partial q^1 & \\partial f^1 / \\partial q^2 \\\\ \\partial f^2 / \\partial q^1 & \\partial f^2 / \\partial q^2 \\end{bmatrix}\\\\\n",
533 | " &= \\begin{bmatrix} 0 & 1 \\\\ -(q^2)^2 / (q^1)^2 + p'(q^1) & 2 q^2 / q^1 \\end{bmatrix}\\\\\n",
534 | " &= \\begin{bmatrix} 0 & 1 \\\\ -u^2 + p'(\\rho) & 2 u \\end{bmatrix}\n",
535 | "\\end{aligned}$$"
536 | ]
537 | },
538 | {
539 | "cell_type": "markdown",
540 | "metadata": {
541 | "slideshow": {
542 | "slide_type": "subslide"
543 | }
544 | },
545 | "source": [
546 | "From our linearization $\\widetilde{q}_t + f'(q_0) \\widetilde{q}_x = 0$ we then have\n",
547 | "\n",
548 | "$$\\begin{aligned}\n",
549 | " &\\widetilde{\\rho}_t + \\widetilde{\\rho u}_x = 0 \\\\\n",
550 | " &\\widetilde{\\rho u}_t + (-u_0^2 + p'(\\rho_0)) \\widetilde{\\rho}_x + (2 u_0) \\widetilde{\\rho u}_x = 0 \\\\\n",
551 | "\\end{aligned}$$"
552 | ]
553 | },
554 | {
555 | "cell_type": "markdown",
556 | "metadata": {
557 | "slideshow": {
558 | "slide_type": "subslide"
559 | }
560 | },
561 | "source": [
562 | "Well this does not really look like the system we mentioned before. This is because we are using the conservation quantities rather than more easily measured quantities. If we switch to pressure and velocity as we had before we can write the perturbation series as\n",
563 | "$$\n",
564 | " p(\\rho) = p(\\rho_0 + \\widetilde{\\rho}) = p(\\rho_0) + p'(\\rho_0) \\widetilde{\\rho} + \\cdots.\n",
565 | "$$\n",
566 | "Knowing that $p(\\rho_0) = p_0$ we then know that $\\widetilde{p} = p'(\\rho_0) \\widetilde{\\rho}$."
567 | ]
568 | },
569 | {
570 | "cell_type": "markdown",
571 | "metadata": {
572 | "slideshow": {
573 | "slide_type": "subslide"
574 | }
575 | },
576 | "source": [
577 | "Similarly we have\n",
578 | "$$\n",
579 | " \\rho u = (\\rho_0 + \\widetilde{\\rho})(u_0 + \\widetilde{u}) = \\rho_0 u_0 + \\widetilde{\\rho} u_0 + \\rho_0 \\widetilde{u}\n",
580 | "$$\n",
581 | "such that\n",
582 | "$$\n",
583 | " \\widetilde{\\rho u} = u_0 \\widetilde{\\rho} + \\rho_0 \\widetilde{u}.\n",
584 | "$$\n"
585 | ]
586 | },
587 | {
588 | "cell_type": "markdown",
589 | "metadata": {
590 | "slideshow": {
591 | "slide_type": "subslide"
592 | }
593 | },
594 | "source": [
595 | "Plugging these expression in leads then to the system we had before\n",
596 | "$$\\begin{aligned}\n",
597 | " &\\widetilde{p}_t + u_0 \\widetilde{p}_x + K_0 \\widetilde{u}_x = 0\\\\\n",
598 | " &\\widetilde{u}_t + \\frac{1}{\\rho_0} \\widetilde{p}_x + u_0 \\widetilde{u} = 0\n",
599 | "\\end{aligned}$$\n",
600 | "Here we have not assumed that $u_0 = 0$, which is the only difference between our systems."
601 | ]
602 | },
603 | {
604 | "cell_type": "markdown",
605 | "metadata": {
606 | "slideshow": {
607 | "slide_type": "subslide"
608 | }
609 | },
610 | "source": [
611 | "#### Sounds Waves - Solution to Linear Acoustics\n",
612 | "\n",
613 | "The solution to a linear scalar hyperbolic PDE has the general form\n",
614 | "$$\n",
615 | " q(x,t) = q_0(x - u t)\n",
616 | "$$\n",
617 | "where the original PDE has the form $q_t + u q_x = 0$ and the initial condition is $q_0(x)$. This suggests a similar form for systems such that we are looking for solutions of the form\n",
618 | "$$\n",
619 | " q(x,t) = \\widetilde{q}(x - st).\n",
620 | "$$\n",
621 | "where now it is not quite clear what $\\widetilde{q}$ or $s$ is."
622 | ]
623 | },
624 | {
625 | "cell_type": "markdown",
626 | "metadata": {
627 | "slideshow": {
628 | "slide_type": "subslide"
629 | }
630 | },
631 | "source": [
632 | "Starting with this ansatz and plugging it into the equation $q_t + A q_x = 0$ we have\n",
633 | "$$\\begin{aligned}\n",
634 | " q_t &= -s \\widetilde{q}'(x - st) \\\\\n",
635 | " q_x &= \\widetilde{q}'(x - st)\n",
636 | "\\end{aligned}$$\n",
637 | "so that we have\n",
638 | "$$\\begin{aligned}\n",
639 | " &-s \\widetilde{q}'(x - st) + A \\widetilde{q}'(x - st) = 0 \\\\\n",
640 | " &A \\widetilde{q}'(x - st) = s \\widetilde{q}'(x - st)\n",
641 | "\\end{aligned}$$\n",
642 | "Note that we now see the structure of an eigenproblem."
643 | ]
644 | },
645 | {
646 | "cell_type": "markdown",
647 | "metadata": {
648 | "slideshow": {
649 | "slide_type": "subslide"
650 | }
651 | },
652 | "source": [
653 | "Looking at the eigenvalues for the matrix $A$ we have\n",
654 | "$$\n",
655 | " \\lambda = u \\pm c_0\n",
656 | "$$\n",
657 | "where $c_0$ is our speed of sound before $\\sqrt{K_0 / \\rho_0}$. Note that here we have retained the background speed for completeness but this can be removed to see the same thing. Also note that $c_0 = \\sqrt{p'(\\rho_0)}$ and matches with the theory of acoustics."
658 | ]
659 | },
660 | {
661 | "cell_type": "markdown",
662 | "metadata": {
663 | "slideshow": {
664 | "slide_type": "subslide"
665 | }
666 | },
667 | "source": [
668 | "For the eigenvectors of $A$ we have\n",
669 | "$$\n",
670 | " R = \\begin{bmatrix} -\\rho_0 c_0 & \\rho_0 c_0 \\\\ 1 & 1 \\end{bmatrix}\n",
671 | "$$\n",
672 | "These will correspond to the $q'(x-st)$ term in our equation. This implies that for the left going wave corresponding to $\\lambda^1 = u_0 - c_0$ then looks like\n",
673 | "$$\n",
674 | " q(x, t) = w^1(x - \\lambda^1 t) r^1\n",
675 | "$$\n",
676 | "and right going as\n",
677 | "$$\n",
678 | " q(x, t) = w^2(x - \\lambda^2 t) r^2\n",
679 | "$$\n",
680 | "and the full superposition of waves as\n",
681 | "$$\n",
682 | " q(x, t) = w^1(x - \\lambda^1 t) r^1 + w^2(x - \\lambda^2 t) r^2\n",
683 | "$$\n",
684 | "Note we still do not know what $w^{1,2}$ are although they are related to the initial condition."
685 | ]
686 | },
687 | {
688 | "cell_type": "markdown",
689 | "metadata": {
690 | "slideshow": {
691 | "slide_type": "subslide"
692 | }
693 | },
694 | "source": [
695 | "One way to find the values of the functions $w^{1,2}$ is to evaluate the expression above at $t=0$ to get\n",
696 | "$$\n",
697 | " w^1(x) r^1 + w^2(x) r^2 = q(x, 0).\n",
698 | "$$\n",
699 | "This equation is equivalent to the linear system\n",
700 | "$$\n",
701 | " R w(x) = q(x, 0).\n",
702 | "$$"
703 | ]
704 | },
705 | {
706 | "cell_type": "markdown",
707 | "metadata": {
708 | "slideshow": {
709 | "slide_type": "subslide"
710 | }
711 | },
712 | "source": [
713 | "Introducing a new variable, $Z_0 \\equiv \\rho_0 c_0$, called the **impedance**, allows us to write the inverse of $R$ as\n",
714 | "$$\n",
715 | " R^{-1} = \\frac{1}{2 Z_0} \\begin{bmatrix}\n",
716 | " -1 & Z_0 \\\\ 1 & Z_0\n",
717 | " \\end{bmatrix}\n",
718 | "$$\n",
719 | "and therefore\n",
720 | "$$\n",
721 | " \\begin{aligned}\n",
722 | " &w^1(x) = \\frac{1}{2 Z_0} (-p(x, 0) + Z_0 u(x, 0)) \\\\\n",
723 | " &w^2(x) = \\frac{1}{2 Z_0} (p(x, 0) + Z_0 u(x, 0)).\n",
724 | " \\end{aligned}\n",
725 | "$$"
726 | ]
727 | },
728 | {
729 | "cell_type": "markdown",
730 | "metadata": {
731 | "slideshow": {
732 | "slide_type": "subslide"
733 | }
734 | },
735 | "source": [
736 | "### Back to Hyperbolicity and Solving Linear Systems Generally\n",
737 | "\n",
738 | "Let us now tie back to our general definition of a hyperbolic linear system of PDEs. Recall that we wanted the matrix $A$ in $q_t + A q_x = 0$ to be diagonalizable with real eigenvalues. Let those eigenvalues be\n",
739 | "$$\n",
740 | " \\lambda^1 \\leq \\lambda^2 \\leq \\cdots \\leq \\lambda^m\n",
741 | "$$\n",
742 | "with corresponding eigenvectors $r^1, r^2, \\ldots, r^m$. Note that for the matrix $A$ to be diagonalizable we need to have a unique eigenvector for every repeated eigenvalue. We also know that the eigenvector matrix $R$ is nonsingular and therefore we can diagonalize the matrix $A$ by a similarity transformation\n",
743 | "$$\n",
744 | " R^{-1} A R = \\Lambda \\text{ or } A = R \\Lambda R^{-1}\n",
745 | "$$\n",
746 | "where $\\Lambda is the matrix with the eigenvalues down its diagonal."
747 | ]
748 | },
749 | {
750 | "cell_type": "markdown",
751 | "metadata": {
752 | "slideshow": {
753 | "slide_type": "subslide"
754 | }
755 | },
756 | "source": [
757 | "Using this transformation let us now turn back to solving a general system. Consider the following set of operations:\n",
758 | "$$\\begin{aligned}\n",
759 | " q_t + A q_x &= 0 && \\text{Original} \\\\\n",
760 | " R^{-1} q_t + R^{-1} A q_x &= 0 && \\text{Multiply by } R^{-1} \\\\\n",
761 | " R^{-1} q_t + R^{-1} R \\Lambda R^{-1} q_x &= 0 && \\text{Replace } A \\\\\n",
762 | " w_t + R^{-1} R \\Lambda w_x &= 0 && \\text{Let } w = R^{-1} q \\\\\n",
763 | " w_t + \\Lambda w_x &= 0 && \\text{Simplify}\n",
764 | "\\end{aligned}$$\n",
765 | "Note this last step now is a decoupled set of hyperbolic equations with\n",
766 | "$$\n",
767 | " w^p_t + \\lambda^p w^p_x = 0 \\text{ for } p=1,2,\\ldots,m.\n",
768 | "$$"
769 | ]
770 | }
771 | ],
772 | "metadata": {
773 | "kernelspec": {
774 | "display_name": "Python 3",
775 | "language": "python",
776 | "name": "python3"
777 | },
778 | "language_info": {
779 | "codemirror_mode": {
780 | "name": "ipython",
781 | "version": 3
782 | },
783 | "file_extension": ".py",
784 | "mimetype": "text/x-python",
785 | "name": "python",
786 | "nbconvert_exporter": "python",
787 | "pygments_lexer": "ipython3",
788 | "version": "3.9.8"
789 | }
790 | },
791 | "nbformat": 4,
792 | "nbformat_minor": 2
793 | }
794 |
--------------------------------------------------------------------------------
/01_linear_hyperbolic.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "skip"
8 | }
9 | },
10 | "source": [
11 | "\n",
12 | " \n",
13 | " | Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli | \n",
14 | "
"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "slideshow": {
22 | "slide_type": "skip"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "from __future__ import print_function\n",
28 | "\n",
29 | "%matplotlib inline\n",
30 | "import numpy\n",
31 | "import matplotlib.pyplot as plt"
32 | ]
33 | },
34 | {
35 | "cell_type": "markdown",
36 | "metadata": {
37 | "slideshow": {
38 | "slide_type": "slide"
39 | }
40 | },
41 | "source": [
42 | "# Linear Hyperbolic PDEs\n",
43 | "\n",
44 | "We saw from the intro that a general linear hyperbolic system of the form\n",
45 | "$$\n",
46 | " q_t + A q_x = 0\n",
47 | "$$\n",
48 | "can be transformed into a set of independent PDEs as $A$ is diagonalizable and with the new variables $w = R^{-1} q$ we can write\n",
49 | "$$\n",
50 | " w^p_t + \\lambda^p w^p_x = 0 \\text{ for } p = 1, 2, \\ldots , m.\n",
51 | "$$\n",
52 | "Our goal in this section will be to formalize some of this and introduce notation that will be helpful later on."
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "metadata": {
58 | "slideshow": {
59 | "slide_type": "subslide"
60 | }
61 | },
62 | "source": [
63 | "## Cauchy Problem\n",
64 | "\n",
65 | "Consider the PDE problem with the linear hyperbolic system above and let\n",
66 | "$$\n",
67 | " q(x, 0) = q_0(x) \\text{ for } -\\infty < x < \\infty.\n",
68 | "$$\n",
69 | "We can project this initial data onto the eigenspace by solving\n",
70 | "$$\n",
71 | " R w_0(x) = q_0(x)\n",
72 | "$$\n",
73 | "whose solution is\n",
74 | "$$\n",
75 | " w_0(x) = R^{-1} q_0(x).\n",
76 | "$$\n",
77 | "The solution then is\n",
78 | "$$\n",
79 | " w^p(x, t) = w^p(x - \\lambda^p t, 0) = w_0(x - \\lambda^p t)\n",
80 | "$$\n",
81 | "and can be written in terms of the original variables as\n",
82 | "$$\n",
83 | " q(x, t) = R w(x, t).\n",
84 | "$$"
85 | ]
86 | },
87 | {
88 | "cell_type": "markdown",
89 | "metadata": {
90 | "slideshow": {
91 | "slide_type": "subslide"
92 | }
93 | },
94 | "source": [
95 | "Note that we can also write this as\n",
96 | "$$\n",
97 | " q(x, t) = \\sum^m_{p=1} w^p(x, t) r^p.\n",
98 | "$$\n",
99 | "This last expression can be interpreted as a set of waves moving at $\\lambda^p$ whose linear superposition provides the solution. Because of this sometimes $w^p$ are known as the **characteristic variables** and the solution along $X(t) = x_0 + \\lambda^p t$, which are called **characteristics of the pth family** or **p-characteristics**."
100 | ]
101 | },
102 | {
103 | "cell_type": "markdown",
104 | "metadata": {
105 | "slideshow": {
106 | "slide_type": "subslide"
107 | }
108 | },
109 | "source": [
110 | "### Left Eigenvectors\n",
111 | "\n",
112 | "One simplification we can make is to introduce the left eigenvectors defined by $L = R^{-1}$ comprised by the row vectors $\\ell^1, \\ell^2, \\ldots, \\ell^m$. These satisfy the eigenproblem\n",
113 | "$$\n",
114 | " \\ell^p A = \\lambda^p \\ell^p.\n",
115 | "$$\n",
116 | "This allows us to write the characteristic variables as\n",
117 | "$$\n",
118 | " w^p(x,t) = \\ell^p q(x, t)\n",
119 | "$$\n",
120 | "and therefore\n",
121 | "$$\n",
122 | " q(x, t) = \\sum^m_{p=1} [\\ell^p q_0(x - \\lambda^p t) ]r^p.\n",
123 | "$$"
124 | ]
125 | },
126 | {
127 | "cell_type": "markdown",
128 | "metadata": {
129 | "slideshow": {
130 | "slide_type": "subslide"
131 | }
132 | },
133 | "source": [
134 | "#### Example: Acoustics\n",
135 | "\n",
136 | "$$\\begin{aligned}\n",
137 | " q(x, t) &= \\begin{bmatrix} p(x, t) \\\\ u(x, t) \\end{bmatrix} = \\sum^2_{p=1} [\\ell^p q_0(x - \\lambda^p t) ] r^p \\\\\n",
138 | " &= \\frac{1}{2 Z_0} \\left \\{ \\begin{bmatrix} -1 & Z_0 \\end{bmatrix} \\begin{bmatrix} p(x, 0) \\\\ u(x, 0) \\end{bmatrix} \\begin{bmatrix} -Z_0 \\\\ 1 \\end{bmatrix} + \\begin{bmatrix} 1 & Z_0 \\end{bmatrix} \\begin{bmatrix} p(x, 0) \\\\ u(x, 0) \\end{bmatrix} \\begin{bmatrix} Z_0 \\\\ 1 \\end{bmatrix} \\right \\}\n",
139 | "\\end{aligned}$$"
140 | ]
141 | },
142 | {
143 | "cell_type": "markdown",
144 | "metadata": {
145 | "slideshow": {
146 | "slide_type": "slide"
147 | }
148 | },
149 | "source": [
150 | "## Domain of Dependence and Range of Influence\n",
151 | "\n",
152 | "Say we wanted to find the solution $q$ at some fixed point in space and time $(X, T)$. We know that the solution must depend on the initial condition only for a Cauchy problem and that for a linear problem the solution will follow the characteristics of the problem. We therefore know that $q(X, T)$ will depend on a particular point $X - \\lambda^P T$ for $p=1,2,\\ldots,m$."
153 | ]
154 | },
155 | {
156 | "cell_type": "markdown",
157 | "metadata": {
158 | "slideshow": {
159 | "slide_type": "subslide"
160 | }
161 | },
162 | "source": [
163 | "If we collect all these points in a set called the **domain of dependence** it can be defined as\n",
164 | "$$\n",
165 | " \\mathcal{D}(X, T) = \\{ X - \\lambda^p T: p = 1,2,\\ldots,m \\}.\n",
166 | "$$\n",
167 | "This set is always bounded for hyperbolic PDEs.\n",
168 | "\n",
169 | "Try to draw an example of this domain of dependence based on $m = 3$."
170 | ]
171 | },
172 | {
173 | "cell_type": "markdown",
174 | "metadata": {},
175 | "source": [
176 | "In contrast $\\mathcal{D}(X, T)$ may be unbounded for parabolic equations such as the heat equation where $\\mathcal{D}(X,T) = \\mathbb R$."
177 | ]
178 | },
179 | {
180 | "cell_type": "markdown",
181 | "metadata": {
182 | "slideshow": {
183 | "slide_type": "subslide"
184 | }
185 | },
186 | "source": [
187 | "Unsurprisingly perhaps $\\mathcal{D}$ directly related to the CFL stability condition. The most generic version of this stability condition states the following:\n",
188 | "\n",
189 | "> The true domain of dependence must be contained in the numerical domain of dependence.\n",
190 | "\n",
191 | "In our case we know the true domain of dependence but have not yet mentioned the numerical domain of dependence (we will come to that later)."
192 | ]
193 | },
194 | {
195 | "cell_type": "markdown",
196 | "metadata": {
197 | "slideshow": {
198 | "slide_type": "subslide"
199 | }
200 | },
201 | "source": [
202 | "We can also turn the domain of dependence around and ask what the range of influence of particular point $x_0$ might have sometime in the future. This is often called the **range of influence**. \n",
203 | "\n",
204 | "Try to draw an example of this influence for the same case as before."
205 | ]
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "metadata": {
210 | "slideshow": {
211 | "slide_type": "subslide"
212 | }
213 | },
214 | "source": [
215 | "## Riemann Problem for a Linear System\n",
216 | "\n",
217 | "As they will become essential to our numerical methods later we will define another specialized Cauchy problem called the **Riemann problem**. It is defined as a Cauchy problem with the addition of an initial condition that is a jump at $x=0$:\n",
218 | "$$\n",
219 | " q(x, 0) = \\left \\{ \\begin{aligned} \n",
220 | " q_\\ell \\quad \\text{if } x < 0 \\\\\n",
221 | " q_r \\quad \\text{if } x > 0\n",
222 | " \\end{aligned} \\right .\n",
223 | "$$\n",
224 | "The solution of the Riemann problem in the case of linear hyperbolic PDEs will therefore be a set of discontinuities moving away from $x=0$ at the characteristic speeds."
225 | ]
226 | },
227 | {
228 | "cell_type": "markdown",
229 | "metadata": {
230 | "slideshow": {
231 | "slide_type": "subslide"
232 | }
233 | },
234 | "source": [
235 | "Let us consider first the a scalar, linear hyperbolic problem defined by\n",
236 | "$$\n",
237 | " q_t + u q_x = 0.\n",
238 | "$$\n",
239 | "Here a single discontinuity will travel at a speed $u$ away from the origin."
240 | ]
241 | },
242 | {
243 | "cell_type": "markdown",
244 | "metadata": {
245 | "slideshow": {
246 | "slide_type": "subslide"
247 | }
248 | },
249 | "source": [
250 | "For the more general system of $m$ equations we know what happens in general but let us now consider it in the context of the Riemann problem. We will first simplify the notation a bit such that\n",
251 | "$$\n",
252 | " q_\\ell = \\sum^m_{p=1} w^p_\\ell r^p \\text{ and } q_r = \\sum^m_{p=1} w^p_r r^p,\n",
253 | "$$\n",
254 | "which simply expresses the initial condition in terms of the characteristic variables."
255 | ]
256 | },
257 | {
258 | "cell_type": "markdown",
259 | "metadata": {
260 | "slideshow": {
261 | "slide_type": "subslide"
262 | }
263 | },
264 | "source": [
265 | "Another way to write this is as the individual $p$th fields as\n",
266 | "$$\n",
267 | " w^p(x, 0) = \\left \\{ \\begin{aligned} \n",
268 | " w^p_\\ell \\quad \\text{if } x < 0 \\\\\n",
269 | " w^p_r \\quad \\text{if } x > 0\n",
270 | " \\end{aligned} \\right .\n",
271 | "$$\n",
272 | "leading to the solution\n",
273 | "$$\n",
274 | " w^p(x, t) = \\left \\{ \\begin{aligned} \n",
275 | " w^p_\\ell \\quad \\text{if } x - \\lambda^p t < 0 \\\\\n",
276 | " w^p_r \\quad \\text{if } x - \\lambda^p t > 0\n",
277 | " \\end{aligned} \\right .\n",
278 | "$$"
279 | ]
280 | },
281 | {
282 | "cell_type": "markdown",
283 | "metadata": {
284 | "slideshow": {
285 | "slide_type": "subslide"
286 | }
287 | },
288 | "source": [
289 | "Based off of this you can then write the full solution as\n",
290 | "$$\n",
291 | " q(x,t ) = \\sum_{p: \\lambda^p < x/t} w^p_r r^p + \\sum_{p: \\lambda^p > x / t} w^p_\\ell r^p.\n",
292 | "$$\n",
293 | "\n",
294 | "With this in hand try and figure out in our diagram from before, picking an $(X, T)$ and what the explicit solution is. Also combine these with the previous drawings for the domain of dependence you drew and the range of influence."
295 | ]
296 | },
297 | {
298 | "cell_type": "markdown",
299 | "metadata": {
300 | "slideshow": {
301 | "slide_type": "subslide"
302 | }
303 | },
304 | "source": [
305 | "Another useful thing to think about at this juncture is that the solution remains constant in a set of wedges with jumps between them defined by\n",
306 | "$$\n",
307 | " (w^p_r - w^p_\\ell) r^p \\equiv \\alpha^p r^p\n",
308 | "$$\n",
309 | "across the $p$th characteristic. This implies then that the jump is proportional to the eigenvectors of the system. This condition is called the **Rankine-Hugoniot jump condition**. In this case we have written in the case of linear hyperbolic PDEs and we will see an analogous version for nonlinear hyperbolic PDEs."
310 | ]
311 | },
312 | {
313 | "cell_type": "markdown",
314 | "metadata": {
315 | "slideshow": {
316 | "slide_type": "subslide"
317 | }
318 | },
319 | "source": [
320 | "We can also write this condition in terms of the original initial data $q_\\ell$ and $q_r$ such that\n",
321 | "$$\n",
322 | " q_r - q_\\ell = \\alpha^1 r^1 + \\cdots + \\alpha^m r^m\n",
323 | "$$\n",
324 | "or in terms of the solution of a linear system\n",
325 | "$$\n",
326 | " R \\alpha = q_r - q_\\ell.\n",
327 | "$$\n",
328 | "In other words we are projecting the jump in $q$ onto the eigenspace."
329 | ]
330 | },
331 | {
332 | "cell_type": "markdown",
333 | "metadata": {
334 | "slideshow": {
335 | "slide_type": "subslide"
336 | }
337 | },
338 | "source": [
339 | "We now introduce a notation that we will reuse extensively in this course. Define\n",
340 | "$$\n",
341 | " \\mathcal{W}^p \\equiv \\alpha^p r^p\n",
342 | "$$\n",
343 | "as the **$\\mathbf{p}$th waves**. This allows us to rewrite the solution as\n",
344 | "$$\\begin{aligned}\n",
345 | " q(x,t) &= q_\\ell + \\sum_{p: \\lambda^p < x/t} \\mathcal{W}^p \\\\\n",
346 | " &= q_r - \\sum_{p: \\lambda^p > x / t} \\mathcal{W}^p\n",
347 | "\\end{aligned}$$\n",
348 | "This can also be written in terms of the Heaviside function as\n",
349 | "$$\n",
350 | " q(x,t) = q_\\ell + \\sum^m_{p=1} H(x- \\lambda^p t) \\mathcal{W}^p\n",
351 | "$$"
352 | ]
353 | },
354 | {
355 | "cell_type": "markdown",
356 | "metadata": {
357 | "slideshow": {
358 | "slide_type": "slide"
359 | }
360 | },
361 | "source": [
362 | "## Phase Plane for a System\n",
363 | "\n",
364 | "The **phase plane** solution for a system is often very useful as an analysis tool. In particular the splitting of $q_r - q_\\ell$ is useful as viewed from the phase plane."
365 | ]
366 | },
367 | {
368 | "cell_type": "markdown",
369 | "metadata": {
370 | "slideshow": {
371 | "slide_type": "subslide"
372 | }
373 | },
374 | "source": [
375 | "For $m=2$ the phase plane is simply the solutions $q^1$ vs. $q^2$ and are manifolds on that plane. For Riemann problems there is a particularly nice relationship as we know that the solution must be a scalar multiple of the eigenvectors. This means that the states $q_r$ and $q_\\ell$ must be connected by two sets of eigenvectors. In the $m=2$ case there is also a middle state, $q_m$ that must have be one of the two intersections between the eigenvectors intersecting at $q_\\ell$ and $q_r$.\n",
376 | "\n",
377 | "Let us attempt to draw an actual picture of how this works."
378 | ]
379 | },
380 | {
381 | "cell_type": "markdown",
382 | "metadata": {
383 | "slideshow": {
384 | "slide_type": "subslide"
385 | }
386 | },
387 | "source": [
388 | "Note that there are two possible states $q_m$. The correct one is chosen based on which $\\lambda^p$ is faster. We will see a more general way to pick which middle state is correct later, also known as **entropy conditions**."
389 | ]
390 | },
391 | {
392 | "cell_type": "markdown",
393 | "metadata": {
394 | "slideshow": {
395 | "slide_type": "subslide"
396 | }
397 | },
398 | "source": [
399 | "#### Example: Acoustics\n",
400 | "\n",
401 | "Let us now turn to our usual example, the acoustics equations defined here as\n",
402 | "$$\n",
403 | " \\begin{bmatrix}\n",
404 | " p \\\\ u\n",
405 | " \\end{bmatrix}_t = \\begin{bmatrix}\n",
406 | " 0 & K_0 \\\\ 1 / \\rho_0 & 0\n",
407 | " \\end{bmatrix} \\begin{bmatrix}\n",
408 | " p \\\\ u\n",
409 | " \\end{bmatrix}_x = 0\n",
410 | "$$"
411 | ]
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "metadata": {
416 | "slideshow": {
417 | "slide_type": "subslide"
418 | }
419 | },
420 | "source": [
421 | "We know the eigensystem already and can solve the Riemann problem projection as $R \\alpha = q_r - q_\\ell$ or\n",
422 | "$$\\begin{aligned}\n",
423 | " \\alpha^1 &= \\ell^1 (q_r - q_\\ell) = \\frac{-(p_r - p_\\ell) + Z_0 (u_r - u_\\ell)}{2 Z_0} \\\\\n",
424 | " \\alpha^2 &= \\ell^2 (q_r - q_\\ell) = \\frac{(p_r - p_\\ell) + Z_0 (u_r - u_\\ell)}{2 Z_0}\n",
425 | "\\end{aligned}$$\n",
426 | "with waves $\\mathcal{W}^1 = \\alpha^1 r^1$ and $\\mathcal{W}^2 = \\alpha^2 r^2$.\n",
427 | "\n",
428 | "The intermediate state is therefore\n",
429 | "$$\n",
430 | " q_m = q_\\ell + \\alpha^1 r^1 = \\frac{1}{2} \\begin{bmatrix} (p_\\ell + p_r) - Z_0 (u_r - u_\\ell) \\\\ (u_\\ell + u_r) - (p_r - p_\\ell) / Z_0 \\end{bmatrix}.\n",
431 | "$$"
432 | ]
433 | },
434 | {
435 | "cell_type": "markdown",
436 | "metadata": {
437 | "slideshow": {
438 | "slide_type": "subslide"
439 | }
440 | },
441 | "source": [
442 | "As an exercise try to find the solutions of the Riemann problem with the initial condition\n",
443 | "$$\n",
444 | " p_r < p_\\ell \\quad \\text{and} \\quad u_\\ell = u_r = 0.\n",
445 | "$$"
446 | ]
447 | },
448 | {
449 | "cell_type": "markdown",
450 | "metadata": {
451 | "slideshow": {
452 | "slide_type": "subslide"
453 | }
454 | },
455 | "source": [
456 | "Solution:\n",
457 | "$$\\begin{aligned}\n",
458 | " \\alpha^1 &= \\frac{p_\\ell - p_r)}{2 Z_0} \\\\\n",
459 | " \\alpha^2 &= \\frac{p_r - p_\\ell}{2 Z_0}\n",
460 | "\\end{aligned}$$\n",
461 | "with the middle state\n",
462 | "$$\n",
463 | " q_m = \\frac{1}{2} \\begin{bmatrix} p_\\ell + p_r \\\\ (p_\\ell - p_r) / Z_0 \\end{bmatrix}.\n",
464 | "$$"
465 | ]
466 | }
467 | ],
468 | "metadata": {
469 | "kernelspec": {
470 | "display_name": "Python 3",
471 | "language": "python",
472 | "name": "python3"
473 | },
474 | "language_info": {
475 | "codemirror_mode": {
476 | "name": "ipython",
477 | "version": 3
478 | },
479 | "file_extension": ".py",
480 | "mimetype": "text/x-python",
481 | "name": "python",
482 | "nbconvert_exporter": "python",
483 | "pygments_lexer": "ipython3",
484 | "version": "3.9.8"
485 | }
486 | },
487 | "nbformat": 4,
488 | "nbformat_minor": 2
489 | }
490 |
--------------------------------------------------------------------------------
/02_finite_volume.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "skip"
8 | }
9 | },
10 | "source": [
11 | "\n",
12 | " \n",
13 | " | Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli | \n",
14 | "
"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "slideshow": {
22 | "slide_type": "skip"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "from __future__ import print_function\n",
28 | "\n",
29 | "%matplotlib inline\n",
30 | "import numpy\n",
31 | "import matplotlib.pyplot as plt"
32 | ]
33 | },
34 | {
35 | "cell_type": "markdown",
36 | "metadata": {
37 | "slideshow": {
38 | "slide_type": "slide"
39 | }
40 | },
41 | "source": [
42 | "# Finite Volume Methods"
43 | ]
44 | },
45 | {
46 | "cell_type": "markdown",
47 | "metadata": {
48 | "slideshow": {
49 | "slide_type": "slide"
50 | }
51 | },
52 | "source": [
53 | "## General Formulation of a Conservation Law\n",
54 | "\n",
55 | "Define the value\n",
56 | "$$\n",
57 | " Q^n_i \\approx \\frac{1}{\\Delta x} \\int^{x_{i+1/2}}_{x_{i-1/2}} q(x, t_n) dx \\equiv \\frac{1}{\\Delta x} \\int_{\\mathcal{C}_i} q(x, t_n) dx\n",
58 | "$$\n",
59 | "where the $i$th **grid cell** is denoted by\n",
60 | "$$\n",
61 | " \\mathcal{C}_i \\equiv (x_{i-1/2}, x_{i+1/2})\n",
62 | "$$\n",
63 | "and $\\Delta x = x_{i+1/2} - x_{i-1/2}$. \n",
64 | "\n",
65 | "If $q(x,t)$ is smooth then the average value \n",
66 | "$$\n",
67 | " Q^n_i = q(x_i, t_n) + \\mathcal{O}(\\Delta x^2)\n",
68 | "$$"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {
74 | "slideshow": {
75 | "slide_type": "subslide"
76 | }
77 | },
78 | "source": [
79 | "With this definition we now return to our version of the conservation law written over the cell $\\mathcal{C}_i$:\n",
80 | "$$\n",
81 | " \\frac{\\text{d}}{\\text{d} t} \\int_{\\mathcal{C}_i} q(x,t) dx = f(q(x_{i-1/2}, t)) - f(q(x_{i+1/2}, t)).\n",
82 | "$$\n",
83 | "Now take the following steps:\n",
84 | "$$\\begin{aligned}\n",
85 | " \\frac{\\text{d}}{\\text{d} t} \\int_{\\mathcal{C}_i} q(x,t) dx &= f(q(x_{i-1/2}, t)) - f(q(x_{i+1/2}, t)) & & \\text{Original}\\\\\n",
86 | " \\int_{\\mathcal{C}_i} q(x,t_{n+1}) dx - \\int_{\\mathcal{C}_i} q(x,t_{n}) dx &= \\int^{t_{n+1}}_{t_n} \\left[ f(q(x_{i-1/2}, t)) - f(q(x_{i+1/2}, t)) \\right ] dt & & \\text{Integrate over } [t_n, t_{n+1}] \\\\\n",
87 | " \\frac{1}{\\Delta x} \\int_{\\mathcal{C}_i} q(x,t_{n+1}) dx &= \\frac{1}{\\Delta x} \\int_{\\mathcal{C}_i} q(x,t_{n}) dx + \\frac{1}{\\Delta x} \\int^{t_{n+1}}_{t_n} \\left[ f(q(x_{i-1/2}, t)) - f(q(x_{i+1/2}, t)) \\right ] dt & & \\text{Rearrange and divide by } \\Delta x \\\\\n",
88 | " Q^{n+1}_i &= Q^n_i + \\frac{1}{\\Delta x} \\int^{t_{n+1}}_{t_n} \\left[ f(q(x_{i-1/2}, t)) - f(q(x_{i+1/2}, t)) \\right ] dt & & \\text{Approximate with averages } Q^{n+1,n}_i \\\\\n",
89 | " Q^{n+1}_i &= Q^n_i - \\frac{\\Delta t}{\\Delta x} (F^n_{i+1/2} - F^n_{i-1/2}) & & \\text{Replace with }F_{i\\pm1/2} \\\\\n",
90 | "\\end{aligned}$$\n",
91 | "where\n",
92 | "$$\n",
93 | " F^n_{i\\pm 1/2} \\approx \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} f(q(x_{i\\pm 1/2}, t)) dt.\n",
94 | "$$"
95 | ]
96 | },
97 | {
98 | "cell_type": "markdown",
99 | "metadata": {
100 | "slideshow": {
101 | "slide_type": "subslide"
102 | }
103 | },
104 | "source": [
105 | "This approximate flux should have a formula akin to\n",
106 | "$$\n",
107 | " F^n_{i-1/2} = \\mathcal{F}(Q^n_{i-1}, Q^n_i)\n",
108 | "$$\n",
109 | "where here we are thinking of $\\mathcal{F}$ as a numerical flux function. The question then turns to how to prescribe a **numerical flux function**. Note that this implies that the update to $Q^{n+1}_i$ depends on three previous values, $Q^n_{i-1}, Q^n_{i}, Q^n_{i+1}$."
110 | ]
111 | },
112 | {
113 | "cell_type": "markdown",
114 | "metadata": {
115 | "slideshow": {
116 | "slide_type": "subslide"
117 | }
118 | },
119 | "source": [
120 | "We can also now discuss how conservation should be described numerically. If\n",
121 | "$$\n",
122 | " \\Delta x \\sum^J_{i=I} Q^{n+1}_i = \\Delta x \\sum^J_{i=I} Q^n_i - \\frac{\\Delta t}{\\Delta x} (F^n_{J+1/2} - F^n_{I-1/2})\n",
123 | "$$\n",
124 | "and the sum of the fluxes cancels then **global conservation** is maintained up to the boundaries of the domain."
125 | ]
126 | },
127 | {
128 | "cell_type": "markdown",
129 | "metadata": {
130 | "slideshow": {
131 | "slide_type": "subslide"
132 | }
133 | },
134 | "source": [
135 | "We can also rewrite the numerical methods as\n",
136 | "$$\n",
137 | " \\frac{Q^{n+1}_i - Q^n_i}{\\Delta t} + \\frac{F^n_{i+1/2} - F^n_{i-1/2}}{\\Delta x} = 0\n",
138 | "$$\n",
139 | "which implies that we have formulated a first order method in terms of finite difference methods. We will find that this is not entirely the case depending on what is prescribed for $F_{i\\pm 1/2}$."
140 | ]
141 | },
142 | {
143 | "cell_type": "markdown",
144 | "metadata": {
145 | "slideshow": {
146 | "slide_type": "subslide"
147 | }
148 | },
149 | "source": [
150 | "## Numerical Flux for the Diffusion Equation\n",
151 | "\n",
152 | "An interesting exercise at this point is to consider a more general method to the above approach. Consider again the parabolic heat equation. We can define a flux function that contains a derivative of $q$ such that\n",
153 | "$$\n",
154 | " f(q_x, x) = -\\beta(x) q_x.\n",
155 | "$$\n",
156 | "Clearly this gives us the heat equation if we substitute this flux function into our general equations\n",
157 | "$$\n",
158 | " q_t + f(q_x, x)_x = q_t - (\\beta(x) q_x)_x = 0.\n",
159 | "$$"
160 | ]
161 | },
162 | {
163 | "cell_type": "markdown",
164 | "metadata": {
165 | "slideshow": {
166 | "slide_type": "subslide"
167 | }
168 | },
169 | "source": [
170 | "One way to prescribe a numerical flux would be the following:\n",
171 | "$$\n",
172 | " \\mathcal{F}(Q_{i-1}, Q_i) = -\\beta_{i-1/2} \\left ( \\frac{Q_i - Q_{i-1}}{\\Delta x} \\right ).\n",
173 | "$$\n",
174 | "If we use this in our previous definition we then have\n",
175 | "$$\n",
176 | " Q^{n+1}_i = Q^n_i + \\frac{\\Delta t}{\\Delta x^2} \\left[ \\beta_{i+1/2}(Q^n_{i+1} - Q^n_i) - \\beta_{i-1/2} (Q^n_i - Q^n_{i-1}) \\right]\n",
177 | "$$\n",
178 | "noting that if $\\beta$ is constant we have\n",
179 | "$$\n",
180 | " Q^{n+1}_i = Q^n_i + \\beta \\frac{\\Delta t }{\\Delta x^2} \\left[ Q^n_{i+1} - 2 Q^n_i + Q^n_{i-1} \\right]\n",
181 | "$$"
182 | ]
183 | },
184 | {
185 | "cell_type": "markdown",
186 | "metadata": {
187 | "slideshow": {
188 | "slide_type": "subslide"
189 | }
190 | },
191 | "source": [
192 | "We however know that the previous scheme is not ideal. Instead if we use the well-known Crank-Nicolson scheme we have\n",
193 | "$$\n",
194 | " Q^{n+1}_i = Q^n_i + \\frac{\\Delta t}{2 \\Delta x^2} \\left[ \\beta_{i+1/2}(Q^n_{i+1} - Q^n_i) - \\beta_{i-1/2} (Q^n_i - Q^n_{i-1}) + \\beta_{i+1/2}(Q^{n+1}_{i+1} - Q^{n+1}_i) - \\beta_{i-1/2} (Q^{n+1}_i - Q^{n+1}_{i-1})\\right ]\n",
195 | "$$\n",
196 | "with the flux\n",
197 | "$$\n",
198 | " F^n_{i-1/2} = -\\frac{1}{\\Delta x} \\left[ \\beta_{i-1/2} (Q^n_i - Q^n_{i-1}) + \\beta_{i-1/2} (Q^{n+1}_i - Q^{n+1}_{i-1}) \\right ]\n",
199 | "$$"
200 | ]
201 | },
202 | {
203 | "cell_type": "markdown",
204 | "metadata": {
205 | "slideshow": {
206 | "slide_type": "slide"
207 | }
208 | },
209 | "source": [
210 | "## Convergence\n",
211 | "\n",
212 | "For any numerical method we desire that as $\\Delta x, \\Delta t \\rightarrow 0$ that the numerical solution converges to the true solution. This generally requires the following conditions:\n",
213 | "\n",
214 | "1. The method must be consistent: the approximation is valid locally.\n",
215 | "1. The method must be stable: small errors do not accumulate too fast."
216 | ]
217 | },
218 | {
219 | "cell_type": "markdown",
220 | "metadata": {
221 | "slideshow": {
222 | "slide_type": "subslide"
223 | }
224 | },
225 | "source": [
226 | "### Consistency\n",
227 | "\n",
228 | "In the case of numerical fluxes we want to require that the numerical flux reduces to the true flux in some sense. One way to require this is to ensure for regions where $q$ is constant that the numerical flux agrees with the flux function:\n",
229 | "$$\n",
230 | " \\mathcal{F}(q, q) = f(q).\n",
231 | "$$\n",
232 | "A more formal definition is to ensure that there is some sort of Lipschitz continuity of the form\n",
233 | "$$\n",
234 | " |\\mathcal{F}(Q_{i-1}, Q_i) - f(q)| \\leq L \\text{max}(|Q_i - q|, |Q_{i-1} - q|).\n",
235 | "$$"
236 | ]
237 | },
238 | {
239 | "cell_type": "markdown",
240 | "metadata": {
241 | "slideshow": {
242 | "slide_type": "subslide"
243 | }
244 | },
245 | "source": [
246 | "### Stability\n",
247 | "\n",
248 | "Stability can take on many different forms, many of which will be discussed later. Here we will consider the necessary condition of CFL stability. This is usually expressed as\n",
249 | "\n",
250 | "$$\n",
251 | " \\nu \\equiv \\left |\\frac{u \\Delta t}{\\Delta x} \\right | \\leq 1.\n",
252 | "$$"
253 | ]
254 | },
255 | {
256 | "cell_type": "markdown",
257 | "metadata": {
258 | "slideshow": {
259 | "slide_type": "slide"
260 | }
261 | },
262 | "source": [
263 | "## Numerical Fluxes\n",
264 | "\n",
265 | "We now will consider a number of different flux definitions and consider their viability."
266 | ]
267 | },
268 | {
269 | "cell_type": "markdown",
270 | "metadata": {
271 | "slideshow": {
272 | "slide_type": "subslide"
273 | }
274 | },
275 | "source": [
276 | "### Example: Unstable Flux\n",
277 | "\n",
278 | "Consider the flux\n",
279 | "$$\n",
280 | " F^n_{i-1/2} = \\mathcal{F}(Q^n_{i-1}, Q^n_i) = \\frac{1}{2} [f(Q^n_{i-1}) + f(Q^n_i)]\n",
281 | "$$\n",
282 | "leading to the method\n",
283 | "$$\n",
284 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{2 \\Delta x} [f(Q^n_{i+1}) + f(Q^n_{i-1})].\n",
285 | "$$\n",
286 | "\n",
287 | "Unfortunately this method is unstable!"
288 | ]
289 | },
290 | {
291 | "cell_type": "markdown",
292 | "metadata": {
293 | "slideshow": {
294 | "slide_type": "subslide"
295 | }
296 | },
297 | "source": [
298 | "### Example: Lax-Friedrichs Method\n",
299 | "\n",
300 | "The classical Lax-Friedrichs method has the flux function\n",
301 | "$$\n",
302 | " \\mathcal{F}(Q^n_{i-1}, Q^n_i) = \\frac{1}{2} [f(Q^n_{i-1}) + f(Q^n_i)] - \\frac{\\Delta x}{2 \\Delta t} (Q^n_i - Q^n_{i-1})\n",
303 | "$$\n",
304 | "and the full method\n",
305 | "$$\n",
306 | " Q^{n+1}_i = \\frac{1}{2} (Q^n_{i-1} + Q^n_{i+1}) - \\frac{\\Delta t}{2 \\Delta x} [ f(Q^n_{i+1}) - f(Q^n_{i-1})]\n",
307 | "$$\n",
308 | "leading to a first order accurate method."
309 | ]
310 | },
311 | {
312 | "cell_type": "markdown",
313 | "metadata": {
314 | "slideshow": {
315 | "slide_type": "subslide"
316 | }
317 | },
318 | "source": [
319 | "### Example: Upwind Methods\n",
320 | "\n",
321 | "We know from finite difference methods that upwind methods have a significant advantage over more general methods by simply looking at where the flow is coming from thereby satisfying the CFL condition. In terms of fluxes the upwind method for advection is\n",
322 | "$$\n",
323 | " F^n_{i-1/2} = u Q^n_{i-1}\n",
324 | "$$\n",
325 | "if $u \\ge 0$. Using this flux function gives us the standard upwind method\n",
326 | "$$\n",
327 | " Q^{n+1}_i = Q^n_i - \\frac{u \\Delta t}{\\Delta x} (Q^n_i - Q^n_{i-1}).\n",
328 | "$$"
329 | ]
330 | },
331 | {
332 | "cell_type": "markdown",
333 | "metadata": {
334 | "slideshow": {
335 | "slide_type": "subslide"
336 | }
337 | },
338 | "source": [
339 | "Note that the last equation has a difference of the values of $Q$ meaning that we can write this in terms of our waves. In this context the numerical method can be written as\n",
340 | "$$\n",
341 | " Q^{n+1}_i = Q^n_i - \\frac{u \\Delta t}{\\Delta x} \\mathcal{W}_{i-1/2}.\n",
342 | "$$"
343 | ]
344 | },
345 | {
346 | "cell_type": "markdown",
347 | "metadata": {
348 | "slideshow": {
349 | "slide_type": "subslide"
350 | }
351 | },
352 | "source": [
353 | "We can also write the method in terms of $u \\leq 0$ as\n",
354 | "$$\n",
355 | " Q^{n+1}_i = Q^n_i - \\frac{u \\Delta t}{\\Delta x} \\mathcal{W}_{i+1/2}.\n",
356 | "$$"
357 | ]
358 | },
359 | {
360 | "cell_type": "markdown",
361 | "metadata": {
362 | "slideshow": {
363 | "slide_type": "subslide"
364 | }
365 | },
366 | "source": [
367 | "We can generalize this so that we can define a flux function\n",
368 | "$$\n",
369 | " F^n_{i-1/2} = u^- Q^n_i + u^+ Q^n_{i-1}\n",
370 | "$$\n",
371 | "where\n",
372 | "$$\n",
373 | " u^+ = \\text{max}(u, 0) \\text{ and } u^- = \\text{min}(u, 0)\n",
374 | "$$\n",
375 | "allowing us to write a more general method as\n",
376 | "$$\n",
377 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{\\Delta x} (u^+ \\mathcal{W}_{i-1/2} + u^- \\mathcal{W}_{i+1/2})\n",
378 | "$$"
379 | ]
380 | },
381 | {
382 | "cell_type": "markdown",
383 | "metadata": {
384 | "slideshow": {
385 | "slide_type": "slide"
386 | }
387 | },
388 | "source": [
389 | "## Godunov's Method\n",
390 | "\n",
391 | "One of the most well-known approaches for constructing a solution to a Riemann problem and a cell update is **Godunov's method**. For linear advection upwind is a special case of Godunov's method."
392 | ]
393 | },
394 | {
395 | "cell_type": "markdown",
396 | "metadata": {
397 | "slideshow": {
398 | "slide_type": "subslide"
399 | }
400 | },
401 | "source": [
402 | "### REA Algorithm\n",
403 | "\n",
404 | "One way to view Godunov's method is in the algorithmic steps\n",
405 | "\n",
406 | "1. Reconstruct\n",
407 | "1. Evolve\n",
408 | "1. Average\n",
409 | "\n",
410 | "We will go through each step in detail next."
411 | ]
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "metadata": {
416 | "slideshow": {
417 | "slide_type": "subslide"
418 | }
419 | },
420 | "source": [
421 | "#### 1. Reconstruct\n",
422 | "\n",
423 | "Reconstruct a piecewise polynomial function $\\widetilde{q}^n(x, t_n)$ defined $\\forall x \\in \\mathcal{C}_i$ from the cell averages $Q^n_i$.\n",
424 | "$$\n",
425 | " \\frac{1}{\\Delta x} \\int_{\\mathcal{i}} \\widetilde{q}^n(x, t_n) dx = Q^n_i\n",
426 | "$$\n",
427 | "In the simplest case we use a piecewise constant and we therefore have\n",
428 | "$$\n",
429 | " \\widetilde{q}^n(x, t_n) = Q^n_i \\quad \\forall x \\in \\mathcal{C}_i.\n",
430 | "$$"
431 | ]
432 | },
433 | {
434 | "cell_type": "markdown",
435 | "metadata": {
436 | "slideshow": {
437 | "slide_type": "subslide"
438 | }
439 | },
440 | "source": [
441 | "#### 2. Evolve\n",
442 | "\n",
443 | "Evolve the hyperbolic equation exactly (or approximately) with this initial data to obtain $\\widetilde{q}^n(x, t_{n+1})$ a time $\\Delta t$ later."
444 | ]
445 | },
446 | {
447 | "cell_type": "markdown",
448 | "metadata": {
449 | "slideshow": {
450 | "slide_type": "subslide"
451 | }
452 | },
453 | "source": [
454 | "#### 3. Average\n",
455 | "\n",
456 | "Average this new function $\\widetilde{q}^n(x, t_{n+1})$ over the grid cell $\\mathcal{C}_i$ to obtain the new cell-average:\n",
457 | "$$\n",
458 | " Q^{n+1}_i = \\frac{1}{\\Delta x} \\int_{\\mathcal{C}_i} \\widetilde{q}^n(x, t_{n+1}) dx.\n",
459 | "$$"
460 | ]
461 | },
462 | {
463 | "cell_type": "markdown",
464 | "metadata": {
465 | "slideshow": {
466 | "slide_type": "subslide"
467 | }
468 | },
469 | "source": [
470 | "One of the key points to note in Godunov's method is that in step 2, evolve, we are solving the hyperbolic equation nominally exactly. In the simple case of the piecewise constants we have set of Riemann problems to solve, hence their importance in our ongoing discussion."
471 | ]
472 | },
473 | {
474 | "cell_type": "markdown",
475 | "metadata": {
476 | "slideshow": {
477 | "slide_type": "subslide"
478 | }
479 | },
480 | "source": [
481 | "### Time Step Constraints\n",
482 | "\n",
483 | "What kind of time constraints arise naturally from Godunov's method? Drawing some diagrams we may think that we need to take timesteps limited by\n",
484 | "$$\n",
485 | " c \\Delta t \\leq \\frac{1}{2} \\Delta x.\n",
486 | "$$"
487 | ]
488 | },
489 | {
490 | "cell_type": "markdown",
491 | "metadata": {
492 | "slideshow": {
493 | "slide_type": "subslide"
494 | }
495 | },
496 | "source": [
497 | "### Numerical Flux for Godunov's Method\n",
498 | "\n",
499 | "So far we have been able to write an effective numerical flux function for each approach we have discussed. The same can be said for Godunov's method. The basic formula for a flux should look like\n",
500 | "$$\n",
501 | " F^n_{i-1/2} \\approx \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} f(q(x_{i-1}, t)) dt.\n",
502 | "$$"
503 | ]
504 | },
505 | {
506 | "cell_type": "markdown",
507 | "metadata": {
508 | "slideshow": {
509 | "slide_type": "subslide"
510 | }
511 | },
512 | "source": [
513 | "The most direct thing we could do is to replace the value of $q(x_{i-1}, t)$ with our reconstructed function such that\n",
514 | "$$\\begin{aligned}\n",
515 | " F^n_{i-1/2} \\approx& \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} f(q(x_{i-1}, t)) dt \\\\\n",
516 | " = & \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} f(\\widetilde{q}(x_{i-1}, t)) dt\n",
517 | "\\end{aligned}$$\n",
518 | "What does this integrate to now?"
519 | ]
520 | },
521 | {
522 | "cell_type": "markdown",
523 | "metadata": {
524 | "slideshow": {
525 | "slide_type": "subslide"
526 | }
527 | },
528 | "source": [
529 | "Recall that for a general Riemann solution we have a set of states in between each wave. Inside this wedge the solution $\\widetilde{q}(x_{i-1}, t)$ is constant. If we define the value along the grid cell edge at $x_{i-1/2}$ as $\\widehat{q}(Q^n_{i-1}, Q^n_i)$ we can then find an expression for the flux as\n",
530 | "\n",
531 | "$$\\begin{aligned}\n",
532 | " F^n_{i-1/2} \\approx& \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} f(\\widetilde{q}(x_{i-1}, t)) dt \\\\\n",
533 | " & = f(\\widehat{q}(Q^n_{i-1}, Q^n_i)).\n",
534 | "\\end{aligned}$$"
535 | ]
536 | },
537 | {
538 | "cell_type": "markdown",
539 | "metadata": {
540 | "slideshow": {
541 | "slide_type": "subslide"
542 | }
543 | },
544 | "source": [
545 | "### Wave-Propagation Form of Godunov's Method\n",
546 | "\n",
547 | "Writing Godunov's method in terms of wave-propagation has some advantages later on when we consider non-conservative hyperbolic PDEs and non-linear cases. To that end consider the definition of our waves from before as\n",
548 | "$$\n",
549 | " Q_i - Q_{i-1} = \\sum^m_{p=1} \\alpha^p_{i-1/2} r^p \\equiv \\sum^m_{p=1} \\mathcal{W}^p_{i-1/2}.\n",
550 | "$$"
551 | ]
552 | },
553 | {
554 | "cell_type": "markdown",
555 | "metadata": {
556 | "slideshow": {
557 | "slide_type": "subslide"
558 | }
559 | },
560 | "source": [
561 | "Recall that we can find any middle state starting from the left or right states, $q_\\ell$ or $q_r$ respectively, in the Riemann fan.\n",
562 | "\n",
563 | "For example, if we are crossing $\\mathcal{W}^2_{i-1/2} - \\alpha^2_{i-1/2} r^2$ say, we know that the wave propagates at speed $\\lambda^2$ and crosses $\\lambda^2 \\Delta t$ over the time step. Averaging this impact into the grid cell then would lead to\n",
564 | "$$\n",
565 | " -\\frac{\\lambda^2 \\Delta t}{\\Delta x} \\mathcal{W}^2_{i-1/2}.\n",
566 | "$$"
567 | ]
568 | },
569 | {
570 | "cell_type": "markdown",
571 | "metadata": {
572 | "slideshow": {
573 | "slide_type": "subslide"
574 | }
575 | },
576 | "source": [
577 | "Taking this to the logical conclusion we then can write the solution as\n",
578 | "$$\\begin{aligned}\n",
579 | " Q^{n+1}_i =& Q^n_i - \\frac{\\lambda^2 \\Delta t}{\\Delta x} \\mathcal{W}^2_{i-1/2} - \\frac{\\lambda^3 \\Delta t}{\\Delta x} \\mathcal{W}^3_{i-1/2} - \\frac{\\lambda^1 \\Delta t}{\\Delta x} \\mathcal{W}^1_{i+1/2} \\\\\n",
580 | " &=Q^n_i - \\frac{\\Delta t}{\\Delta x} (\\lambda^2 \\mathcal{W}^2_{i-1/2} + \\lambda^3 \\mathcal{W}^3_{i-1/2} + \\lambda^1 \\mathcal{W}^1_{i+1/2})\n",
581 | "\\end{aligned}$$"
582 | ]
583 | },
584 | {
585 | "cell_type": "markdown",
586 | "metadata": {
587 | "slideshow": {
588 | "slide_type": "subslide"
589 | }
590 | },
591 | "source": [
592 | "Define $\\lambda^+ \\equiv \\max(\\lambda, 0)$ and $\\lambda^- \\equiv \\min(\\lambda, 0)$ we can write this in general as\n",
593 | "$$\n",
594 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{\\Delta x} \\left[ \\sum^m_{p=1} (\\lambda^p)^+ \\mathcal{W}^p_{i-1/2} + \\sum^m_{p=1} (\\lambda^p)^- \\mathcal{W}^p_{i+1/2} \\right ].\n",
595 | "$$\n",
596 | "At this point we can identify the numerical fluxes that are now defined as\n",
597 | "$$\n",
598 | " F^n_{i-1/2} = A Q_{i-1} + \\sum^m_{p=1} (\\lambda^p)^+ \\mathcal{W}^p_{i-1/2}\n",
599 | "$$\n",
600 | "for a linear case."
601 | ]
602 | },
603 | {
604 | "cell_type": "markdown",
605 | "metadata": {
606 | "slideshow": {
607 | "slide_type": "subslide"
608 | }
609 | },
610 | "source": [
611 | "We will also introduce the notation at this point of the **fluctuations**\n",
612 | "$$\n",
613 | " \\mathcal{A}^- \\Delta Q_{i-1/2} = \\sum^m_{p=1} (\\lambda^p)^- \\mathcal{W}^p_{i-1/2} \\\\\n",
614 | " \\mathcal{A}^+ \\Delta Q_{i-1/2} = \\sum^m_{p=1} (\\lambda^p)^+ \\mathcal{W}^p_{i-1/2}\n",
615 | "$$\n",
616 | "so that the previous update formula can be written as\n",
617 | "$$\n",
618 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{\\Delta x} \\left[ \\mathcal{A}^+ \\Delta Q_{i-1/2} + \\mathcal{A}^- \\Delta Q_{i+1/2} \\right ].\n",
619 | "$$\n",
620 | "These fluctuations represent the total impact of the left and right going waves. "
621 | ]
622 | },
623 | {
624 | "cell_type": "markdown",
625 | "metadata": {
626 | "slideshow": {
627 | "slide_type": "subslide"
628 | }
629 | },
630 | "source": [
631 | "This additional notation can be motivated via the linear case. If we define the matrices\n",
632 | "$$\n",
633 | " \\Lambda^+ = \\text{diag}[(\\lambda^p)^+] \\quad \\Lambda^- = \\text{diag}[(\\lambda^p)^-]\n",
634 | "$$\n",
635 | "we can then also write split matrices for $A$ as\n",
636 | "$$\n",
637 | " A^+ = R \\Lambda^+ R^{-1} \\quad A^- = R \\Lambda^- R^{-1}\n",
638 | "$$\n",
639 | "noting that\n",
640 | "$$\n",
641 | " A = R \\Lambda R^{-1} = R (\\Lambda^+ + \\Lambda^-) R^{-1} = A^+ + A^-.\n",
642 | "$$"
643 | ]
644 | },
645 | {
646 | "cell_type": "markdown",
647 | "metadata": {
648 | "slideshow": {
649 | "slide_type": "subslide"
650 | }
651 | },
652 | "source": [
653 | "Turning back to our notation, we can now write the multiplication\n",
654 | "$$\\begin{aligned}\n",
655 | " A^+ \\Delta Q_{i-1/2} &= R \\Lambda^+ R^{-1} (Q_i - Q_{i-1}) \\\\\n",
656 | " =& R \\Lambda^+ \\alpha_{i-1/2} \\\\\n",
657 | " =& \\sum^m_{p=1} (\\lambda^p) \\alpha^p_{i-1/2} r^p \\\\\n",
658 | " =& \\mathcal{A}^+ \\Delta Q_{i-1/2}.\n",
659 | "\\end{aligned}$$"
660 | ]
661 | },
662 | {
663 | "cell_type": "markdown",
664 | "metadata": {
665 | "slideshow": {
666 | "slide_type": "subslide"
667 | }
668 | },
669 | "source": [
670 | "### Roe's Method\n",
671 | "\n",
672 | "One additional and helpful way to look at the definition of the fluxes is to rewrite\n",
673 | "$$\n",
674 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{\\Delta x} \\left[ \\sum^m_{p=1} (\\lambda^p)^+ \\mathcal{W}^p_{i-1/2} + \\sum^m_{p=1} (\\lambda^p)^- \\mathcal{W}^p_{i+1/2} \\right ]\n",
675 | "$$\n",
676 | "or the flux version\n",
677 | "$$\n",
678 | " F^n_{i-1/2} = \\sum^m_{p=1} (\\lambda^p)^+ \\mathcal{W}^p_{i-1/2}\n",
679 | "$$\n",
680 | "as\n",
681 | "$$\n",
682 | " F^n_{i-1/2} = \\frac{1}{2} \\left [ (AQ_{i-1} + AQ_i) - \\sum^m_{p=1} [(\\lambda^p)^+ - (\\lambda^p)^- ] \\mathcal{W}^p_{i-1/2} \\right].\n",
683 | "$$"
684 | ]
685 | },
686 | {
687 | "cell_type": "markdown",
688 | "metadata": {
689 | "slideshow": {
690 | "slide_type": "subslide"
691 | }
692 | },
693 | "source": [
694 | "Define\n",
695 | "$$\n",
696 | " |A| = R |\\Lambda| R^{-1|} \\quad |\\Lambda| = \\text{diag}(|\\lambda^p|)\n",
697 | "$$\n",
698 | "we then have\n",
699 | "$$\\begin{aligned}\n",
700 | " F^n_{i-1/2} &= \\frac{1}{2} \\left [ (AQ_{i-1} + AQ_i) - \\sum^m_{p=1} [(\\lambda^p)^+ - (\\lambda^p)^- ] \\mathcal{W}^p_{i-1/2} \\right] \\\\\n",
701 | " &= \\frac{1}{2}(A Q_{i-1} + A Q_i) - \\frac{1}{2} |A| (Q_i - Q_{i-1}) \\\\\n",
702 | " &= \\frac{1}{2} [f(Q_{i-1} + f(Q_i)] - \\frac{1}{2} |A| (Q_i - Q_{i-1})\n",
703 | "\\end{aligned}$$\n",
704 | "hence an average of of the fluxes we know to be unstable *plus* a correction term."
705 | ]
706 | }
707 | ],
708 | "metadata": {
709 | "celltoolbar": "Slideshow",
710 | "kernelspec": {
711 | "display_name": "Python 3",
712 | "language": "python",
713 | "name": "python3"
714 | },
715 | "language_info": {
716 | "codemirror_mode": {
717 | "name": "ipython",
718 | "version": 3
719 | },
720 | "file_extension": ".py",
721 | "mimetype": "text/x-python",
722 | "name": "python",
723 | "nbconvert_exporter": "python",
724 | "pygments_lexer": "ipython3",
725 | "version": "3.7.4"
726 | }
727 | },
728 | "nbformat": 4,
729 | "nbformat_minor": 2
730 | }
731 |
--------------------------------------------------------------------------------
/03_high_resolution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "skip"
8 | }
9 | },
10 | "source": [
11 | "\n",
12 | " \n",
13 | " | Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli | \n",
14 | "
"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "slideshow": {
22 | "slide_type": "skip"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "from __future__ import print_function\n",
28 | "\n",
29 | "%matplotlib inline\n",
30 | "import numpy\n",
31 | "import matplotlib.pyplot as plt\n",
32 | "import matplotlib.animation\n",
33 | "from IPython.display import HTML\n",
34 | "\n",
35 | "import os\n",
36 | "import pyclaw\n",
37 | "path = os.path.join(os.environ.get(\"CLAW\", os.getcwd()), \"pyclaw\", \"fvmbook\", \"chap6\")\n",
38 | "os.chdir(path)\n",
39 | "import advection"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {
45 | "slideshow": {
46 | "slide_type": "slide"
47 | }
48 | },
49 | "source": [
50 | "# High-Resolution Methods\n",
51 | "\n",
52 | "The general approach we will take to augmenting our wave propagation methodology is to add correction terms in the following way:\n",
53 | "$$\n",
54 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{\\Delta x} \\left (\\mathcal{A}^+ \\Delta Q_{i-1/2} + \\mathcal{A}^- \\Delta Q_{i+1/2} \\right) - \\frac{\\Delta t}{\\Delta x} \\left (\\widetilde{F}_{i+1/2} - \\widetilde{F}_{i-1/2} \\right)\n",
55 | "$$\n",
56 | "where here we have written these corrections as fluxes."
57 | ]
58 | },
59 | {
60 | "cell_type": "markdown",
61 | "metadata": {
62 | "slideshow": {
63 | "slide_type": "slide"
64 | }
65 | },
66 | "source": [
67 | "## Lax-Wendroff Method\n",
68 | "\n",
69 | "The first approach we will investigate is the Lax-Wendroff method derived from a Taylor series approach. Recall that the Taylor series of our solution has the form\n",
70 | "$$\n",
71 | " q(x, t_{n+1}) = q(x, t_n) + \\Delta t q_t(x, t_n) + \\frac{1}{2} \\Delta t^2 q_{tt}(x, t_n) + \\ldots\n",
72 | "$$\n",
73 | "If we consider solving the linear advection problem $q_t + A q_x = 0$ and assume *smooth solutions* then we can replace time derivatives with spatial derivatives in our Taylor series above where $q_t = -A q_x$ to find\n",
74 | "$$\n",
75 | " q(x, t_{n+1}) = q(x, t_n) - \\Delta t A q_x(x, t_n) + \\frac{1}{2} \\Delta t^2 q_{tt}(x, t_n) + \\ldots\n",
76 | "$$"
77 | ]
78 | },
79 | {
80 | "cell_type": "markdown",
81 | "metadata": {
82 | "slideshow": {
83 | "slide_type": "subslide"
84 | }
85 | },
86 | "source": [
87 | "Taking the second time derivative of $q_t = -A q_x$ leads to\n",
88 | "$$\\begin{aligned}\n",
89 | " \\frac{\\partial}{\\partial t} (q_t) =& \\frac{\\partial}{\\partial t}(-A q_x) \\\\\n",
90 | " q_{tt} =& -A (q_x)_t \\\\\n",
91 | " q_{tt} =& A^2 q_{xx}.\n",
92 | "\\end{aligned}$$\n",
93 | "Plugging this in again into our Taylor series we now have\n",
94 | "$$\n",
95 | " q(x, t_{n+1}) = q(x, t_n) - \\Delta t A q_x(x, t_n) + \\frac{1}{2} \\Delta t^2 A^2 q_{xx}(x, t_n) + \\ldots\n",
96 | "$$"
97 | ]
98 | },
99 | {
100 | "cell_type": "markdown",
101 | "metadata": {
102 | "slideshow": {
103 | "slide_type": "subslide"
104 | }
105 | },
106 | "source": [
107 | "Replacing the spatial derivatives with second order finite differences then leads us to the Lax-Wendroff method\n",
108 | "$$\n",
109 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{2 \\Delta x} (Q^n_{i+1} - Q^n_{i-1}) + \\frac{1}{2} \\left(\\frac{\\Delta t}{\\Delta x}\\right)^2 A^2 (Q^n_{i+1} - Q^n_i + Q^n_{i-1}).\n",
110 | "$$"
111 | ]
112 | },
113 | {
114 | "cell_type": "markdown",
115 | "metadata": {
116 | "slideshow": {
117 | "slide_type": "subslide"
118 | }
119 | },
120 | "source": [
121 | "This can again be interpreted as a finite volume method with the flux function defined as\n",
122 | "$$\n",
123 | " F^n_{i-1/2} =\\frac{1}{2} A (Q^n_{i-1} + Q^n_i) - \\frac{1}{2} \\frac{\\Delta t}{\\Delta x} A^2 (Q^n_i - Q^n_{i-1})\n",
124 | "$$\n",
125 | "As mentioned before this looks like the unstable flux with a diffusive correction term. From a method of lines and absolute stability point-of-view this is exactly what pushed the eigenvalues into the absolute stability region of forward Euler."
126 | ]
127 | },
128 | {
129 | "cell_type": "code",
130 | "execution_count": null,
131 | "metadata": {
132 | "slideshow": {
133 | "slide_type": "skip"
134 | }
135 | },
136 | "outputs": [],
137 | "source": [
138 | "def q_true(t, IC='gauss_square'):\n",
139 | " # True Solution\n",
140 | " x_true = numpy.linspace(0.0, 1.0, 1000)\n",
141 | " x_shift = x_true - t\n",
142 | " x_shift = numpy.mod(x_shift, 1.0)\n",
143 | " if IC == 'gauss_square':\n",
144 | " x1 = 0.6; x2 = 0.8\n",
145 | " beta=200.; x0=0.3; mx=100\n",
146 | " q_true = numpy.exp(-beta * (x_shift-x0)**2) + (x_shift>0.6)*(x_shift<0.8)\n",
147 | " elif IC == 'wavepacket':\n",
148 | " beta=100.; x0=0.5; mx=100\n",
149 | " q_true = numpy.exp(-beta * (x_shift-x0)**2) * sin(80.*x_shift)\n",
150 | " return q_true\n",
151 | "\n",
152 | "def advection_animation(solver_order=2, limiters=0, IC='gauss_square'):\n",
153 | " \n",
154 | " # compute the solution with the method define above:\n",
155 | " claw = advection.fig_61_62_63(solver_order=solver_order, limiters=limiters)\n",
156 | " claw.keep_copy = True\n",
157 | " claw.run()\n",
158 | " x = claw.frames[0].grid.dimensions[0].centers\n",
159 | " x_true = numpy.linspace(0.0, 1.0, 1000)\n",
160 | " \n",
161 | " fig = plt.figure()\n",
162 | " axes = plt.subplot(1, 1, 1)\n",
163 | " axes.set_xlim((x[0], x[-1]))\n",
164 | " axes.set_ylim((-0.1, 1.1))\n",
165 | " axes.set_title(\"Lax-Wendroff\")\n",
166 | " \n",
167 | " def init():\n",
168 | " axes.set_xlim((x[0], x[-1]))\n",
169 | " axes.set_ylim((-0.1, 1.1))\n",
170 | " computed_line, = axes.plot(x[0], claw.frames[0].q[0, :][0], 'ro')\n",
171 | " exact_line, = axes.plot(x_true[0], q_true(0.0)[0], 'k')\n",
172 | " return (computed_line, exact_line)\n",
173 | " \n",
174 | " computed_line, exact_line = init()\n",
175 | " \n",
176 | " def fplot(n):\n",
177 | " computed_line.set_data([x,], [claw.frames[n].q[0, :]])\n",
178 | " exact_line.set_data([x_true], [q_true(claw.frames[n].t)])\n",
179 | " return (computed_line, exact_line)\n",
180 | "\n",
181 | " frames_to_plot = range(0, len(claw.frames))\n",
182 | " plt.close(fig)\n",
183 | " return matplotlib.animation.FuncAnimation(fig, fplot, frames=frames_to_plot, interval=100,\n",
184 | " blit=True, init_func=init, repeat=False)"
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "execution_count": null,
190 | "metadata": {},
191 | "outputs": [],
192 | "source": [
193 | "HTML(advection_animation(solver_order=2, limiters=0, IC='gauss_square').to_jshtml())"
194 | ]
195 | },
196 | {
197 | "cell_type": "markdown",
198 | "metadata": {
199 | "slideshow": {
200 | "slide_type": "slide"
201 | }
202 | },
203 | "source": [
204 | "## Beam-Warming Method\n",
205 | "Another approach to second order accuracy is to instead use one-sided or upwinded derivative approximations. With the same Taylor series approach if we instead replace the spatial derivatives with upwinded differences we then have\n",
206 | "$$\\begin{aligned}\n",
207 | " q_x(x_i,t_n) &= \\frac{1}{2\\Delta x} [3 q(x_i, t_n) - 4q(x_{i-1}, t_n) + q(x_{i-2}, t_n)] + \\mathcal{O}(\\Delta x^2) \\\\\n",
208 | " q_{xx}(x_i,t_n) &= \\frac{1}{\\Delta x^2} [q(x_i, t_n) - 2q(x_{i-1}, t_n) + q(x_{i-2}, t_n)] + \\mathcal{O}(\\Delta x^2) \\\\\n",
209 | "\\end{aligned}$$\n",
210 | "leading to\n",
211 | "$$\n",
212 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{2 \\Delta x} A (3 Q^n_i - 4 Q^n_{i-1} + Q^n_{i-2} ) + \\frac{1}{2} \\left(\\frac{\\Delta t}{\\Delta z} \\right)^2 A^2 (Q^n - 2 Q^n_{i-1} + Q^n_{i-2})\n",
213 | "$$\n",
214 | "or in flux form\n",
215 | "$$\n",
216 | " F^n_{i-1/2} = A Q^n_{i-1} + \\frac{1}{2} A \\left ( 1 - \\frac{\\Delta t}{\\Delta x} A \\right) (Q^n_{i-1} - Q^n_{i-2}).\n",
217 | "$$"
218 | ]
219 | },
220 | {
221 | "cell_type": "markdown",
222 | "metadata": {
223 | "slideshow": {
224 | "slide_type": "slide"
225 | }
226 | },
227 | "source": [
228 | "## Preview of Limiters\n",
229 | "\n",
230 | "Given that higher order methods work well in smooth regions while lower order methods work better in regions where high gradients or discontinuities exist we will pursue a way to combine the advantages of both and decide dynamically what type of method to use. This is the primary role of a limiter."
231 | ]
232 | },
233 | {
234 | "cell_type": "markdown",
235 | "metadata": {
236 | "slideshow": {
237 | "slide_type": "subslide"
238 | }
239 | },
240 | "source": [
241 | "As a first examination of this idea consider the numerical flux for the Lax-Wendroff method rewritten in the form\n",
242 | "$$\n",
243 | " F^n_{i-1/2} = (A^- Q^n_i + A^+Q^n_{i-1}) + \\frac{1}{2} |A| \\left ( I - \\frac{\\Delta t}{\\Delta x} |A| \\right) (Q^n_i - Q^n_{i-1})\n",
244 | "$$\n",
245 | "This is therefore the upwind flux with a correction term added similar to how we suggested in the beginning of this lecture."
246 | ]
247 | },
248 | {
249 | "cell_type": "markdown",
250 | "metadata": {
251 | "slideshow": {
252 | "slide_type": "subslide"
253 | }
254 | },
255 | "source": [
256 | "We can also rewrite the previous flux then as\n",
257 | "$$\\begin{aligned}\n",
258 | " F^n_{i-1/2} &= (A^- Q^n_i + A^+Q^n_{i-1}) + \\frac{1}{2} |A| \\left ( I - \\frac{\\Delta t}{\\Delta x} |A| \\right) (Q^n_i - Q^n_{i-1}) \\\\\n",
259 | " &=\\mathcal{F}_L(Q_{i-1}, Q_i) + \\Phi^n_{i-1/2} [\\mathcal{F}_H(Q_{i-1}, Q_i) - \\mathcal{F}_L(Q_{i-1}, Q_i)]\n",
260 | "\\end{aligned}$$\n",
261 | "\n",
262 | "In this form if $\\Phi^n_{i-1/2} = 0$ then this reduces to the low-order method and if $\\Phi^n_{i-1/2} = 1$ then we get the high-order method."
263 | ]
264 | },
265 | {
266 | "cell_type": "code",
267 | "execution_count": null,
268 | "metadata": {
269 | "slideshow": {
270 | "slide_type": "skip"
271 | }
272 | },
273 | "outputs": [],
274 | "source": [
275 | "### Compare several methods for advecting a Gaussian and square wave.\n",
276 | "### \n",
277 | "### The settings coded here are for Figure 6.1(a).\n",
278 | "### For Figure 6.1(b), set solver.order=2.\n",
279 | "### For Figure 6.2(a), set solver.order=2 and solver.limiters = pyclaw.limiters.tvd.minmod (1)\n",
280 | "### For Figure 6.2(b), set solver.order=2 and solver.limiters = pyclaw.limiters.tvd.superbee (2)\n",
281 | "### For Figure 6.2(c), set solver.order=2 and solver.limiters = pyclaw.limiters.tvd.MC (4)\n",
282 | "\n",
283 | "# HTML(advection_animation(solver_order=2, limiters=0, IC='gauss_square').to_jshtml())\n",
284 | "# HTML(advection_animation(solver_order=2, limiters=1, IC='gauss_square').to_jshtml())\n",
285 | "# HTML(advection_animation(solver_order=2, limiters=2, IC='gauss_square').to_jshtml())\n",
286 | "HTML(advection_animation(solver_order=2, limiters=4, IC='gauss_square').to_jshtml())"
287 | ]
288 | },
289 | {
290 | "cell_type": "markdown",
291 | "metadata": {
292 | "slideshow": {
293 | "slide_type": "slide"
294 | }
295 | },
296 | "source": [
297 | "## The REA Algorithm with Piecewise Linear Reconstruction\n",
298 | "\n",
299 | "In the REA algorithm we have the following steps:\n",
300 | "\n",
301 | "1. Reconstruct\n",
302 | "1. Evolve\n",
303 | "1. Average\n",
304 | "\n",
305 | "One of the ways to understand higher-oder methods is to modify the *reconstruct* step to higher-order polynomials."
306 | ]
307 | },
308 | {
309 | "cell_type": "markdown",
310 | "metadata": {
311 | "slideshow": {
312 | "slide_type": "subslide"
313 | }
314 | },
315 | "source": [
316 | "From the cell averages $Q^n_i$ we need to construct piecewise linear functions such that\n",
317 | "$$\n",
318 | " \\widetilde{q}^n(x, t_n) = Q^n_i + \\sigma^n_i (x - x_i) \\quad \\text{for } x_{i-1/2} \\leq x \\leq x_{i+1/2}\n",
319 | "$$\n",
320 | "assuming that x_i is the cell center. We now need to figure out how to determine the slope $\\sigma^n_i$."
321 | ]
322 | },
323 | {
324 | "cell_type": "markdown",
325 | "metadata": {
326 | "slideshow": {
327 | "slide_type": "subslide"
328 | }
329 | },
330 | "source": [
331 | "If we assume $u > 0$ we can compute for linear advection $q_t + u q_x = 0$ that the update formula that correct solution to this problem should be\n",
332 | "$$\\begin{aligned}\n",
333 | " Q^{n+1}_i &= \\frac{u \\Delta t}{\\Delta x} \\left(Q^n_{i-1} + \\frac{1}{2} (\\Delta x - u \\Delta t) \\sigma^n_{i-1} \\right) + \\left(1 - \\frac{u \\Delta t}{\\Delta x} \\right) \\left ( Q^n_i - \\frac{1}{2} u \\Delta t \\sigma^n_i \\right) \\\\\n",
334 | " &= Q^n_i - \\frac{u \\Delta t}{\\Delta x}(Q^n_i - Q^n_{i-1} ) - \\frac{1}{2} \\frac{u \\Delta t}{\\Delta x} (\\Delta x - u \\Delta t) (\\sigma^n_i - \\sigma^n_{i-1})\n",
335 | "\\end{aligned}$$"
336 | ]
337 | },
338 | {
339 | "cell_type": "markdown",
340 | "metadata": {
341 | "slideshow": {
342 | "slide_type": "slide"
343 | }
344 | },
345 | "source": [
346 | "## Choice of Slopes\n",
347 | "\n",
348 | "We still have yet to specify which slope we would like to use for $\\sigma^n_i$. For a linear reconstruction we have three options:\n",
349 | "$$\\begin{aligned}\n",
350 | " &\\text{Centered} & & \\sigma^n_i = \\frac{Q^n_{i+1} - Q^n_{i-1}}{2 \\Delta x} && \\text{(Fromm)} \\\\\n",
351 | " &\\text{Upwind Slope} & & \\sigma^n_i = \\frac{Q^n_{i} - Q^n_{i-1}}{\\Delta x} && \\text{(Beam-Warming)} \\\\\n",
352 | " &\\text{Downwind Slope} & & \\sigma^n_i = \\frac{Q^n_{i+1} - Q^n_{i}}{\\Delta x} && \\text{(Lax-Wendroff)}\n",
353 | "\\end{aligned}$$\n",
354 | "At this point it is not clear exactly which slope might be the best."
355 | ]
356 | },
357 | {
358 | "cell_type": "markdown",
359 | "metadata": {
360 | "slideshow": {
361 | "slide_type": "slide"
362 | }
363 | },
364 | "source": [
365 | "## Oscillations\n",
366 | "\n",
367 | "One of the key observations from the Lax-Wendroff or Beam-Warming methods is that spurious oscillations end up being created. From modified equation analysis this is not surprising given that the leading error terms are dispersive in nature. In the context of hyperbolic PDEs we would like to avoid these oscillations as they are generally not indicative of true solutions. In fact, at a discontinuity we know that in many instances that the solution should dissipating energy or smoothing the solution physically. Therefore we will seek to remove these oscillations from our solutions."
368 | ]
369 | },
370 | {
371 | "cell_type": "markdown",
372 | "metadata": {
373 | "slideshow": {
374 | "slide_type": "slide"
375 | }
376 | },
377 | "source": [
378 | "## Total Variation\n",
379 | "\n",
380 | "To provide a concrete way to *limit* the slope we will introduce a mathematical way to measure oscillations.\n",
381 | "\n",
382 | "The **total variation** for a grid function $Q$ is defined as\n",
383 | "$$\n",
384 | " \\text{TV}(Q) = \\sum^\\infty_{i=-\\infty} |Q_i - Q_{i-1} |\n",
385 | "$$"
386 | ]
387 | },
388 | {
389 | "cell_type": "markdown",
390 | "metadata": {
391 | "slideshow": {
392 | "slide_type": "subslide"
393 | }
394 | },
395 | "source": [
396 | "We can also define for a function this metric as \n",
397 | "$$\n",
398 | " \\text{TV}(q(x)) = \\sup \\sum^N_{j=1} |q(\\xi_j) - q(\\xi_{j-1}) |\n",
399 | "$$\n",
400 | "Another definition is\n",
401 | "$$\n",
402 | " \\text{TV}(q) = \\limsup_{\\epsilon \\rightarrow 0} \\frac{1}{\\epsilon} \\int^\\infty_{-\\infty} |q(x) - q(x - \\epsilon)|dx\n",
403 | "$$\n",
404 | "which reduces to\n",
405 | "$$\n",
406 | " \\text{TV}(q) = \\int^\\infty_{-\\infty} |q'(x)|dx\n",
407 | "$$\n",
408 | "if $q$ is differentiable."
409 | ]
410 | },
411 | {
412 | "cell_type": "markdown",
413 | "metadata": {
414 | "slideshow": {
415 | "slide_type": "subslide"
416 | }
417 | },
418 | "source": [
419 | "A two-level method is called **total variation diminishing** (TVD) if, for any set of data $Q^n$, the values $Q^{n+1}$ computed by the method satisfies\n",
420 | "$$\n",
421 | " \\text{TV}(Q^{n+1}) \\leq \\text{TV}(Q^n).\n",
422 | "$$"
423 | ]
424 | },
425 | {
426 | "cell_type": "markdown",
427 | "metadata": {
428 | "slideshow": {
429 | "slide_type": "subslide"
430 | }
431 | },
432 | "source": [
433 | "One important consequence of a TVD method is that if data is initially monotone in the sense that\n",
434 | "$$\n",
435 | " Q^n_i \\leq Q^n_{i+1} \\text{ or } Q^n_i \\geq Q^n_{i+1} \\quad \\forall i\n",
436 | "$$\n",
437 | "then this will hold for all future time. This leads us to the next definition."
438 | ]
439 | },
440 | {
441 | "cell_type": "markdown",
442 | "metadata": {
443 | "slideshow": {
444 | "slide_type": "subslide"
445 | }
446 | },
447 | "source": [
448 | "A method is called **monotonicity-preserving** if \n",
449 | "$$\n",
450 | " Q^n_i \\geq Q^n_{i+1} \\forall i \\Rightarrow Q^{n+1}_i \\geq Q^{n+1}_{i+1} \\forall i\n",
451 | "$$\n",
452 | "Any TVD method is monotonicity preserving."
453 | ]
454 | },
455 | {
456 | "cell_type": "markdown",
457 | "metadata": {
458 | "slideshow": {
459 | "slide_type": "subslide"
460 | }
461 | },
462 | "source": [
463 | "How then can we derive a TVD method? If we follow the REA algorithm then in the reconstruction phase we can require\n",
464 | "$$\n",
465 | " \\text{TV}(\\widetilde{q}^n(x, t_n)) \\leq \\text{TV}(Q^n)\n",
466 | "$$\n",
467 | "so that our resulting evolved function should remain TVD. This can be clearly seen as the evolve step will also maintain this relationship as will the averaging."
468 | ]
469 | },
470 | {
471 | "cell_type": "markdown",
472 | "metadata": {
473 | "slideshow": {
474 | "slide_type": "slide"
475 | }
476 | },
477 | "source": [
478 | "## Slope-Limiter Methods\n",
479 | "\n",
480 | "Now that we have established some basis as to how we may want to reconstruct functions let us return to the question of reconstructing the slopes $\\sigma$."
481 | ]
482 | },
483 | {
484 | "cell_type": "markdown",
485 | "metadata": {
486 | "slideshow": {
487 | "slide_type": "subslide"
488 | }
489 | },
490 | "source": [
491 | "One choice of slope that maintains second-order accuracy and the TVD property is the **minmod slope** defined as \n",
492 | "$$\n",
493 | " \\sigma^n_i = \\text{minmod}\\left( \\frac{Q^n_i - Q^n_{i-1}}{\\Delta x}, \\frac{Q^n_{i+1} - Q^n_{i}}{\\Delta x} \\right)\n",
494 | "$$\n",
495 | "where\n",
496 | "$$\n",
497 | " \\text{minmod}(a, b) = \\left \\{ \\begin{aligned}\n",
498 | " a & & \\text{if } |a| < |b| \\text{ and } ab > 0 \\\\\n",
499 | " b & & \\text{if } |b| < |a| \\text{ and } ab > 0 \\\\\n",
500 | " 0 & & \\text{if } ab \\leq 0 \\\\\n",
501 | " \\end{aligned} \\right .\n",
502 | "$$"
503 | ]
504 | },
505 | {
506 | "cell_type": "markdown",
507 | "metadata": {
508 | "slideshow": {
509 | "slide_type": "subslide"
510 | }
511 | },
512 | "source": [
513 | "Compositions of the minmod function also form a number of slope choices. One in particular is the **monotonized central-difference limiter** (MC)\n",
514 | "$$\n",
515 | " \\sigma^n_i = \\text{minmod}\\left( \\left (\\frac{Q^n_{i+1} - Q^n_{i-1}}{2 \\Delta x} \\right ), 2\\left(\\frac{Q^n_i - Q^n_{i-1}}{\\Delta x} \\right), 2 \\left (\\frac{Q^n_{i+1} - Q^n_{i}}{\\Delta x} \\right ) \\right )\n",
516 | "$$\n",
517 | "Note that these still represent finite difference approximations."
518 | ]
519 | },
520 | {
521 | "cell_type": "markdown",
522 | "metadata": {
523 | "slideshow": {
524 | "slide_type": "slide"
525 | }
526 | },
527 | "source": [
528 | "## Flux Formulation with Piecewise Linear Reconstruction\n",
529 | "\n",
530 | "Using these reconstructed slopes how does this now impact our flux formulations? Let us turn to the basic definition of a flux function then and see how it is impacted by our reconstruction."
531 | ]
532 | },
533 | {
534 | "cell_type": "markdown",
535 | "metadata": {
536 | "slideshow": {
537 | "slide_type": "subslide"
538 | }
539 | },
540 | "source": [
541 | "$$\\begin{aligned}\n",
542 | " F^n_{i-1/2} &= \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} u \\widetilde{q}^n(x_{i-1/2}, t) dt \\\\\n",
543 | " &= \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} u \\widetilde{q}^n(x_{i-1/2} - u(t - t_n), t_n) dt \\\\\n",
544 | " &= \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} u \\left[ Q^n_{i-1} + (x_{i-1/2} - u (t - t_n) - x_{i-1} ) \\sigma^n_{i-1} \\right] dt \\\\\n",
545 | " &= u Q^n_{i-1} + \\frac{1}{2} u (\\Delta x - u \\Delta t) \\sigma^n_{i-1} \\\\\n",
546 | "\\end{aligned}$$\n",
547 | "Plugging this into our original updating formula leads to\n",
548 | "$$\n",
549 | " Q^{n+1}_i = Q^n_i - \\frac{u \\Delta t}{\\Delta x} (Q^n_i - Q^n_{i-1} ) - \\frac{1}{2} \\frac{u \\Delta t}{\\Delta x} (\\Delta x - u \\Delta t) (\\sigma^n_i - \\sigma^n_{i-1})\n",
550 | "$$"
551 | ]
552 | },
553 | {
554 | "cell_type": "markdown",
555 | "metadata": {
556 | "slideshow": {
557 | "slide_type": "subslide"
558 | }
559 | },
560 | "source": [
561 | "We can also think instead of limiting the fluxes between cells to update our first-order methods to higher-order. If we define\n",
562 | "$$\n",
563 | " \\Delta Q^n_{i-1/2} \\equiv Q^n_i - Q^n_{i-1}\n",
564 | "$$\n",
565 | "and then define a flux such that\n",
566 | "$$\n",
567 | " F^n_{i-1/2} = u^- Q^n_i + u^+ Q^n_{i-1} + \\frac{1}{2} |u| \\left ( 1- \\left |\\frac{u \\Delta t}{\\Delta x} \\right |\\right) \\delta^n_{i-1/2}\n",
568 | "$$\n",
569 | "where\n",
570 | "$$\n",
571 | " \\delta^n_{i-1/2} \\equiv \\text{limited} (\\Delta Q^n_{i-1/2})\n",
572 | "$$"
573 | ]
574 | },
575 | {
576 | "cell_type": "markdown",
577 | "metadata": {
578 | "slideshow": {
579 | "slide_type": "slide"
580 | }
581 | },
582 | "source": [
583 | "## Flux Limiters\n",
584 | "\n",
585 | "We can now start to make connections between our desire for high-order methods, limiting, and TVD. Lax-Wendroff for instance is simply interpretable as the piecewise linear reconstruction in the most straight-forward way as as central difference. Let us meld the rest of the methods and others by generalizing this idea a bit."
586 | ]
587 | },
588 | {
589 | "cell_type": "markdown",
590 | "metadata": {
591 | "slideshow": {
592 | "slide_type": "subslide"
593 | }
594 | },
595 | "source": [
596 | "Let\n",
597 | "$$\n",
598 | " \\delta^n_{i-1/2} = \\phi(\\theta^n_{i-1/2}) \\Delta Q^n_{i-1/2}\n",
599 | "$$\n",
600 | "where\n",
601 | "$$\n",
602 | " \\theta^n_{i-1/2} = \\frac{\\Delta Q^n_{I-1/2}}{\\Delta Q^n_{i-1/2}}\n",
603 | "$$\n",
604 | "and\n",
605 | "$$\n",
606 | " I = \\left \\{ \\begin{aligned}\n",
607 | " i - 1 & & \\text{if } u > 0 \\\\\n",
608 | " i + 1 & & \\text{if } u < 0\n",
609 | " \\end{aligned} \\right .\n",
610 | "$$\n",
611 | "Basically we are \"measuring\" the smoothness of the function $Q$ using $\\theta$. We then want the function $\\phi$ to \"limit\" the slope based on the smoothness of $Q$."
612 | ]
613 | },
614 | {
615 | "cell_type": "markdown",
616 | "metadata": {
617 | "slideshow": {
618 | "slide_type": "subslide"
619 | }
620 | },
621 | "source": [
622 | "One interesting case is to choose\n",
623 | "$$\n",
624 | " \\phi(\\theta) = \\theta\n",
625 | "$$\n",
626 | "where\n",
627 | "$$\n",
628 | " \\delta^n_{i-1/2} = \\left( \\frac{\\Delta Q^n_{I-1/2}}{\\Delta Q^n_{i-1/2}} \\right) \\Delta Q^n_{i-1/2} = \\Delta Q^n_{I-1/2}\n",
629 | "$$\n",
630 | "which reduces to the upwind scheme and therefore the Beam-Warming method."
631 | ]
632 | },
633 | {
634 | "cell_type": "markdown",
635 | "metadata": {
636 | "slideshow": {
637 | "slide_type": "subslide"
638 | }
639 | },
640 | "source": [
641 | "Given this framework we can then define the following set of methods:\n",
642 | "\n",
643 | "Linear Methods:\n",
644 | "$$\\begin{aligned}\n",
645 | " \\text{upwind:} & & \\phi(\\theta) &= 0 \\\\\n",
646 | " \\text{Lax-Wendroff:} & & \\phi(\\theta) &= 1 \\\\\n",
647 | " \\text{Beam-Warming:} & & \\phi(\\theta) &= \\theta \\\\\n",
648 | " \\text{Fromm:} & & \\phi(\\theta) &= \\frac{1}{2} (1 + \\theta) \\\\\n",
649 | "\\end{aligned}$$\n",
650 | "\n",
651 | "High-Resolution (non-linear) Methods:\n",
652 | "$$\\begin{aligned}\n",
653 | " \\text{minmod:} & & \\phi(\\theta) &= \\text{minmod}(1, \\theta) \\\\\n",
654 | " \\text{superbee:} & & \\phi(\\theta) &= \\max(0, \\min(1, 2\\theta), \\min(2, \\theta) \\\\\n",
655 | " \\text{MC:} & & \\phi(\\theta) &= \\max(0, \\min((1+\\theta)/2, 2, 2 \\theta)\\\\\n",
656 | " \\text{van Leer:} & & \\phi(\\theta) &= \\frac{\\theta + |\\theta|}{1 + |\\theta|} \\\\\n",
657 | "\\end{aligned}$$"
658 | ]
659 | },
660 | {
661 | "cell_type": "markdown",
662 | "metadata": {
663 | "slideshow": {
664 | "slide_type": "slide"
665 | }
666 | },
667 | "source": [
668 | "## TVD Limiters\n",
669 | "\n",
670 | "Returning back to our desire for having a TVD scheme we need to ask the question, which of our limiters will make our scheme TVD? This is at times for linear limiters easy to check but we need something a bit more powerful for the non-linear limiters we have introduced."
671 | ]
672 | },
673 | {
674 | "cell_type": "markdown",
675 | "metadata": {
676 | "slideshow": {
677 | "slide_type": "subslide"
678 | }
679 | },
680 | "source": [
681 | "**Harten**: Consider a general method of the form\n",
682 | "$$\n",
683 | " Q^{n+1}_i = Q^n_i - C^n_{i-1} (Q^n_i - Q^n_{i-1}) + D^n_i (Q^n_{i+1} - Q^n_i)\n",
684 | "$$\n",
685 | "over one time step, where the coefficients $C^n_{i-1}$ and $D^n_i$ are arbitrary (which can depend on values of Q^n in particular). Then\n",
686 | "$$\n",
687 | " \\text{TV}(Q^{n+1}) \\leq \\text{TV}(Q^n)\n",
688 | "$$\n",
689 | "provided the following conditions are satisfied\n",
690 | "$$\\begin{aligned}\n",
691 | " C^n_{i-1} \\geq 0 & & \\forall i \\\\\n",
692 | " D^n_{i} \\geq 0 & & \\forall i \\\\\n",
693 | " C^n_{i} + D^n_i \\leq 1 & & \\forall i \\\\\n",
694 | "\\end{aligned}$$"
695 | ]
696 | },
697 | {
698 | "cell_type": "markdown",
699 | "metadata": {
700 | "slideshow": {
701 | "slide_type": "subslide"
702 | }
703 | },
704 | "source": [
705 | "Let's apply this theorem to the flux limiter method for the advection equation where $u > 0$. First the general flux update form looks like \n",
706 | "$$\n",
707 | " Q^{n+1}_i = Q^n_i - \\nu (Q^n_i - Q^n_{i-1} ) - \\frac{1}{2} \\nu (1 - \\nu) [\\phi(\\theta^n_{i+1/2}) (Q^n_{i+1} - Q^n_i) - \\phi(\\theta^n_{i-1/2}) (Q^n_i - Q^n_{i-1})]\n",
708 | "$$\n",
709 | "for flux limiters replacing the $u \\Delta t / \\Delta x$ with $\\nu$. Try to write this in the form from Harten first."
710 | ]
711 | },
712 | {
713 | "cell_type": "markdown",
714 | "metadata": {
715 | "slideshow": {
716 | "slide_type": "subslide"
717 | }
718 | },
719 | "source": [
720 | "We can write this with\n",
721 | "$$\n",
722 | " C^n_{i-1} = \\nu - \\frac{1}{2} \\nu (1 - \\nu) \\phi(\\theta^n_{i-1/2}) \\\\\n",
723 | " D^n_i = -\\frac{1}{2} \\nu (1 - \\nu) \\phi(\\theta^n_{i-1/2})\n",
724 | "$$\n",
725 | "but this is not sufficient to show the method is TVD via Harten's theorem. However, if $0 \\leq \\nu \\leq 1$ then $D < 0$ when $\\phi \\approx 1$."
726 | ]
727 | },
728 | {
729 | "cell_type": "markdown",
730 | "metadata": {
731 | "slideshow": {
732 | "slide_type": "subslide"
733 | }
734 | },
735 | "source": [
736 | "One thing to note however is that \n",
737 | "$$\n",
738 | " Q^n_{i+1} - Q^n_i = \\frac{Q^n_i - Q^n_{i-1} }{\\theta^n_{i+1/2}}\n",
739 | "$$\n",
740 | "so that our original form can actually be written so that\n",
741 | "$$\n",
742 | " C^n_{i-1} = \\nu + \\frac{1}{2} \\nu (1 - \\nu) \\left[ \\frac{\\phi(\\theta^n_{i+1/2} )}{\\theta^n_{i+1/2}} - \\phi(\\theta^n_{i-1/2} ) \\right] \\\\\n",
743 | " D^n_i = 0\n",
744 | "$$\n",
745 | "so that the conditions are satisfied if\n",
746 | "$$\n",
747 | " 0 \\leq C^n_{i-1} \\leq 1\n",
748 | "$$\n",
749 | "which in turn holds if $0 \\leq \\nu \\leq 1$ as well as the bound\n",
750 | "$$\n",
751 | " \\left | \\frac{\\phi(\\theta_1)}{\\theta_1} - \\phi(\\theta_2) \\right | \\leq 2 \\quad \\forall \\theta_1, \\theta_2.\n",
752 | "$$"
753 | ]
754 | },
755 | {
756 | "cell_type": "markdown",
757 | "metadata": {
758 | "slideshow": {
759 | "slide_type": "subslide"
760 | }
761 | },
762 | "source": [
763 | "A couple of interesting cases result from this realization:\n",
764 | "1. $\\theta \\leq 0$: we are at an extremum and we know that $\\phi(\\theta) = 0$.\n",
765 | "1. $\\theta > 0$: we want $\\phi(\\theta) > 0$ as we do not want to negate the sign of the slope"
766 | ]
767 | },
768 | {
769 | "cell_type": "markdown",
770 | "metadata": {
771 | "slideshow": {
772 | "slide_type": "subslide"
773 | }
774 | },
775 | "source": [
776 | "Also we can also disentangle the bound to find\n",
777 | "$$\n",
778 | " 0 \\leq \\frac{\\phi(\\theta)}{\\theta} \\leq 2 \\quad \\text{and} \\quad 0 \\leq \\phi(\\theta) \\leq 2.\n",
779 | "$$\n",
780 | "for all values $\\phi(\\theta) \\geq 0$. This can be rewritten as\n",
781 | "$$\n",
782 | " 0 \\leq \\phi(\\theta) \\leq \\text{minmod}(2, 2\\theta).\n",
783 | "$$"
784 | ]
785 | },
786 | {
787 | "cell_type": "markdown",
788 | "metadata": {
789 | "slideshow": {
790 | "slide_type": "subslide"
791 | }
792 | },
793 | "source": [
794 | "Often we also may want to require the the function $\\phi$ be symmetric implying that\n",
795 | "$$\n",
796 | " \\phi(1 / \\theta) = \\frac{\\phi(\\theta)}{\\theta}\n",
797 | "$$"
798 | ]
799 | },
800 | {
801 | "cell_type": "markdown",
802 | "metadata": {
803 | "slideshow": {
804 | "slide_type": "slide"
805 | }
806 | },
807 | "source": [
808 | "## Methods for Systems\n",
809 | "\n",
810 | "All of these methods of course also apply to systems of hyperbolic PDEs. If we look at the flux differencing form of Lax-Wendroff\n",
811 | "$$\n",
812 | " \\mathcal{F}(Q_{i-1}, Q_i) = \\frac{1}{2} A (Q_{i-1} + Q_i) - \\frac{1}{2} \\frac{\\Delta t}{\\Delta x} A^2 (Q_i - Q_{i-1})\n",
813 | "$$\n",
814 | "and recall that $A = A^+ + A^-$ we can rewrite this as\n",
815 | "$$\n",
816 | " \\mathcal{F}(Q_{i-1}, Q_i) = (A^+ Q_{i-1} + A^- Q_i) + \\frac{1}{2} |A| \\left( I - \\frac{\\Delta t}{\\Delta x} |A| \\right )(Q_i - Q_{i-1}).\n",
817 | "$$\n",
818 | "This has the form of an upwind, first-order term with the added correction due to Lax-Wendroff. We will need to limit this correction term."
819 | ]
820 | },
821 | {
822 | "cell_type": "markdown",
823 | "metadata": {
824 | "slideshow": {
825 | "slide_type": "subslide"
826 | }
827 | },
828 | "source": [
829 | "First rewrite the correction term from before as\n",
830 | "$$\n",
831 | " \\frac{1}{2} |A| \\left( I - \\frac{\\Delta t}{\\Delta x} |A| \\right )(Q_i - Q_{i-1}) = \\frac{1}{2} |A| \\left( I - \\frac{\\Delta t}{\\Delta x} |A| \\right ) \\sum^m_{p=1} \\alpha^p_{i-1/2} r^p\n",
832 | "$$\n",
833 | "effectively writing the jump $\\Delta Q_{i-1/2}$ in terms of the waves or otherwise projecting the jump onto the eigenvectors of $A$. If we replace the coefficient $\\alpha$ with a limited version, i.e.\n",
834 | "$$\n",
835 | " \\widetilde{\\alpha}^p_{i-1/2} = \\alpha^p_{i-1/2} (\\theta^p_{i-1/2})\n",
836 | "$$\n",
837 | "where\n",
838 | "$$\n",
839 | " \\theta^p_{i-1/2} = \\frac{\\alpha^p_{I-1/2}}{\\alpha^p_{i-1/2}}\n",
840 | "$$\n",
841 | "with the $I$ from before."
842 | ]
843 | },
844 | {
845 | "cell_type": "markdown",
846 | "metadata": {
847 | "slideshow": {
848 | "slide_type": "subslide"
849 | }
850 | },
851 | "source": [
852 | "We can then write the original flux as \n",
853 | "$$\n",
854 | " \\mathcal{F}(Q_{i-1}, Q_i) = (A^+ Q_{i-1} + A^- Q_i) + \\frac{1}{2} |A| \\left( I - \\frac{\\Delta t}{\\Delta x} |A| \\right ) \\sum^m_{p=1} \\widetilde{\\alpha}^p_{i-1/2} r^p\n",
855 | "$$\n",
856 | "or using the fact that $|A| r^p = |\\lambda^p| r^p$ we get\n",
857 | "$$\n",
858 | " \\mathcal{F}(Q_{i-1}, Q_i) = (A^+ Q_{i-1} + A^- Q_i) + \\frac{1}{2} \\sum^m_{p=1} \\left( 1 - \\frac{\\Delta t}{\\Delta x} |\\lambda^p| \\right ) \\widetilde{\\alpha}^p_{i-1/2} r^p.\n",
859 | "$$\n",
860 | "Another useful way to write this is in terms of limited waves defined by\n",
861 | "$$\n",
862 | " \\widetilde{\\mathcal{W}}^p_{i-1/2} = \\widetilde{\\alpha}^p_{i-1/2} r^p.\n",
863 | "$$"
864 | ]
865 | },
866 | {
867 | "cell_type": "markdown",
868 | "metadata": {
869 | "slideshow": {
870 | "slide_type": "slide"
871 | }
872 | },
873 | "source": [
874 | "## Wave-Propagation Implementation\n",
875 | "\n",
876 | "We now turn to implementing this in the wave-propagation form and is the way that Clawpack implements these algorithms."
877 | ]
878 | },
879 | {
880 | "cell_type": "markdown",
881 | "metadata": {
882 | "slideshow": {
883 | "slide_type": "subslide"
884 | }
885 | },
886 | "source": [
887 | "First look at the general form where the upwinding terms and limited flux difference are easy to identify:\n",
888 | "$$\n",
889 | " Q^{n+1}_i = Q^n_i - \\frac{\\Delta t}{\\Delta x} (A^+ \\Delta Q_{i-1/2} + A^- \\Delta Q_{i+1/2} ) - \\frac{\\Delta t}{\\Delta x} (\\widetilde{F}_{i+1/2} - \\widetilde{F}_{i-1/2}).\n",
890 | "$$\n",
891 | "Now we replace everything with our waves with\n",
892 | "$$\\begin{aligned}\n",
893 | " A^+ \\Delta Q_{i-1/2} &= \\sum^{m}_{p=1} (\\lambda^p)^+ \\mathcal{W}^p_{i-1/2} \\\\\n",
894 | " A^- \\Delta Q_{i-1/2} &= \\sum^{m}_{p=1} (\\lambda^p)^- \\mathcal{W}^p_{i-1/2} \\\\\n",
895 | " \\widetilde{F}_{i-1/2} &= \\frac{1}{2} \\sum^m_{p=1} \\left( I - \\frac{\\Delta t}{\\Delta x} |\\lambda^p| \\right ) \\widetilde{\\mathcal{W}}^p_{i-1/2}\n",
896 | "\\end{aligned}$$"
897 | ]
898 | },
899 | {
900 | "cell_type": "markdown",
901 | "metadata": {
902 | "slideshow": {
903 | "slide_type": "slide"
904 | }
905 | },
906 | "source": [
907 | "## Non-Linear Systems\n",
908 | "\n",
909 | "In general all the methods mentioned so far can easily be applied to nonlinear systems as well. We can do this by knowing that in general we are still solving Riemann problems that yield a set of waves $\\mathcal{W}^p_{i-1/2}$ and speeds $s^p_{i-1/2}$ that can be treated analogously to the linear problem."
910 | ]
911 | },
912 | {
913 | "cell_type": "markdown",
914 | "metadata": {
915 | "slideshow": {
916 | "slide_type": "subslide"
917 | }
918 | },
919 | "source": [
920 | "Along with this generalization we will define the following more general quantities:\n",
921 | "$$\\begin{aligned}\n",
922 | " \\mathcal{A}^- \\Delta Q_{i-1/2} &= \\sum^m_{p=1} (s^p_{i-1/2})^- \\mathcal{W}^p_{i-1/2}\\\\\n",
923 | " \\mathcal{A}^+ \\Delta Q_{i-1/2} &= \\sum^m_{p=1} (s^p_{i-1/2})^+ \\mathcal{W}^p_{i-1/2}\n",
924 | "\\end{aligned}$$\n",
925 | "and requiring\n",
926 | "$$\\begin{aligned}\n",
927 | " \\mathcal{A}^- \\Delta Q_{i-1/2} + \\mathcal{A}^+ \\Delta Q_{i-1/2} = f(Q_i) - f(Q_{i-1})\n",
928 | "\\end{aligned}$$\n",
929 | "as before. There are additional issues that will be addressed when we start to study the nonlinear problem in more general."
930 | ]
931 | }
932 | ],
933 | "metadata": {
934 | "kernelspec": {
935 | "display_name": "Python 3",
936 | "language": "python",
937 | "name": "python3"
938 | },
939 | "language_info": {
940 | "codemirror_mode": {
941 | "name": "ipython",
942 | "version": 3
943 | },
944 | "file_extension": ".py",
945 | "mimetype": "text/x-python",
946 | "name": "python",
947 | "nbconvert_exporter": "python",
948 | "pygments_lexer": "ipython3",
949 | "version": "3.9.8"
950 | }
951 | },
952 | "nbformat": 4,
953 | "nbformat_minor": 2
954 | }
955 |
--------------------------------------------------------------------------------
/04_bc.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "skip"
8 | }
9 | },
10 | "source": [
11 | "\n",
12 | " \n",
13 | " | Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli | \n",
14 | "
"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "slideshow": {
22 | "slide_type": "skip"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "from __future__ import print_function\n",
28 | "\n",
29 | "%matplotlib inline\n",
30 | "import numpy\n",
31 | "import matplotlib.pyplot as plt\n",
32 | "import matplotlib.animation\n",
33 | "from IPython.display import HTML\n",
34 | "\n",
35 | "import os\n",
36 | "import pyclaw\n",
37 | "path = os.path.join(os.environ.get(\"CLAW\", os.getcwd()), \"pyclaw\", \"fvmbook\", \"chap6\")\n",
38 | "os.chdir(path)\n",
39 | "import advection"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {
45 | "slideshow": {
46 | "slide_type": "slide"
47 | }
48 | },
49 | "source": [
50 | "# Boundary Conditions\n",
51 | "\n",
52 | "Up until now we have yet to address a way to enfore boundary conditions on our methods. In this lecture we will address this and study how we might handle both simple and complex boundary conditions."
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "metadata": {
58 | "slideshow": {
59 | "slide_type": "subslide"
60 | }
61 | },
62 | "source": [
63 | "The primary way we will implement boundary conditions is by adding **ghost cells** to the domain. These cells are outside of the domain and can be set arbitrarily to enforce many types of boundary conditions depending on what is desired. Keep in mind a couple of things though:\n",
64 | "\n",
65 | "1. For many hyperbolic PDEs we only need BCs on one end of the domain.\n",
66 | "1. Enforcing non-reflecting BCs is important for many applications is highly non-trivial.\n",
67 | "1. Setting BCs may require the solution of more complex equations so that an incoming boundary condition is correctly set.\n",
68 | "\n",
69 | "The rest of this lecture will use examples to illustrate different BCs."
70 | ]
71 | },
72 | {
73 | "cell_type": "markdown",
74 | "metadata": {
75 | "slideshow": {
76 | "slide_type": "slide"
77 | }
78 | },
79 | "source": [
80 | "## Example: Advection\n",
81 | "\n",
82 | "Consider the scalar advection equation $q_t + u q_x$ on $x\\in[a,b]$ with BC\n",
83 | "$$\n",
84 | " q(a, t) = g_a(t)\n",
85 | "$$\n",
86 | "that can easily be generalized to also be at $x=b$. Note also that we only have one BC needed."
87 | ]
88 | },
89 | {
90 | "cell_type": "markdown",
91 | "metadata": {
92 | "slideshow": {
93 | "slide_type": "subslide"
94 | }
95 | },
96 | "source": [
97 | "### Outflow Boundary Conditions\n",
98 | "\n",
99 | "Analytically we have no BC at $x = b$ and if we simply use an upwind method we do not need one numerically. However, if we are using a Lax-Wendroff like method we still require a value at $x=b$ to be specified. One of the easiest ways to specify this is to use **zero-order extrapolation** boundary conditions defined by\n",
100 | "$$\n",
101 | " Q^n_{N+1} = Q^n_N \\quad Q^n_{N+2} = Q^n_N.\n",
102 | "$$\n",
103 | "This formulation then implies that the gradient outside of the domain is zero and that in most cases any wave approaching the boundary will simply propagate out of the domain."
104 | ]
105 | },
106 | {
107 | "cell_type": "markdown",
108 | "metadata": {
109 | "slideshow": {
110 | "slide_type": "subslide"
111 | }
112 | },
113 | "source": [
114 | "What about the case where we may want to use a first-order extrapolation given by\n",
115 | "$$\n",
116 | " Q^n_{N+1} = Q^n_N + (Q^n_N - Q^n_{N-1} ) = 2 Q^n_{N} - Q^n_{N-1}?\n",
117 | "$$\n",
118 | "This leads to $\\Delta Q^n_{N+1/2} = \\Delta Q^n_{N-1/2}$ and the correction terms cancel leading to an update that again reduces to first-order upwind."
119 | ]
120 | },
121 | {
122 | "cell_type": "markdown",
123 | "metadata": {
124 | "slideshow": {
125 | "slide_type": "subslide"
126 | }
127 | },
128 | "source": [
129 | "This extrapolation seems simplistic but turns out to be extremely powerful. This extrapolation, in conjunction with our finite volume methods and characteristic decomposition, tend to be very robust when considering non-reflecting boundary conditions. In fact first-order extrapolation can even lead to issues not found in the zero-order extrapolation and is generally not used."
130 | ]
131 | },
132 | {
133 | "cell_type": "markdown",
134 | "metadata": {
135 | "slideshow": {
136 | "slide_type": "subslide"
137 | }
138 | },
139 | "source": [
140 | "### Inflow Boundary Conditions\n",
141 | "\n",
142 | "At the inflow boundary it is a bit more clear what to do. Depending on how the BC is specified there are multiple ways to numerically represent the BC. The most straight forward perhaps is the case when a direct flux is specified that would easily integrate into the methods discussed already."
143 | ]
144 | },
145 | {
146 | "cell_type": "markdown",
147 | "metadata": {
148 | "slideshow": {
149 | "slide_type": "subslide"
150 | }
151 | },
152 | "source": [
153 | "Based off of this we could want to integrate along the boundary such that\n",
154 | "$$\\begin{aligned}\n",
155 | " F^n_{1/2} &= \\frac{1}{\\Delta t} \\int^{t_{n+1}}_{t_n} u q(a, t) dt \\\\\n",
156 | " &=\\frac{u}{\\Delta t} \\int^{t_{n+1}}_{t_n} g_a(t) dt\n",
157 | "\\end{aligned}$$\n",
158 | "or\n",
159 | "$$\n",
160 | " F^n_{1/2} = u g_a(t_n + \\Delta t / 2)\n",
161 | "$$\n",
162 | "as an approximation."
163 | ]
164 | },
165 | {
166 | "cell_type": "markdown",
167 | "metadata": {
168 | "slideshow": {
169 | "slide_type": "subslide"
170 | }
171 | },
172 | "source": [
173 | "One draw back to the flux integration approach is that we may need to have fluxes also specified further from the boundary for larger stencil methods."
174 | ]
175 | },
176 | {
177 | "cell_type": "markdown",
178 | "metadata": {
179 | "slideshow": {
180 | "slide_type": "subslide"
181 | }
182 | },
183 | "source": [
184 | "What if instead we tried to find a way to directly specify the values for $Q$ in the ghost cells? This allows the method that we are using interior to the domain to be applied everywhere where we have two cells sharing a boundary. For instance\n",
185 | "$$\n",
186 | " Q^n_0 = \\frac{1}{\\Delta x} \\int^a_{a - \\Delta x} q(x, t_n) dx.\n",
187 | "$$\n",
188 | "The drawback here is that we do not know in general $q(x, t_n)$."
189 | ]
190 | },
191 | {
192 | "cell_type": "markdown",
193 | "metadata": {
194 | "slideshow": {
195 | "slide_type": "subslide"
196 | }
197 | },
198 | "source": [
199 | "Instead we can use the fact we know the characteristics as they head into the domain. We could for instance use\n",
200 | "$$\\begin{aligned}\n",
201 | " q(x, t_n) &= q(a, t_n + (a -x) / u)\\\\\n",
202 | " &= g_a(t_n + (a - x) / u)\n",
203 | "\\end{aligned}$$\n",
204 | "leading to\n",
205 | "$$\\begin{aligned}\n",
206 | " Q^n_0 &= \\frac{1}{\\Delta x} \\int^a_{a - \\Delta x} g_a\\left( t_n + \\frac{a - x}{u} \\right ) dx \\\\\n",
207 | " &= \\frac{u}{\\Delta x} \\int^{t_n + \\Delta x / u}_{t_n} g_a(\\tau) d\\tau\n",
208 | "\\end{aligned}$$\n",
209 | "We can again approximate these integrals with higher-order approximations."
210 | ]
211 | },
212 | {
213 | "cell_type": "markdown",
214 | "metadata": {
215 | "slideshow": {
216 | "slide_type": "slide"
217 | }
218 | },
219 | "source": [
220 | "## Example: Acoustics\n",
221 | "\n",
222 | "Systems of equations are slightly more complex to specify BCs for but follow a similar pattern. There are also special types of BCs that can arise for systems for which we will discuss. We will use the linear acoustics equations for this discussion."
223 | ]
224 | },
225 | {
226 | "cell_type": "markdown",
227 | "metadata": {
228 | "slideshow": {
229 | "slide_type": "subslide"
230 | }
231 | },
232 | "source": [
233 | "Recall that the acoustics equations linearized around a state where $u=0$ takes the form\n",
234 | "$$\\begin{aligned}\n",
235 | " &p_t + K_0 u_x = 0 \\\\\n",
236 | " \\rho_0 &u_t + p_x = 0\n",
237 | "\\end{aligned}$$\n",
238 | "and has characteristic variables\n",
239 | "$$\\begin{aligned}\n",
240 | " w^1(x,t) &= \\frac{1}{2 Z_0} (-p + Z_0 u) \\\\\n",
241 | " w^2(x,t) &= \\frac{1}{2 Z_0} (p + Z_0 u)\n",
242 | "\\end{aligned}$$"
243 | ]
244 | },
245 | {
246 | "cell_type": "markdown",
247 | "metadata": {
248 | "slideshow": {
249 | "slide_type": "subslide"
250 | }
251 | },
252 | "source": [
253 | "### Non-Reflecting Boundary Conditions\n",
254 | "\n",
255 | "**Non-reflecting boundary conditions**, also called **absorbing boundary conditions**, are useful when you would like to have waves that leave a finite domain to not impact what is going on interior to the domain. One good example of this is when you want an infinite domain, such as the case with a Cauchy problem, but of course cannot represent this in a numerical example. The non-reflecting boundary conditions will preserve the steady state solution that would evolve between say waves moving in opposite directions. Let us study this in the context of the acoustics equations."
256 | ]
257 | },
258 | {
259 | "cell_type": "markdown",
260 | "metadata": {
261 | "slideshow": {
262 | "slide_type": "subslide"
263 | }
264 | },
265 | "source": [
266 | "With Godunov-type methods that solve a Riemann problem it turns out that zero-order extrapolation works well as non-reflecting boundary conditions. One way to see that this is indeed a good idea is to consider the update formulas in terms of the characteristic variables:\n",
267 | "$$\n",
268 | " W^1 = \\frac{-Q^1 + Z_0 Q^2}{2 Z_0} \\\\\n",
269 | " W^2 = \\frac{Q^1 + Z_0 Q^2}{2 Z_0}.\n",
270 | "$$\n",
271 | "This separation into characteristic fields then has the same properties as the scalar advection case. This also leads to the conclusion that\n",
272 | "$$\n",
273 | " Q^n_0 = Q^n_1 \\quad \\quad Q^n_{-1} = Q^n_1.\n",
274 | "$$\n",
275 | "Note that this causes the gradient to be zero and therefore the flux."
276 | ]
277 | },
278 | {
279 | "cell_type": "markdown",
280 | "metadata": {
281 | "slideshow": {
282 | "slide_type": "subslide"
283 | }
284 | },
285 | "source": [
286 | "### Incoming Waves\n",
287 | "\n",
288 | "Say we want to impose the boundary condition\n",
289 | "$$\n",
290 | " w^2(a, t) = \\sin(\\omega t)\n",
291 | "$$\n",
292 | "without any reflection of waves hitting this boundary. Decomposing $Q_1$ into the characteristic variables such that\n",
293 | "$$\n",
294 | " Q_1 = W^1_1 r^1 + W^2_1 r^2\n",
295 | "$$\n",
296 | "then the ghost cell should be set to\n",
297 | "$$\n",
298 | " Q_0 = W^1_1 r^1 + \\sin(\\omega(t_n + \\Delta x / 2 c_0)) r^2.\n",
299 | "$$"
300 | ]
301 | },
302 | {
303 | "cell_type": "markdown",
304 | "metadata": {
305 | "slideshow": {
306 | "slide_type": "subslide"
307 | }
308 | },
309 | "source": [
310 | "If we want to generalize this to a system of equations with the boundary condition of $g_a(t)$ then we can also write\n",
311 | "$$\n",
312 | " Q_0 = Q_1 + \\left [g_a(t_n + \\Delta x / 2 \\lambda^j) - W^j_1\\right ] r^j.\n",
313 | "$$"
314 | ]
315 | },
316 | {
317 | "cell_type": "markdown",
318 | "metadata": {
319 | "slideshow": {
320 | "slide_type": "subslide"
321 | }
322 | },
323 | "source": [
324 | "### Solid Walls\n",
325 | "\n",
326 | "A particular type of boundary condition comes up often in fluid dynamics, that of a solid wall. If we consider a tube of gas that has a wall at one end we would expect a sound wave to reflect off of the end of the tube with the wall and reverse its direction. The effective solid wall boundary condition should be then\n",
327 | "$$\n",
328 | " u(a, t) = 0.\n",
329 | "$$"
330 | ]
331 | },
332 | {
333 | "cell_type": "markdown",
334 | "metadata": {
335 | "slideshow": {
336 | "slide_type": "subslide"
337 | }
338 | },
339 | "source": [
340 | "The key to enforcing a wall boundary condition is to observe that if we set the ghost cell value to an equivalent value for the pressure but an opposite $u$ that this will satisfy the above condition. In other words\n",
341 | "$$\n",
342 | " p^0(a - \\xi) = p^0(a + \\xi) \\\\\n",
343 | " u^0(a - \\xi) = -u^0(a + \\xi)\n",
344 | "$$"
345 | ]
346 | },
347 | {
348 | "cell_type": "markdown",
349 | "metadata": {
350 | "slideshow": {
351 | "slide_type": "subslide"
352 | }
353 | },
354 | "source": [
355 | "This then suggests that we set the ghost cells to\n",
356 | "$$\n",
357 | " Q_0 = \\begin{bmatrix} p_0 \\\\ u_0 \\end{bmatrix} = \\begin{bmatrix} p_1 \\\\ -u_1 \\end{bmatrix} \\\\\n",
358 | " Q_{-1} = \\begin{bmatrix} p_{-1} \\\\ u_{-1} \\end{bmatrix} = \\begin{bmatrix} p_2 \\\\ -u_2 \\end{bmatrix}\n",
359 | "$$"
360 | ]
361 | },
362 | {
363 | "cell_type": "markdown",
364 | "metadata": {
365 | "slideshow": {
366 | "slide_type": "subslide"
367 | }
368 | },
369 | "source": [
370 | "### Oscillating Walls\n",
371 | "\n",
372 | "Instead of a solid wall we may want to specify a wall that is oscillating. This could represent a source of acoustic waves, such as a speaker. Here we will only consider small amplitude motions."
373 | ]
374 | },
375 | {
376 | "cell_type": "markdown",
377 | "metadata": {
378 | "slideshow": {
379 | "slide_type": "subslide"
380 | }
381 | },
382 | "source": [
383 | "Consider again the fixed domain $x \\in [a, b]$ with the boundary condition\n",
384 | "$$\n",
385 | " u(a, t) = U(t).\n",
386 | "$$\n",
387 | "Note that this will degenerate into our solid wall case if $U(t) = 0$."
388 | ]
389 | },
390 | {
391 | "cell_type": "markdown",
392 | "metadata": {
393 | "slideshow": {
394 | "slide_type": "subslide"
395 | }
396 | },
397 | "source": [
398 | "Consider a single frequency oscillation prescribed by\n",
399 | "$$\n",
400 | " U(t) = \\epsilon \\sin(\\omega t) \\quad \\epsilon \\ll 1.\n",
401 | "$$\n",
402 | "Using what we had from before to prescribe the boundary condition we could then specify\n",
403 | "$$\n",
404 | " Q_0 = \\begin{bmatrix} p_0 \\\\ u_0 \\end{bmatrix} = \\begin{bmatrix} p_1 \\\\ 2 U(t_n) - u_1 \\end{bmatrix} \\\\\n",
405 | " Q_{-1} = \\begin{bmatrix} p_{-1} \\\\ u_{-1} \\end{bmatrix} = \\begin{bmatrix} p_2 \\\\ 2 U(t_n)-u_2 \\end{bmatrix}\n",
406 | "$$"
407 | ]
408 | },
409 | {
410 | "cell_type": "markdown",
411 | "metadata": {
412 | "slideshow": {
413 | "slide_type": "slide"
414 | }
415 | },
416 | "source": [
417 | "## Periodic Boundary Conditions\n",
418 | "\n",
419 | "Last but not least we also have periodic BCs to cover. This is perhaps the easiest of the BCs to specify where with our previous definitions set\n",
420 | "$$\n",
421 | " Q^n_{-1} = Q^n_{N-1} \\quad Q^n_0 = Q^n_N \\quad Q^n_{N+1} = Q^n_1 \\quad Q^n_{N+2} Q^n_2.\n",
422 | "$$"
423 | ]
424 | }
425 | ],
426 | "metadata": {
427 | "celltoolbar": "Slideshow",
428 | "kernelspec": {
429 | "display_name": "Python 3",
430 | "language": "python",
431 | "name": "python3"
432 | },
433 | "language_info": {
434 | "codemirror_mode": {
435 | "name": "ipython",
436 | "version": 3
437 | },
438 | "file_extension": ".py",
439 | "mimetype": "text/x-python",
440 | "name": "python",
441 | "nbconvert_exporter": "python",
442 | "pygments_lexer": "ipython3",
443 | "version": "3.9.8"
444 | }
445 | },
446 | "nbformat": 4,
447 | "nbformat_minor": 2
448 | }
449 |
--------------------------------------------------------------------------------
/05_convergence.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "skip"
8 | }
9 | },
10 | "source": [
11 | "\n",
12 | " \n",
13 | " | Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli | \n",
14 | "
"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "%matplotlib inline\n",
24 | "\n",
25 | "import numpy\n",
26 | "import matplotlib.pyplot as plt\n",
27 | "\n",
28 | "from clawpack import pyclaw\n",
29 | "from clawpack import riemann"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {
35 | "slideshow": {
36 | "slide_type": "slide"
37 | }
38 | },
39 | "source": [
40 | "# Convergence, Accuracy, and Stability"
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "metadata": {
46 | "slideshow": {
47 | "slide_type": "subslide"
48 | }
49 | },
50 | "source": [
51 | "For real world problems in science and engineering it is often difficult to find true solutions of any complexity (or at all). Instead we rely on a process called **Verification and Validation** or **V&V**. This refers to a two step process rougly described by the following.\n",
52 | " - **Verification** is the theoretical analysis including convergence and accuracy showing that a chosen numerical method performs as expected. \n",
53 | " - **Validation** is the process of comparing the numerical solution obtained from a numerical method on a test problem, either analytical or observed or experimental data.\n",
54 | " \n",
55 | "We will concentrate on the former but the entire process V&V is important."
56 | ]
57 | },
58 | {
59 | "cell_type": "markdown",
60 | "metadata": {
61 | "slideshow": {
62 | "slide_type": "slide"
63 | }
64 | },
65 | "source": [
66 | "## Convergence\n",
67 | "\n",
68 | "The first step in our discussion is to establish a form of error. For finite differences the point-wise values are often used and differenced from the true point-wise values. For finite volume methods it is much more natural to use cell-wise averages."
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {
74 | "slideshow": {
75 | "slide_type": "subslide"
76 | }
77 | },
78 | "source": [
79 | "Let $q(x, t_n)$ be the true solution evaluated at time $t_n$. Define\n",
80 | "$$\n",
81 | " q^n_i = \\frac{1}{\\Delta x} \\int_{\\mathcal{C}_i} q(x, t_n) dx\n",
82 | "$$\n",
83 | "as the exact cell-average then. Note that for q(x, t_n) sufficiently smooth the point-wise evaluation at cell centers and the cell-averages will will agree to $\\mathcal{O}(\\Delta x^2)$."
84 | ]
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {
89 | "slideshow": {
90 | "slide_type": "subslide"
91 | }
92 | },
93 | "source": [
94 | "Now define the global error as\n",
95 | "$$\n",
96 | " E^N = Q^N - q^N\n",
97 | "$$\n",
98 | "where our finite final time $T$ is defined by $T = N \\Delta t$. Note that as $\\Delta t \\rightarrow 0$ that $N \\rightarrow \\infty$."
99 | ]
100 | },
101 | {
102 | "cell_type": "markdown",
103 | "metadata": {
104 | "slideshow": {
105 | "slide_type": "subslide"
106 | }
107 | },
108 | "source": [
109 | "Often times we will also assume that there is a fixed relationship between $\\Delta x$ and $\\Delta t$, such as the CFL condition, to simplify our analysis."
110 | ]
111 | },
112 | {
113 | "cell_type": "markdown",
114 | "metadata": {
115 | "slideshow": {
116 | "slide_type": "subslide"
117 | }
118 | },
119 | "source": [
120 | "### Norms\n",
121 | "\n",
122 | "Next up is a choice of norms. We of course can rely on the $p$-norms\n",
123 | "$$\n",
124 | " ||E||_p = \\left(\\Delta x \\sum^\\infty_{i=-\\infty} |E_i|^p \\right )^{1/p}\n",
125 | "$$\n",
126 | "for vectors and\n",
127 | "$$\n",
128 | " ||E||_p = \\left( \\int^\\infty_{i=-\\infty} |E(x)|^p dx \\right )^{1/p}\n",
129 | "$$\n",
130 | "for functions.\n",
131 | "\n",
132 | "The $p=1$ norm is of particular for conservation laws as integrals of the solution itself are often of interest."
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "metadata": {
138 | "slideshow": {
139 | "slide_type": "subslide"
140 | }
141 | },
142 | "source": [
143 | "Now that we have our basic definitions we can define convergence.\n",
144 | "\n",
145 | "A method is **convergent** at time $T$ in the norm $||\\cdot||$ if \n",
146 | "$$\n",
147 | " \\lim_{\\Delta t \\rightarrow 0, N \\Delta t = T} ||E^N|| = 0.\n",
148 | "$$\n",
149 | "\n",
150 | "A method is **accurate of order s** if\n",
151 | "$$\n",
152 | " ||E^N|| = \\mathcal{O}(\\Delta t^s) \\quad \\Delta t \\rightarrow 0.\n",
153 | "$$"
154 | ]
155 | },
156 | {
157 | "cell_type": "markdown",
158 | "metadata": {
159 | "slideshow": {
160 | "slide_type": "subslide"
161 | }
162 | },
163 | "source": [
164 | "Note that if $q(x,t)$ is smooth we could also define point-wise convergence. However we already know that hypernbolic PDEs can contain discontinuities and we cannot expect convergence in the max norm. There are many other caveats that discontinuities in our solutions will provide and we will talk about them as they arise."
165 | ]
166 | },
167 | {
168 | "cell_type": "markdown",
169 | "metadata": {
170 | "slideshow": {
171 | "slide_type": "slide"
172 | }
173 | },
174 | "source": [
175 | "## One-Step and Local Truncation Errors\n",
176 | "\n",
177 | "Almost always it is very difficult to directly prove convergence. Instead we often show two properties of a method:\n",
178 | "\n",
179 | "1. The method is **consistent** with the original equation. This is the same as analysis on error produced in one step of the method or the local error.\n",
180 | "1. The method is **stable**. Errors produced in previous time steps do not grow catastrophically and therefore the global error is directly dependent on local errors.\n",
181 | "\n",
182 | "The **fundamental theorem of numerical methods** implies that if a method is both consistent and stable that it is convergence. This is sometimes called the Lax equivalence theorem or Dahlquist's equivalence theorem, for PDEs and ODEs respectively."
183 | ]
184 | },
185 | {
186 | "cell_type": "markdown",
187 | "metadata": {
188 | "slideshow": {
189 | "slide_type": "subslide"
190 | }
191 | },
192 | "source": [
193 | "An explicit, one-step numerical method can be written as\n",
194 | "$$\n",
195 | " Q^{n+1}_i = \\mathcal{N}(Q^n_i)\n",
196 | "$$\n",
197 | "Note that $\\mathcal{N}(\\cdot)$ can be multi-stage or non-linear but fundamentally requires only the currently known time to get the next time step."
198 | ]
199 | },
200 | {
201 | "cell_type": "markdown",
202 | "metadata": {
203 | "slideshow": {
204 | "slide_type": "subslide"
205 | }
206 | },
207 | "source": [
208 | "The **one-step error** can then be defined as\n",
209 | "$$\n",
210 | " \\widetilde{\\tau}^n = \\mathcal{N}(q^n) - q^{n+1}\n",
211 | "$$\n",
212 | "Notice that the method is receiving EXACT data to produce the next time step in this case.\n",
213 | "\n",
214 | "Instead we can also define the **local truncation error**, or LTE, as\n",
215 | "$$\n",
216 | " \\tau^n = \\frac{1}{\\Delta t} [\\mathcal{N}(q^n) - q^{n+1}).\n",
217 | "$$\n",
218 | "Here we have purposefully related the one-step to the local truncation error making explicit the division by $\\Delta t$. LTE will end up being more useful as it is directly related to the global error."
219 | ]
220 | },
221 | {
222 | "cell_type": "markdown",
223 | "metadata": {
224 | "slideshow": {
225 | "slide_type": "subslide"
226 | }
227 | },
228 | "source": [
229 | "LTE is also important as it allows us define consistency at this point. A **consistent** method is one for which\n",
230 | "$$\n",
231 | " \\tau^n \\rightarrow 0 \\text{ as } \\Delta t \\rightarrow 0.\n",
232 | "$$"
233 | ]
234 | },
235 | {
236 | "cell_type": "markdown",
237 | "metadata": {
238 | "slideshow": {
239 | "slide_type": "subslide"
240 | }
241 | },
242 | "source": [
243 | "#### Example: Upwinding\n",
244 | "\n",
245 | "Consider the first-order upwinding method\n",
246 | "$$\n",
247 | " Q^{n+1}_i = Q^n_i - \\frac{u \\Delta t}{\\Delta x}(Q^n_i - Q^n_{i-1})\n",
248 | "$$\n",
249 | "with $u > 0$. Compute the local truncation error, confirming that the method is first-order and therefore consistent."
250 | ]
251 | },
252 | {
253 | "cell_type": "markdown",
254 | "metadata": {
255 | "slideshow": {
256 | "slide_type": "subslide"
257 | }
258 | },
259 | "source": [
260 | "This can simply be computed by plugging in the method into the equation for LTE. First we need the following Taylor series expansions:\n",
261 | "$$\\begin{aligned}\n",
262 | " q^n_{i-1} &= q^n_i - \\Delta x (q^n_i)_x + \\frac{\\Delta x^2}{2} (q^n_i)_{xx} + \\mathcal{O}(\\Delta x^3) \\\\\n",
263 | " q^{n+1}_{i} &= q^n_i + \\Delta t (q^n_i)_t + \\frac{\\Delta t^2}{2} (q^n_i)_{tt} + \\mathcal{O}(\\Delta t^3)\n",
264 | "\\end{aligned}$$\n",
265 | "Now we can finish the LTE computation:\n",
266 | "$$\\begin{aligned}\n",
267 | " \\tau^n &= \\frac{1}{\\Delta t} \\left[q^n_i - \\frac{u \\Delta t}{\\Delta x} (q^n_i - q^n_{i-1}) - q^{n+1}_i \\right ] & & \\\\\n",
268 | " &= \\frac{1}{\\Delta t} \\left \\{ q^n_i - \\frac{u \\Delta t}{\\Delta x} \\left[q^n_i - \\left(q^n_i - \\Delta x (q^n_i)_x + \\frac{\\Delta x^2}{2} (q^n_i)_{xx} + \\mathcal{O}(\\Delta x^3) \\right)\\right] \\right . & & \\text{Taylor Series} \\\\\n",
269 | " & \\left . \\quad \\quad \\quad - \\left(q^n_i + \\Delta t (q^n_i)_t + \\frac{\\Delta t^2}{2} (q^n_i)_{tt} + \\mathcal{O}(\\Delta t^3) \\right) \\right \\} & & \\\\\n",
270 | " &= -[(q^n_i)_t + u (q^n_i)_x] + \\frac{1}{2} \\Delta x u (q^n_i)_{xx} - \\frac{1}{2} \\Delta t (q^n_i)_{tt} + \\mathcal{O}(\\Delta x^2, \\Delta t^2) & & \\text{Simplify}\n",
271 | "\\end{aligned}$$\n",
272 | "The first term is identically zero as it is the equation we are solving leading us to the conclusion that $\\tau^n = \\mathcal{O}(\\Delta x, \\Delta t)$."
273 | ]
274 | },
275 | {
276 | "cell_type": "markdown",
277 | "metadata": {
278 | "slideshow": {
279 | "slide_type": "slide"
280 | }
281 | },
282 | "source": [
283 | "## Stability Theory\n",
284 | "\n",
285 | "Stability theory is concerned with gauranteeing that the local errors made in previous time steps do not catastrophically blow up in future time steps. Here we will study the general concepts and a number of ways to show stability for methods we have already discussed.}"
286 | ]
287 | },
288 | {
289 | "cell_type": "markdown",
290 | "metadata": {
291 | "slideshow": {
292 | "slide_type": "subslide"
293 | }
294 | },
295 | "source": [
296 | "First rewrite the global error as\n",
297 | "$$\n",
298 | " Q^n = q^n + E^n.\n",
299 | "$$\n",
300 | "Now apply the numerical method $\\mathcal{N}(\\cdot)$ to this data so that we have\n",
301 | "$$\n",
302 | " Q^{n+1} = \\mathcal{N}(Q^n) = \\mathcal{N}(q^n + E^n)\n",
303 | "$$\n",
304 | "so that\n",
305 | "$$\\begin{aligned}\n",
306 | " E^{n+1} &= Q^{n+1} - q^{n+1} \\\\\n",
307 | " &= \\mathcal{N}(q^n + E^n) - q^{n+1} \\\\\n",
308 | " &= \\mathcal{N}(q^n + E^n) - \\mathcal{N}(q^n) + \\mathcal{N}(q^n) - q^{n+1} \\\\\n",
309 | " &= [\\mathcal{N}(q^n + E^n) - \\mathcal{N}(q^n)] + \\Delta t \\tau^n.\n",
310 | "\\end{aligned}$$\n",
311 | "Note that this has now separated the global error into two pieces, the error that occured locally represented by the LTE and one based on the previous numerical error."
312 | ]
313 | },
314 | {
315 | "cell_type": "markdown",
316 | "metadata": {
317 | "slideshow": {
318 | "slide_type": "subslide"
319 | }
320 | },
321 | "source": [
322 | "### Contractive Operators\n",
323 | "\n",
324 | "A **contractive operator** is an operator $\\mathcal{N}(\\cdot)$ in some norm that satisfies\n",
325 | "$$\n",
326 | " ||\\mathcal{N}(P) - \\mathcal{N}(Q) || \\leq ||P-Q||\n",
327 | "$$\n",
328 | "for any two grid functions $P$ and $Q$.\n",
329 | "\n",
330 | "If $\\mathcal{N}$ is contractive then the method represented by $\\mathcal{N}$ is also stable in this norm."
331 | ]
332 | },
333 | {
334 | "cell_type": "markdown",
335 | "metadata": {
336 | "slideshow": {
337 | "slide_type": "subslide"
338 | }
339 | },
340 | "source": [
341 | "Let's apply this idea to our case. Let $P = q^n + E^n$ and $Q = q^n$:\n",
342 | "$$\\begin{aligned}\n",
343 | " ||E^{n+1}|| &\\leq ||\\mathcal{N}(q^n + E^n) - \\mathcal{N}(q^n)|| + \\Delta t ||\\tau^n|| \\\\\n",
344 | " & \\leq ||E^n|| + \\Delta t ||\\tau^n||.\n",
345 | "\\end{aligned}$$\n",
346 | "\n",
347 | "Applying this recursively then leads to\n",
348 | "$$\n",
349 | " ||E^n|| \\leq ||E^0|| + \\Delta t \\sum^{N-1}_{n=1} ||\\tau^n||.\n",
350 | "$$"
351 | ]
352 | },
353 | {
354 | "cell_type": "markdown",
355 | "metadata": {
356 | "slideshow": {
357 | "slide_type": "subslide"
358 | }
359 | },
360 | "source": [
361 | "Now suppose that \n",
362 | "$$\n",
363 | " ||\\tau|| \\equiv \\max_{0 \\leq n \\leq N} ||\\tau^n||\n",
364 | "$$\n",
365 | "so that we can then write\n",
366 | "$$\\begin{aligned}\n",
367 | " ||E^N|| &\\leq ||E^0|| + N \\Delta t ||\\tau|| \\\\\n",
368 | " &\\leq ||E^0|| + T ||\\tau||\n",
369 | "\\end{aligned}$$"
370 | ]
371 | },
372 | {
373 | "cell_type": "markdown",
374 | "metadata": {
375 | "slideshow": {
376 | "slide_type": "subslide"
377 | }
378 | },
379 | "source": [
380 | "### Lax-Richtmyer Stability for Linear Methods\n",
381 | "\n",
382 | "We actually can require something slighly weaker as a sufficient condition that $\\mathcal{N}$ is stable. If we have instead\n",
383 | "$$\n",
384 | " ||\\mathcal{N}(P) - \\mathcal{N}(Q) || \\leq (1 + \\alpha \\Delta t) ||P - Q||\n",
385 | "$$\n",
386 | "where $\\alpha$ is a constant indepdent of $\\Delta t$ we can still show convergence."
387 | ]
388 | },
389 | {
390 | "cell_type": "markdown",
391 | "metadata": {
392 | "slideshow": {
393 | "slide_type": "subslide"
394 | }
395 | },
396 | "source": [
397 | "We now have\n",
398 | "$$\n",
399 | " ||E^{n+1}|| \\leq (1 + \\alpha \\Delta t) ||E^n|| + \\Delta t ||\\tau||\n",
400 | "$$\n",
401 | "implying\n",
402 | "$$\\begin{aligned}\n",
403 | " ||E^n|| &\\leq (1+\\alpha \\Delta t)^N ||E^0|| + \\Delta t \\sum^{N-1}_{n=1} (1 + \\alpha \\Delta t)^{N - 1 - n} ||\\tau|| \\\\\n",
404 | " &\\leq e^{\\alpha T} (||E^0|| + T ||\\tau||) \\quad (\\text{for } N\\Delta t = T).\n",
405 | "\\end{aligned}$$"
406 | ]
407 | },
408 | {
409 | "cell_type": "markdown",
410 | "metadata": {
411 | "slideshow": {
412 | "slide_type": "subslide"
413 | }
414 | },
415 | "source": [
416 | "Generally this type of stability if $\\mathcal{N}$ is linear is **Lax-Richtmyer Stability** that can be expressed as\n",
417 | "$$\n",
418 | " ||\\mathcal{N}|| \\leq 1 + \\alpha \\Delta t.\n",
419 | "$$"
420 | ]
421 | },
422 | {
423 | "cell_type": "markdown",
424 | "metadata": {
425 | "slideshow": {
426 | "slide_type": "subslide"
427 | }
428 | },
429 | "source": [
430 | "### 2-Norm Stability and von Neumann Analysis\n",
431 | "\n",
432 | "When a method is again linear we can turn to Fourier analysis to provide an easy means to prove stability. This is the basis of **von Neumann stability**, which we will examine here."
433 | ]
434 | },
435 | {
436 | "cell_type": "markdown",
437 | "metadata": {
438 | "slideshow": {
439 | "slide_type": "subslide"
440 | }
441 | },
442 | "source": [
443 | "Let $Q^n_j$ represent an arbitrary grid function for the Cauchy problem. Suppose that $||Q^n_j||_2 < \\infty$ so that we can express the grid function as\n",
444 | "$$\n",
445 | " Q^n_j = \\frac{1}{\\sqrt{2 \\pi}} \\int^\\infty_{-\\infty} \\widehat{Q}(\\xi) e^{i \\xi j \\Delta x} d\\xi\n",
446 | "$$\n",
447 | "If we apply a LINEAR function $\\mathcal{N}$ to $Q^n_j$ we can find the update\n",
448 | "$$\n",
449 | " Q^{n+1}_j = \\frac{1}{\\sqrt{2 \\pi}} \\int^\\infty_{-\\infty} \\widehat{Q}(\\xi) g(\\xi, \\Delta x, \\Delta t) e^{i \\xi j \\Delta x} d\\xi\n",
450 | "$$\n",
451 | "where $g(\\cdot)$ represents the **amplification factor** for wave number $\\xi$ of the method. We can rewrite this more helpfully as\n",
452 | "$$\n",
453 | " \\widehat{Q}^{n+1}(\\xi) = g(\\xi, \\Delta x, \\Delta t) \\widehat{Q}^n(\\xi).\n",
454 | "$$"
455 | ]
456 | },
457 | {
458 | "cell_type": "markdown",
459 | "metadata": {
460 | "slideshow": {
461 | "slide_type": "subslide"
462 | }
463 | },
464 | "source": [
465 | "Recall that **Parseval's relation** states that\n",
466 | "$$\n",
467 | " ||Q^n||_2 = ||\\widehat{Q}^n||_2\n",
468 | "$$\n",
469 | "where\n",
470 | "$$\n",
471 | " ||Q^n||_2 = \\left (\\Delta x \\sum^\\infty_{j=-\\infty} |Q^n_i|^2 \\right )^{1/2} \\quad \\quad ||\\widehat{Q}^n||_2 = \\left (\\int^\\infty_{j=-\\infty} |\\widehat{Q}^n(\\xi)|^2 d\\xi \\right )^{1/2}\n",
472 | "$$\n",
473 | "This of course implies that if we can show boundedness of the Fourier transform that we have also shown the boundedness of the original function."
474 | ]
475 | },
476 | {
477 | "cell_type": "markdown",
478 | "metadata": {
479 | "slideshow": {
480 | "slide_type": "subslide"
481 | }
482 | },
483 | "source": [
484 | "Turning back to therefore proving the boundedness of $\\widehat{Q}$ then we consider single wave number data of the form\n",
485 | "$$\n",
486 | " Q^n_j = e^{i \\xi j \\Delta x}.\n",
487 | "$$\n",
488 | "As long as $\\xi$ remains arbitrary we can consider the single wave number form of solutions. Therefore, if we can show that the amplification factor from\n",
489 | "$$\n",
490 | " \\widehat{Q}^{n+1}(\\xi) = g(\\xi, \\Delta x, \\Delta t) \\widehat{Q}^n(\\xi)\n",
491 | "$$\n",
492 | "that $|g| \\leq 1$ we have proven what we set out to."
493 | ]
494 | },
495 | {
496 | "cell_type": "markdown",
497 | "metadata": {
498 | "slideshow": {
499 | "slide_type": "subslide"
500 | }
501 | },
502 | "source": [
503 | "#### Example: Upwind\n",
504 | "\n",
505 | "Again consider the upwind method, a linear, explicit, one-step method. Writing the upwind method with $u > 0$ and directly using the Courant number $\\nu$ we have\n",
506 | "$$\\begin{aligned}\n",
507 | " Q^{n+1}_j &= Q^n_j - \\nu (Q^n_j = Q^n_{j - 1}) \\\\\n",
508 | " &= (1 - \\nu) Q^n_j + \\nu Q^n_{j - 1} \\\\\n",
509 | "\\end{aligned}$$\n",
510 | "Plugging $Q^n_j = e^{i \\xi j \\Delta x}$ into the above expression leads to\n",
511 | "$$\\begin{aligned}\n",
512 | " Q^{n+1}_j &= (1 - \\nu) Q^n_j + \\nu Q^n_{j - 1} \\\\\n",
513 | " &= (1 - \\nu) e^{i \\xi j \\Delta x} + \\nu e^{-i \\xi \\Delta x} e^{i \\xi j \\Delta x} \\\\\n",
514 | " &= [(1 - \\nu) + \\nu e^{-i \\xi\\Delta x} ] e^{i \\xi j \\Delta x} \\\\\n",
515 | " &= g(\\xi, \\Delta x, \\Delta t) Q^n_j.\n",
516 | "\\end{aligned}$$"
517 | ]
518 | },
519 | {
520 | "cell_type": "markdown",
521 | "metadata": {
522 | "slideshow": {
523 | "slide_type": "subslide"
524 | }
525 | },
526 | "source": [
527 | "So we know that we have\n",
528 | "$$\n",
529 | " g(\\xi, \\Delta x, \\Delta t) = (1 - \\nu) + \\nu e^{-i \\xi\\Delta x}.\n",
530 | "$$\n",
531 | "Since $-1 \\leq e^{-i \\xi\\Delta x} \\leq 1$ we are not worried about that assuming $-1 \\leq \\nu \\leq 1$. Of course this also holds for the first term and we see that if the CFL condition is statisfied the method is stable."
532 | ]
533 | },
534 | {
535 | "cell_type": "markdown",
536 | "metadata": {
537 | "slideshow": {
538 | "slide_type": "subslide"
539 | }
540 | },
541 | "source": [
542 | "### 1-Norm Stability of the Upwind Method\n",
543 | "\n",
544 | "As mentioned before, the 1-norm is often used for conservation laws, especially in the case of nonlinear PDEs. Again we will consider the upwind in the form\n",
545 | "$$\n",
546 | " Q^{n+1}_i = (1- \\nu) Q^n_i + \\nu Q^n_{i-1}.\n",
547 | "$$"
548 | ]
549 | },
550 | {
551 | "cell_type": "markdown",
552 | "metadata": {
553 | "slideshow": {
554 | "slide_type": "subslide"
555 | }
556 | },
557 | "source": [
558 | "Applying the 1-norm we have\n",
559 | "$$\\begin{aligned}\n",
560 | " ||Q^{n+1}||_1 &= \\Delta x \\sum_i |Q^{n+1}_i| & & \\\\\n",
561 | " &= \\Delta x \\sum_i |(1-\\nu)Q^n_i + \\nu Q^n_{i-1}| & & \\\\\n",
562 | " &\\leq \\Delta x \\sum_i [(1-\\nu) |Q^n_i| + \\nu |Q^n_{i-1}| ] & & \\text{Triangle Inequality} \\\\\n",
563 | " ||Q^{n+1}||_1 &\\leq (1-\\nu) ||Q^n||_1 + \\nu ||Q^n||_1 = ||Q^n||_1 & &\n",
564 | "\\end{aligned}$$\n",
565 | "This only works if $0 \\leq \\nu \\leq 1$."
566 | ]
567 | },
568 | {
569 | "cell_type": "markdown",
570 | "metadata": {
571 | "slideshow": {
572 | "slide_type": "subslide"
573 | }
574 | },
575 | "source": [
576 | "### Total-Variation Stability for Nonlinear Method\n",
577 | "\n",
578 | "Many of the above stability proofs relied on the method being linear. For non-linear methods we turn to our ideas of total variation."
579 | ]
580 | },
581 | {
582 | "cell_type": "markdown",
583 | "metadata": {
584 | "slideshow": {
585 | "slide_type": "subslide"
586 | }
587 | },
588 | "source": [
589 | "A numerical methods is **total-variation bounded** (TVB) if, for any data $Q^0$ with $TV(Q^0) < \\infty$ and time $T$, there is a constant $R > 0$ and $\\Delta t_0 > 0$ s.t.\n",
590 | "$$\n",
591 | " \\text{TV}(Q^n) \\leq R \\quad \\forall n \\Delta t \\leq T \\quad \\text{when} \\Delta t < \\Delta t_0\n",
592 | "$$\n",
593 | "\n",
594 | "In other words we require a uniform bound on the total variation up to a time $T$."
595 | ]
596 | },
597 | {
598 | "cell_type": "markdown",
599 | "metadata": {
600 | "slideshow": {
601 | "slide_type": "subslide"
602 | }
603 | },
604 | "source": [
605 | "We actually require something a bit less strict as we can again use a bound such that\n",
606 | "$$\n",
607 | " \\text{TV}(Q^{n+1}) \\leq (1 + \\alpha \\Delta t) \\text{TV}(Q^n)\n",
608 | "$$\n",
609 | "again for an $\\alpha$ constant independent of $\\Delta t$."
610 | ]
611 | },
612 | {
613 | "cell_type": "markdown",
614 | "metadata": {
615 | "slideshow": {
616 | "slide_type": "slide"
617 | }
618 | },
619 | "source": [
620 | "## Accuracy at Extrema\n",
621 | "\n",
622 | "The TVD methods we have already discussed are sufficient to show stability but not neccesary. We would be better off choosing Lax-Wendroff for instance near smooth extrema. This leads to a number of other methods that attempt to maintain stability but also smooth extrema such as the **esentially nonoscillatory** (ENO) method family."
623 | ]
624 | },
625 | {
626 | "cell_type": "markdown",
627 | "metadata": {
628 | "slideshow": {
629 | "slide_type": "slide"
630 | }
631 | },
632 | "source": [
633 | "## Order of Accuracy is Not Everything\n",
634 | "\n",
635 | "Unfortunately our usual metric of order of accuracy is not always a proper metric for judging a method. In fact a high-order of accuracy method may not be as accurate on a particular grid as a low order method. One example of this is a grid that is aligned such that it exactly solves the method but is first-order. We will now consider other situations where this may also be true."
636 | ]
637 | },
638 | {
639 | "cell_type": "markdown",
640 | "metadata": {
641 | "slideshow": {
642 | "slide_type": "subslide"
643 | }
644 | },
645 | "source": [
646 | "Consider the error expression\n",
647 | "$$\n",
648 | " ||E^N|| = C(\\Delta x)^2 + \\text{higher-order terms}.\n",
649 | "$$\n",
650 | "There's a lot that can go wrong here, for instance $C$ may be large and the higher-order terms may be imporant apart from $\\Delta x \\rightarrow 0$."
651 | ]
652 | },
653 | {
654 | "cell_type": "markdown",
655 | "metadata": {
656 | "slideshow": {
657 | "slide_type": "subslide"
658 | }
659 | },
660 | "source": [
661 | "Here the most important piece that may not adhere to order of accuracy are discontinuities in our solution. We can also show that even given a smooth solution that a limiter method will perform better than a strictly Lax-Wendroff based method."
662 | ]
663 | },
664 | {
665 | "cell_type": "code",
666 | "execution_count": null,
667 | "metadata": {
668 | "slideshow": {
669 | "slide_type": "subslide"
670 | }
671 | },
672 | "outputs": [],
673 | "source": [
674 | "def run_simulation(dx, limiters=[0]):\n",
675 | "\n",
676 | " solver = pyclaw.ClawSolver1D(riemann.advection_1D)\n",
677 | "\n",
678 | " solver.bc_lower[0] = 2\n",
679 | " solver.bc_upper[0] = 2\n",
680 | " solver.limiters = limiters\n",
681 | " solver.order = 2\n",
682 | " solver.cfl_desired = 0.9\n",
683 | "\n",
684 | " mx = 1.0 / dx + 2\n",
685 | " x = pyclaw.Dimension(0.0, 1.0, mx, name='x')\n",
686 | " domain = pyclaw.Domain(x)\n",
687 | " num_eqn = 1\n",
688 | " state = pyclaw.State(domain, num_eqn)\n",
689 | " state.problem_data['u'] = 1.0\n",
690 | "\n",
691 | " xc = domain.grid.x.centers\n",
692 | " beta=100.; x0=0.5; mx=100\n",
693 | " state.q[0,:] = numpy.exp(-beta * (xc-x0)**2) * numpy.sin(80.*xc)\n",
694 | " # beta=200.; x0=0.3; mx=100\n",
695 | " # state.q[0,:] = numpy.exp(-beta * (xc-x0)**2) + (xc>0.6)*(xc<0.8)\n",
696 | "\n",
697 | " claw = pyclaw.Controller()\n",
698 | " claw.solution = pyclaw.Solution(state, domain)\n",
699 | " claw.solver = solver\n",
700 | " claw.tfinal = 2.0\n",
701 | " claw.keep_copy = True\n",
702 | "\n",
703 | " claw.run()\n",
704 | "\n",
705 | " return claw.frames[-1].q\n",
706 | "\n",
707 | "def compute_lax_wendroff(dx):\n",
708 | " return run_simulation(dx, limiters=[0])\n",
709 | "\n",
710 | "def compute_limited(dx, limiters=[4]):\n",
711 | " return run_simulation(dx, limiters=limiters)\n",
712 | "\n",
713 | "def true_solution(dx, t):\n",
714 | "\n",
715 | " mx = 1.0 / dx + 2\n",
716 | " xtrue = numpy.linspace(0.0, 1.0, mx)\n",
717 | " xshift = numpy.mod(xtrue - t, 1.0)\n",
718 | " # x1 = 0.6; x2 = 0.8; beta=200.; x0=0.3\n",
719 | " # return numpy.exp(-beta * (xshift-x0)**2) + (xshift>0.6)*(xshift<0.8)\n",
720 | "\n",
721 | " beta=100.; x0=0.5; mx=100\n",
722 | " return numpy.exp(-beta * (xshift-x0)**2) * numpy.sin(80.*xshift)\n",
723 | " \n",
724 | "plot_solution = False\n",
725 | "\n",
726 | "deltas = numpy.logspace(-1, -4, 8)\n",
727 | "error_lax_L1 = []\n",
728 | "error_mc_L1 = []\n",
729 | "error_lax_max = []\n",
730 | "error_mc_max = []\n",
731 | "for dx in deltas:\n",
732 | " Q = compute_lax_wendroff(dx)\n",
733 | " error_lax_L1.append(numpy.linalg.norm(dx * (Q \n",
734 | " - true_solution(dx, 2.0)), 1))\n",
735 | " error_lax_max.append(numpy.max(Q - true_solution(dx, 2.0)))\n",
736 | " Q = compute_limited(dx)\n",
737 | " error_mc_L1.append(numpy.linalg.norm(dx * (Q\n",
738 | " - true_solution(dx, 2.0)), 1))\n",
739 | " error_mc_max.append(numpy.max(Q - true_solution(dx, 2.0)))\n",
740 | "\n",
741 | "if plot_solution:\n",
742 | " fig, axes = plt.subplots(1, 1)\n",
743 | " x = numpy.linspace(0, 1, 100)\n",
744 | " q = compute_lax_wendroff(x[1]-x[0])[0]\n",
745 | " axes.plot(x, compute_lax_wendroff(x[1]-x[0])[0], 'xr')\n",
746 | " axes.plot(x, compute_limited(x[1] - x[0])[0], 'ob')\n",
747 | " axes.plot(x, true_solution(x[1]-x[0], 2.0), 'k-')\n",
748 | "\n",
749 | "order_C = lambda delta_x, error, order: numpy.exp(numpy.log(error) - order * numpy.log(delta_x))\n",
750 | "\n",
751 | "fig, axes = plt.subplots(1, 2)\n",
752 | "fig.set_figwidth(fig.get_figwidth() * 2)\n",
753 | "\n",
754 | "axes[0].loglog(deltas, error_lax_L1, 'ko-', label=\"Lax-Wendroff\")\n",
755 | "axes[0].loglog(deltas, error_mc_L1, 'ko--', label=\"Limited\")\n",
756 | "axes[0].set_title(\"Error Comparison, $\\ell_1$ Norm\")\n",
757 | "axes[0].set_xlabel(\"$\\Delta x$\")\n",
758 | "axes[0].set_ylabel(\"$||Q - q||_1$\")\n",
759 | "axes[0].loglog(deltas, order_C(deltas[2], error_lax_L1[2], 2.0) * deltas**2.0, 'b', label=\"2nd Order\")\n",
760 | "axes[0].legend()\n",
761 | "\n",
762 | "axes[1].loglog(deltas, error_lax_max, 'ko-', label=\"Lax-Wendroff\")\n",
763 | "axes[1].loglog(deltas, error_mc_max, 'ko--', label=\"Limited\")\n",
764 | "axes[1].set_title(\"Error Comparison, Max Norm\")\n",
765 | "axes[1].set_xlabel(\"$\\Delta x$\")\n",
766 | "axes[1].set_ylabel(\"$||Q - q||_\\infty$\")\n",
767 | "axes[1].loglog(deltas, order_C(deltas[3], error_lax_max[3], 2.0) * deltas**2.0, 'b', label=\"2nd Order\")\n",
768 | "axes[1].legend()\n",
769 | "\n",
770 | "plt.show()"
771 | ]
772 | },
773 | {
774 | "cell_type": "markdown",
775 | "metadata": {
776 | "slideshow": {
777 | "slide_type": "slide"
778 | }
779 | },
780 | "source": [
781 | "## Modified Equations\n",
782 | "\n",
783 | "One way we can start to understand numerical methods is to find the modified equations that equate to the method, i.e. the equation we are actually solving. This is best shown by example."
784 | ]
785 | },
786 | {
787 | "cell_type": "markdown",
788 | "metadata": {
789 | "slideshow": {
790 | "slide_type": "subslide"
791 | }
792 | },
793 | "source": [
794 | "#### Example: The Upwind Method\n",
795 | "\n",
796 | "Again consider the upwind method with $u > 0$ for the advection equation:\n",
797 | "$$\n",
798 | " Q^{n+1}_i = Q^n_i - \\frac{u \\Delta t}{\\Delta x} (Q^n_i - Q^n_{i-1}).\n",
799 | "$$\n",
800 | "\n",
801 | "Now replace the numerical solution with a function $v(x,t)$ that is different from the true solution $q(x,t)$ that instead solves the problem the numerical method is sovling but exactly. Plugging this into our method leads us to\n",
802 | "$$\n",
803 | " v(x, t+ \\Delta t) = v(x,t) - \\frac{u \\Delta t}{\\Delta x} [v(x,t) - v(x - \\Delta x, t)].\n",
804 | "$$"
805 | ]
806 | },
807 | {
808 | "cell_type": "markdown",
809 | "metadata": {
810 | "slideshow": {
811 | "slide_type": "subslide"
812 | }
813 | },
814 | "source": [
815 | "$$\n",
816 | " v(x, t+ \\Delta t) = v(x,t) - \\frac{u \\Delta t}{\\Delta x} [v(x,t) - v(x - \\Delta x, t)].\n",
817 | "$$\n",
818 | "Expanding this expression as a Taylor series leads to\n",
819 | "$$\\begin{aligned}\n",
820 | " 0 &= \\left( v_t + \\frac{\\Delta t}{2} v_{tt} + \\frac{\\Delta t^2}{6} v_{ttt} + \\mathcal{O}(\\Delta t^3) \\right ) + u \\left( v_x - \\frac{\\Delta x}{2} v_{xx} + \\frac{\\Delta x^2}{6} v_{xxx} + \\mathcal{O}(\\Delta x^3) \\right) \\\\\n",
821 | " v_t + u v_x &= \\frac{1}{2} (u \\Delta x v_{xx} - \\Delta t v_{tt} ) - \\frac{1}{6} [u \\Delta x^2 v_{xxx} + \\Delta t^2 v_{ttt} ] + \\mathcal{O}(\\Delta x^3, \\Delta t^3).\n",
822 | "\\end{aligned}$$\n",
823 | "This PDE satisfies the original advection equation plus a number of extra terms. For instance we see that the upwind method seems to solve the advection equation plus another wave equation dependent on $u$ and $\\Delta t$ and $\\Delta x$. The second order error terms are dispersive in nature."
824 | ]
825 | },
826 | {
827 | "cell_type": "markdown",
828 | "metadata": {
829 | "slideshow": {
830 | "slide_type": "subslide"
831 | }
832 | },
833 | "source": [
834 | "The true power of modified equation analysis is that we can interpret the error as the left-over terms as mentioned above. We can also extend this analysis by replacing the terms in the modified equation we have derived using the original equation:\n",
835 | "$$\\begin{aligned}\n",
836 | " v_t + u v_x &= \\frac{1}{2} (u \\Delta x v_{xx} - \\Delta t v_{tt}) \\Rightarrow \\\\\n",
837 | " v_{tt} &= -u v_{xt} + \\frac{1}{2} (u \\Delta x v_{xxt} - \\Delta t v_{ttt}) \\text{ and } \\Rightarrow \\\\\n",
838 | " v_{tx} &= -u v_{xx} + \\frac{1}{2}(u \\Delta x v_{xxx} - \\Delta t v_{ttx}),\n",
839 | "\\end{aligned}$$\n",
840 | "which combined leads to\n",
841 | "$$\n",
842 | " v_{tt} = u^2 v_{xx} + \\mathcal{O}(\\Delta t)\n",
843 | "$$\n",
844 | "which leads to \n",
845 | "$$\n",
846 | " v_t + u v_x = \\frac{u \\Delta x}{2} (1 - \\nu) v_{xx}\n",
847 | "$$"
848 | ]
849 | },
850 | {
851 | "cell_type": "markdown",
852 | "metadata": {
853 | "slideshow": {
854 | "slide_type": "subslide"
855 | }
856 | },
857 | "source": [
858 | "#### Example: Beam-Warming Method\n",
859 | "\n",
860 | "Try and calculate this same modified method for Beam-Warming defined by\n",
861 | "$$\n",
862 | " Q^{n+1}_i = Q^n_i - \\nu (3 Q^n_i - 4 Q^n_{i-1} + Q^n_{i-2}) + \\frac{1}{2} \\nu^2 (Q^n_i- 2 Q^n_{i-1} + Q^n_{i-2})\n",
863 | "$$"
864 | ]
865 | },
866 | {
867 | "cell_type": "markdown",
868 | "metadata": {
869 | "slideshow": {
870 | "slide_type": "subslide"
871 | }
872 | },
873 | "source": [
874 | "The modified equation is\n",
875 | "$$\n",
876 | " v_t + u v_x = \\frac{1}{6} u \\Delta x^2 (2 - 3 \\nu + \\nu^2) v_{xxx}\n",
877 | "$$"
878 | ]
879 | }
880 | ],
881 | "metadata": {
882 | "kernelspec": {
883 | "display_name": "Python 3",
884 | "language": "python",
885 | "name": "python3"
886 | },
887 | "language_info": {
888 | "codemirror_mode": {
889 | "name": "ipython",
890 | "version": 3
891 | },
892 | "file_extension": ".py",
893 | "mimetype": "text/x-python",
894 | "name": "python",
895 | "nbconvert_exporter": "python",
896 | "pygments_lexer": "ipython3",
897 | "version": "3.9.8"
898 | }
899 | },
900 | "nbformat": 4,
901 | "nbformat_minor": 2
902 | }
903 |
--------------------------------------------------------------------------------
/10_balance_laws.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "skip"
8 | }
9 | },
10 | "source": [
11 | "\n",
12 | " \n",
13 | " | Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli | \n",
14 | "
"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "slideshow": {
22 | "slide_type": "skip"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "from __future__ import print_function\n",
28 | "\n",
29 | "%matplotlib inline\n",
30 | "\n",
31 | "import numpy\n",
32 | "import matplotlib.pyplot as plt\n",
33 | "import matplotlib.animation\n",
34 | "\n",
35 | "from IPython.display import HTML\n",
36 | "from clawpack import pyclaw\n",
37 | "from clawpack import riemann"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {
43 | "slideshow": {
44 | "slide_type": "slide"
45 | }
46 | },
47 | "source": [
48 | "# Source Terms and Balance Laws\n",
49 | "\n",
50 | "Up until now we have only considered classical conservation laws. Now we will start to look at methods for solving systems of the form\n",
51 | "$$\n",
52 | " q_t + f(q)_x = \\psi(q),\n",
53 | "$$\n",
54 | "often instead called **balance laws**."
55 | ]
56 | },
57 | {
58 | "cell_type": "markdown",
59 | "metadata": {
60 | "slideshow": {
61 | "slide_type": "subslide"
62 | }
63 | },
64 | "source": [
65 | " - Reacting flow\n",
66 | " - External forcing (gravity)\n",
67 | " - Geometric source terms\n",
68 | " - Higher-order derivatives"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {
74 | "slideshow": {
75 | "slide_type": "slide"
76 | }
77 | },
78 | "source": [
79 | "## Fractional-Step Methods"
80 | ]
81 | },
82 | {
83 | "cell_type": "markdown",
84 | "metadata": {
85 | "slideshow": {
86 | "slide_type": "slide"
87 | }
88 | },
89 | "source": [
90 | "### Example: Advection-Reaction Equation\n",
91 | "\n",
92 | "#### Unsplit Method\n",
93 | "\n",
94 | "#### Fractional-Step Method"
95 | ]
96 | },
97 | {
98 | "cell_type": "markdown",
99 | "metadata": {
100 | "slideshow": {
101 | "slide_type": "slide"
102 | }
103 | },
104 | "source": [
105 | "## General Formulation of Fractional-Step Methods"
106 | ]
107 | },
108 | {
109 | "cell_type": "markdown",
110 | "metadata": {
111 | "slideshow": {
112 | "slide_type": "slide"
113 | }
114 | },
115 | "source": [
116 | "## Strang Splitting"
117 | ]
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {
122 | "slideshow": {
123 | "slide_type": "slide"
124 | }
125 | },
126 | "source": [
127 | "## Accuracy of Splittings"
128 | ]
129 | },
130 | {
131 | "cell_type": "markdown",
132 | "metadata": {
133 | "slideshow": {
134 | "slide_type": "slide"
135 | }
136 | },
137 | "source": [
138 | "## Implicit Methods, Viscous Terms, and Higher-Order Derivatives"
139 | ]
140 | },
141 | {
142 | "cell_type": "markdown",
143 | "metadata": {
144 | "slideshow": {
145 | "slide_type": "slide"
146 | }
147 | },
148 | "source": [
149 | "## Steady-State Problems"
150 | ]
151 | },
152 | {
153 | "cell_type": "markdown",
154 | "metadata": {
155 | "slideshow": {
156 | "slide_type": "slide"
157 | }
158 | },
159 | "source": [
160 | "## Boundary Conditions for Fractional-Step Methods"
161 | ]
162 | },
163 | {
164 | "cell_type": "markdown",
165 | "metadata": {
166 | "slideshow": {
167 | "slide_type": "slide"
168 | }
169 | },
170 | "source": [
171 | "## Stiff and Singular Source Terms"
172 | ]
173 | },
174 | {
175 | "cell_type": "markdown",
176 | "metadata": {
177 | "slideshow": {
178 | "slide_type": "slide"
179 | }
180 | },
181 | "source": [
182 | "## Rankine-Hugoniot Jump Conditions at a Singular Source"
183 | ]
184 | },
185 | {
186 | "cell_type": "markdown",
187 | "metadata": {
188 | "slideshow": {
189 | "slide_type": "slide"
190 | }
191 | },
192 | "source": [
193 | "## Nonlinear Traffic Flow with Sources"
194 | ]
195 | },
196 | {
197 | "cell_type": "markdown",
198 | "metadata": {
199 | "slideshow": {
200 | "slide_type": "slide"
201 | }
202 | },
203 | "source": [
204 | "## Accurate Solution of Quasisteady Problems"
205 | ]
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "metadata": {
210 | "slideshow": {
211 | "slide_type": "slide"
212 | }
213 | },
214 | "source": [
215 | "## Relaxation Systems\n",
216 | "\n",
217 | "### Chapman-Enskog Expansion\n",
218 | "\n",
219 | "### Violation of the Subcharacteristic Condition\n",
220 | "\n",
221 | "### Thermal Relaxation and Isothermal Flow"
222 | ]
223 | },
224 | {
225 | "cell_type": "markdown",
226 | "metadata": {
227 | "slideshow": {
228 | "slide_type": "slide"
229 | }
230 | },
231 | "source": [
232 | "## Relaxation Schemes"
233 | ]
234 | }
235 | ],
236 | "metadata": {
237 | "celltoolbar": "Slideshow",
238 | "kernelspec": {
239 | "display_name": "Python 3",
240 | "language": "python",
241 | "name": "python3"
242 | },
243 | "language_info": {
244 | "codemirror_mode": {
245 | "name": "ipython",
246 | "version": 3
247 | },
248 | "file_extension": ".py",
249 | "mimetype": "text/x-python",
250 | "name": "python",
251 | "nbconvert_exporter": "python",
252 | "pygments_lexer": "ipython3",
253 | "version": "3.9.8"
254 | }
255 | },
256 | "nbformat": 4,
257 | "nbformat_minor": 2
258 | }
259 |
--------------------------------------------------------------------------------
/11_multidimension.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "skip"
8 | }
9 | },
10 | "source": [
11 | "\n",
12 | " \n",
13 | " | Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli | \n",
14 | "
"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "slideshow": {
22 | "slide_type": "skip"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "from __future__ import print_function\n",
28 | "\n",
29 | "%matplotlib inline\n",
30 | "\n",
31 | "import numpy\n",
32 | "import matplotlib.pyplot as plt\n",
33 | "import matplotlib.animation\n",
34 | "\n",
35 | "from IPython.display import HTML\n",
36 | "from clawpack import pyclaw\n",
37 | "from clawpack import riemann"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {
43 | "slideshow": {
44 | "slide_type": "slide"
45 | }
46 | },
47 | "source": [
48 | "# Multidimensional Problems\n",
49 | "\n",
50 | "We now will consider multidimensional hyperbolic PDEs of the form\n",
51 | "$$\n",
52 | " q_t + f(q)_x + g(q)_y = 0\n",
53 | "$$\n",
54 | "in conservation form and in the quasilinear form\n",
55 | "$$\n",
56 | " q_t + A(q, x, y, t) q_x + B(q, x, y, t) q_y = 0.\n",
57 | "$$\n",
58 | "Analogously we have\n",
59 | "$$\n",
60 | " q_t + f(q)_x + g(q)_y + h(q)_z = 0\n",
61 | "$$\n",
62 | "in three dimensions."
63 | ]
64 | },
65 | {
66 | "cell_type": "markdown",
67 | "metadata": {
68 | "slideshow": {
69 | "slide_type": "slide"
70 | }
71 | },
72 | "source": [
73 | "## Derivation of Conservation Laws\n",
74 | "\n",
75 | "Similar to the 1 dimensional case we consider some conserved quantity inside of a spatial domain $\\Omega$ and consider the time change in the quantity inside of the domain. This is commonly written as\n",
76 | "$$\n",
77 | " \\frac{\\text{d}}{\\text{d} t} \\int \\int_\\Omega q(x, y, t) dx dy = \\text{net flux across } \\partial \\Omega\n",
78 | "$$\n",
79 | "where $\\partial \\Omega$ is the boundary of $\\Omega$.\n",
80 | "\n",
81 | "If $f(q)$ is the flux across the boundary in the x-direction with units of per unit length in $t$ and per unit time then we will consider an interval (x_0, y_0) \\times (x_0, y_0 + \\Delta y) over time $\\Delta t$ leading to\n",
82 | "$$\n",
83 | " \\Delta t \\Delta y f(q(x_0, y_0, t))\n",
84 | "$$\n",
85 | "for $\\Delta y$ and $\\Delta t$ sufficiently small. The same follows for the y-direction."
86 | ]
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {
91 | "slideshow": {
92 | "slide_type": "subslide"
93 | }
94 | },
95 | "source": [
96 | "Generalizing these ideas let\n",
97 | "$$\n",
98 | " \\vec{~f}(q) = (f(q), g(q))\n",
99 | "$$\n",
100 | "be the flux vector and\n",
101 | "$$\n",
102 | " \\vec{~n}(s) = (n^x(s), n^y(s))\n",
103 | "$$\n",
104 | "be the outward-pointing unit normal vector to $\\partial \\Omega$ as some point $\\vec{~x}(s) = (x(s), y(s))$ on $\\partial \\Omega$ ($s$ is usually taken to be the arc-length parameterization on $\\partial \\Omega$). Then the flux in the direction of $\\vec{~n}(s)$ is\n",
105 | "$$\n",
106 | " \\vec{~n}(s) \\cdot \\vec{~f}(q(x(s), y(s), t))\n",
107 | "$$\n",
108 | "and therefore we have\n",
109 | "$$\\begin{aligned}\n",
110 | " \\frac{\\text{d}}{\\text{d} t} \\int \\int_\\Omega q(x, y, t) dx dy &= \\text{net flux across } \\partial \\Omega \\\\\n",
111 | " &= - \\int_{\\partial \\Omega} \\vec{~n}(s) \\cdot \\vec{~f}(q) ds \\\\\n",
112 | " &= - \\int \\int_{\\Omega} \\vec{~\\nabla} \\cdot \\vec{~f}(q) dx dy\n",
113 | "\\end{aligned}$$\n",
114 | "where we have assumed that $q$ is smooth in the last step and used the divergence theorem. This of course then leads to\n",
115 | "$$\n",
116 | " \\int \\int_\\Omega [q_t + \\vec{~\\nabla} \\cdot \\vec{~f}(q)] dx dy = 0\n",
117 | "$$\n",
118 | "and therefore the strong form of the conservation law."
119 | ]
120 | },
121 | {
122 | "cell_type": "markdown",
123 | "metadata": {
124 | "slideshow": {
125 | "slide_type": "subslide"
126 | }
127 | },
128 | "source": [
129 | "Simplifying this a bit let's consider a more specific region $\\Omega = (x_{i-1}, x_{i}) \\times (y_{j-1}, y_j)$. Now it's much more clear that we need to integrate the flux $f(q)$ over the faces aligned with $x_{i-1}$ and $x_i$ and the flux $g(q)$ over the faces with $y_{j-1}$ and $y_j$ leading to\n",
130 | "$$\n",
131 | " \\frac{\\text{d}}{\\text{d} t} \\int^{y_j}_{y_{j-1}} \\int^{x_i}_{x_{i-1}} q(x, y, t) dx dy = \\int^{y_j}_{y_{j-1}} (f(q(x_{i-1}, y, t) - f(q(x_i, y, t)) dy + \\int^{x_i}_{x_{i-1}} (g(q(x, y_{j-1}, t) - g(q(x, y_j, t)) dx.\n",
132 | "$$\n",
133 | "Again for smooth situations this can be rewritten using the FTC as the strong form from before."
134 | ]
135 | },
136 | {
137 | "cell_type": "markdown",
138 | "metadata": {
139 | "slideshow": {
140 | "slide_type": "slide"
141 | }
142 | },
143 | "source": [
144 | "## Advection\n",
145 | "\n",
146 | "For advection with possibly variable speeds we have the fluxes\n",
147 | "$$\n",
148 | " f = u(x, y, t) q(x, y, t) \\quad \\text{and} \\quad g = v(x, y, t) q(x, y, t)\n",
149 | "$$\n",
150 | "so that we have\n",
151 | "$$\n",
152 | " q_t + (uq)_x + (vq)_y = 0.\n",
153 | "$$\n",
154 | "This of course simplifies if $u$ and $v$ are independent of space and time so that we know the solution is\n",
155 | "$$\n",
156 | " q(x, y, t) = q(x - u t, y - v t, 0).\n",
157 | "$$"
158 | ]
159 | },
160 | {
161 | "cell_type": "markdown",
162 | "metadata": {
163 | "slideshow": {
164 | "slide_type": "subslide"
165 | }
166 | },
167 | "source": [
168 | "### Acoustics\n",
169 | "\n",
170 | "As an example of a system of linear system of equations let's again consider the acoustics system. We again have perturbations from some rest state defined by $q_0$ such that\n",
171 | "$$\n",
172 | " q_t + f'(q_0) q_x + g'(q_0) q_y = 0\n",
173 | "$$\n",
174 | "where now $q$ is the perturbation to $q_0$. The Jacobians with $u_0 = v_0 = 0$ then are\n",
175 | "$$\n",
176 | " f'(q_0) = \\begin{bmatrix}\n",
177 | " 0 & 1 & 0 \\\\\n",
178 | " P'(\\rho_0) & 0 & 0 \\\\\n",
179 | " 0 & 0 & 0\n",
180 | " \\end{bmatrix} \\quad g'(q_0) = \\begin{bmatrix}\n",
181 | " 0 & 0 & 1 \\\\\n",
182 | " 0 & 0 & 0 \\\\\n",
183 | " P'(\\rho_0) & 0 & 0 \\\\\n",
184 | " \\end{bmatrix}.\n",
185 | "$$\n",
186 | "This system can then be written as\n",
187 | "$$\n",
188 | " q_t + A q_x + B q_y = 0\n",
189 | "$$\n",
190 | "where\n",
191 | "$$\n",
192 | " q = \\begin{bmatrix} p \\\\ u \\\\ v \\end{bmatrix} \\quad\n",
193 | " A = \\begin{bmatrix}\n",
194 | " 0 & K_0 & 0 \\\\\n",
195 | " \\frac{1}{\\rho_0} & 0 & 0 \\\\\n",
196 | " 0 & 0 & 0\n",
197 | " \\end{bmatrix} \\quad B = \\begin{bmatrix}\n",
198 | " 0 & 0 & K_0 \\\\\n",
199 | " 0 & 0 & 0 \\\\\n",
200 | " \\frac{1}{\\rho_0} & 0 & 0 \\\\\n",
201 | " \\end{bmatrix}.\n",
202 | "$$"
203 | ]
204 | },
205 | {
206 | "cell_type": "markdown",
207 | "metadata": {
208 | "slideshow": {
209 | "slide_type": "slide"
210 | }
211 | },
212 | "source": [
213 | "## Hyperbolicity\n",
214 | "\n",
215 | "In multiple spatial dimensions it is not entirely clear how to extend our notion of hyperbolicity to one dimension to multiple. It turns out we need the condition that the matrices $A$ and $B$ are both diagonalizable with real eigenvalues but also that any combination of these matrices have the same condition.\n",
216 | "\n",
217 | "Why might this latter condition be needed?"
218 | ]
219 | },
220 | {
221 | "cell_type": "markdown",
222 | "metadata": {
223 | "slideshow": {
224 | "slide_type": "subslide"
225 | }
226 | },
227 | "source": [
228 | "The critical addition here is that we want wave-like behavior not only in the coordinate aligned directions but in any direction. The other way to look at this is that an affine transformation of the coordinate axes should not change the nature of the problem (by a rotation for instance).\n",
229 | "\n",
230 | "This can be formalized by saying that for any $\\vec{~n}$ that waves should propagate as\n",
231 | "$$\n",
232 | " q(x, y, t) = \\widetilde{q}(\\vec{~n} \\cdot \\vec{~x} - s t).\n",
233 | "$$\n",
234 | "This also requires then that\n",
235 | "$$\n",
236 | " \\widetilde{A} \\widetilde{q}(\\vec{~n} \\cdot \\vec{~x} - s t) = s \\widetilde{q}(\\vec{~n} \\cdot \\vec{~x} - s t)\n",
237 | "$$\n",
238 | "where\n",
239 | "$$\n",
240 | " \\widetilde{A} = \\vec{~n} \\cdot \\vec{~A} = n^x A + n^y B.\n",
241 | "$$"
242 | ]
243 | },
244 | {
245 | "cell_type": "markdown",
246 | "metadata": {
247 | "slideshow": {
248 | "slide_type": "subslide"
249 | }
250 | },
251 | "source": [
252 | "This then leads to the following definition for hyperbolicity:\n",
253 | "\n",
254 | "The constant-coefficient system \n",
255 | "$$\n",
256 | " q_t + A q_x + B q_y = 0\n",
257 | "$$ \n",
258 | "is (strongly) **hyperbolic** if, for every choice of $\\vec{~n}$, the matrix $\\vec{~A} = \\vec{~n} \\cdot \\vec{~A}$ is diagonalizable with real eigenvalues. The quasilinear system \n",
259 | "$$\n",
260 | " q_t + f'(q) q_x + g'(q) q_y = 0\n",
261 | "$$\n",
262 | "is **hyperbolic** in some region of state space if the Jacobian matrix\n",
263 | "$$\n",
264 | " \\widetilde{f}'(q) = \\vec{~n} \\cdot \\vec{~f}(q) = n^x f'(q) + n^y g'(q)\n",
265 | "$$\n",
266 | "is diagonalizable with real eigenvalues for every $\\vec{~n}$, for all $q$ in the region."
267 | ]
268 | },
269 | {
270 | "cell_type": "markdown",
271 | "metadata": {
272 | "slideshow": {
273 | "slide_type": "subslide"
274 | }
275 | },
276 | "source": [
277 | "Let's now check to see that this makes sense. If we know that the matrices are diagonalizable then we know that for a given coordinate system that\n",
278 | "$$\n",
279 | " A = R^x \\Lambda^x (R^x)^{-1} \\quad B = R^y \\Lambda^y (R^y)^{-1}\n",
280 | "$$\n",
281 | "meaning that we cannot simply transform the equations into the characteristic variables. If the eigensystem has the same eigenvectors then we could do this leading to\n",
282 | "$$\n",
283 | " w_t + \\Lambda^x w_x + \\Lambda^y w_y = 0\n",
284 | "$$\n",
285 | "leading to something similar from the 1-dimensional case. Unfortunately this is often not the case."
286 | ]
287 | },
288 | {
289 | "cell_type": "markdown",
290 | "metadata": {
291 | "slideshow": {
292 | "slide_type": "slide"
293 | }
294 | },
295 | "source": [
296 | "## Shallow Water Equations\n",
297 | "\n",
298 | "In two space dimensions the shallow water equations are\n",
299 | "$$\\begin{aligned}\n",
300 | " &h_t + (hu)_x + (hv)_y = 0 \\\\\n",
301 | " &(hu)_t + \\left( hu^2 + \\frac{1}{2} g h^2 \\right)_x + (huv)_y = 0 \\\\\n",
302 | " &(hv)_t + (huv)_x + \\left( hv^2 + \\frac{1}{2} g h^2 \\right)_y = 0\n",
303 | "\\end{aligned}$$\n",
304 | "leading to the Jacobians\n",
305 | "$$\n",
306 | " f'(q) = \\begin{bmatrix}\n",
307 | " 0 & 1 & 0 \\\\\n",
308 | " -u^2 + gh & 2u & 0 \\\\\n",
309 | " -uv & v & u\n",
310 | " \\end{bmatrix} \\quad g'(q) = \\begin{bmatrix}\n",
311 | " 0 & 0 & 1 \\\\\n",
312 | " -uv & v & u \\\\\n",
313 | " -v^2 + gh & 0 & 2v\n",
314 | " \\end{bmatrix}.\n",
315 | "$$"
316 | ]
317 | },
318 | {
319 | "cell_type": "markdown",
320 | "metadata": {
321 | "slideshow": {
322 | "slide_type": "subslide"
323 | }
324 | },
325 | "source": [
326 | "The eigenproblem then leads to\n",
327 | "$$\n",
328 | " \\Lambda^x = \\begin{bmatrix}\n",
329 | " u - \\sqrt{gh} & 0 & 0 \\\\\n",
330 | " 0 & u & 0 \\\\\n",
331 | " 0 & 0 & u + \\sqrt{gh}\n",
332 | " \\end{bmatrix} \\quad \\Lambda^y = \\begin{bmatrix}\n",
333 | " v - \\sqrt{gh} & 0 & 0 \\\\\n",
334 | " 0 & v & 0 \\\\\n",
335 | " 0 & 0 & v + \\sqrt{gh}\n",
336 | " \\end{bmatrix}\n",
337 | "$$\n",
338 | "and\n",
339 | "$$\n",
340 | " R^x = \\begin{bmatrix}\n",
341 | " 1 & 0 & 1 \\\\\n",
342 | " u - \\sqrt{gh} & 0 & u + \\sqrt{gh} \\\\\n",
343 | " v & 1 & v\n",
344 | " \\end{bmatrix} \\quad R^y = \\begin{bmatrix}\n",
345 | " 1 & 0 & 1 \\\\\n",
346 | " u & -1 & u \\\\\n",
347 | " v - \\sqrt{gh} & 0 & v + \\sqrt{gh}\n",
348 | " \\end{bmatrix}\n",
349 | "$$"
350 | ]
351 | },
352 | {
353 | "cell_type": "markdown",
354 | "metadata": {
355 | "slideshow": {
356 | "slide_type": "slide"
357 | }
358 | },
359 | "source": [
360 | "# Numerical Methods for Multiple Dimensions\n",
361 | "\n",
362 | "We now aim to approximate the cell average\n",
363 | "$$\n",
364 | " Q^n_{ij} \\approx \\frac{1}{\\Delta x \\Delta y} \\int^{y_{j+1/2}}_{y_{j-1/2}} \\int^{x_{i+1/2}}_{x_{i-1/2}} q(x, y, t_n) dx dy\n",
365 | "$$"
366 | ]
367 | },
368 | {
369 | "cell_type": "markdown",
370 | "metadata": {
371 | "slideshow": {
372 | "slide_type": "slide"
373 | }
374 | },
375 | "source": [
376 | "## Finite Difference Methods\n",
377 | "\n",
378 | "It can be useful at this juncture to review some of the multi-dimensional methods for finite differences. Here instead of the goal of approximating cell averages we are approximating the point-wise approximations with\n",
379 | "$$\n",
380 | " Q^n_{ij} \\approx q(x_i, y_j, t_n).\n",
381 | "$$"
382 | ]
383 | },
384 | {
385 | "cell_type": "markdown",
386 | "metadata": {
387 | "slideshow": {
388 | "slide_type": "subslide"
389 | }
390 | },
391 | "source": [
392 | "### Taylor-Series Expansions\n",
393 | "\n",
394 | "Taylor-series usually is the start of any analysis for finite difference methods and this is no different. Consider the linear hyperbolic system\n",
395 | "$$\n",
396 | " q_t + A q_x + B q_y = 0.\n",
397 | "$$\n",
398 | "Assuming appropriate smoothness we can derive relationships using the equation itself. The general expression can be rewritten as a recursive operator as\n",
399 | "$$\n",
400 | " \\partial_t^{(j)} q = [ - (A \\partial_x + B \\partial_y )]^{j} q\n",
401 | "$$\n",
402 | "so that for instance we can find the second time derivative as\n",
403 | "$$\n",
404 | " q_{tt} = A^2 q_{xx} + A B q_{yx} + B A q_{xy} + B^2 q_{yy}.\n",
405 | "$$\n",
406 | "Note that in general we can permute the matrices however derivative order can due our assumption of smoothness."
407 | ]
408 | },
409 | {
410 | "cell_type": "markdown",
411 | "metadata": {
412 | "slideshow": {
413 | "slide_type": "subslide"
414 | }
415 | },
416 | "source": [
417 | "$$\n",
418 | " q_{tt} = A^2 q_{xx} + A B q_{yx} + B A q_{xy} + B^2 q_{yy}\n",
419 | "$$\n",
420 | "From here we can build the time derivative as\n",
421 | "$$\\begin{aligned}\n",
422 | " q(x_i, y_j, t_n + \\Delta t) &= q + \\Delta t q_t + \\frac{\\Delta t^2}{2} q_{tt} + \\cdots \\\\\n",
423 | " &= q - \\Delta t (A q_x + B q_y) + \\frac{\\Delta t^2}{2} \\left( A^2 q_{xx} + A B q_{yx} + B A q_{xy} + B^2 q_{yy} \\right) + \\cdots\n",
424 | "\\end{aligned}$$\n",
425 | "This generally holds unless $A$ and $B$ also vary with $x$ and $y$, which then leads to the expression\n",
426 | "$$\n",
427 | " q_{tt} = A (A q_{x})_x + A (B q_{y})_x + B (A q_{x})_y + B (B q_{y})_y\n",
428 | "$$\n",
429 | "instead."
430 | ]
431 | },
432 | {
433 | "cell_type": "markdown",
434 | "metadata": {
435 | "slideshow": {
436 | "slide_type": "subslide"
437 | }
438 | },
439 | "source": [
440 | "### The Lax-Wendroff Method\n",
441 | "\n",
442 | "We can now take this expression and using centered finite differences discretize the derivatives. The trickier now though is that we have cross-derivative terms. For the second derivatives we have the common centered difference of\n",
443 | "$$\n",
444 | " q_{yy} = \\frac{1}{\\Delta y^2} (Q^n_{i,j-1} - 2 Q^n_{ij} + Q^n_{i,j+1}).\n",
445 | "$$\n",
446 | "For the cross-derivatives we then have\n",
447 | "$$\n",
448 | " q_{xy} = q_{yx} \\approx \\frac{1}{4 \\Delta x \\Delta y} [(Q^n_{i+1,j+1} - Q^n_{i-1, j+1}) - (Q^n_{i+1,j-1} - Q^n_{i-1, j-1})]\n",
449 | "$$\n",
450 | "that are centered derivatives applied in each directions. This leads to the final approximation of\n",
451 | "$$\\begin{aligned}\n",
452 | " Q^{n+1}_{ij} &= Q^n_{ij} - \\frac{\\Delta t}{2 \\Delta x} A (Q^n_{i+1,j} - Q^n_{i-1, j}) - \\frac{\\Delta t}{2 \\Delta y} B (Q^n_{i, j+1} - Q^n_{i, j-1}) \\\\\n",
453 | " &\\quad+ \\frac{\\Delta t^2}{2 \\Delta x^2} A^2 (Q^n_{i+1,j} - 2 Q^n_{ij} + Q^n_{i-1, j}) + \\frac{\\Delta t^2}{2 \\Delta y^2} B^2 (Q^n_{i,j+1} - 2 Q^n_{ij} + Q^n_{i,j-1}) \\\\\n",
454 | " &\\quad+ \\frac{\\Delta t^2}{8 \\Delta x \\Delta y} (AB + BA) [(Q^n_{i+1,j+1} - Q^n_{i-1, j+1}) - (Q^n_{i+1,j-1} - Q^n_{i-1, j-1})]\n",
455 | "\\end{aligned}$$"
456 | ]
457 | },
458 | {
459 | "cell_type": "markdown",
460 | "metadata": {
461 | "slideshow": {
462 | "slide_type": "slide"
463 | }
464 | },
465 | "source": [
466 | "## Finite Volume Methods\n",
467 | "\n",
468 | "As we used the Lax-Wendroff method before to create a second-order accurate finite volume method we will do the same here. Instead of following directly though we will immediately introduce our Riemann problem machinery and limiting to avoid the dispersion issues we usually see Lax-Wendroff method. Before moving on however we will look at some other alternatives before looking delving into this."
469 | ]
470 | },
471 | {
472 | "cell_type": "markdown",
473 | "metadata": {
474 | "slideshow": {
475 | "slide_type": "subslide"
476 | }
477 | },
478 | "source": [
479 | "### Fully Discrete Methods\n",
480 | "\n",
481 | "Fully-discrete methods, such as flux-differencing forms of Lax-Wendroff, define a flux across each grid cell edge and use this to compute the method updates. Note that we still need to provide limited fluxes in order to avoid oscillatory solutions."
482 | ]
483 | },
484 | {
485 | "cell_type": "markdown",
486 | "metadata": {
487 | "slideshow": {
488 | "slide_type": "subslide"
489 | }
490 | },
491 | "source": [
492 | "#### Flux-Differencing Approaches\n",
493 | "\n",
494 | "Let's return to the flux versions of our conservation law (the nonlinear one) and consider a rectangular cell \n",
495 | "$$\n",
496 | " \\mathcal{C}_{ij} = [x_{i-1/2}, x_{i+1/2}] \\times [y_{j-1/2}, y_{j+1/2}] = [x_{i-1/2}, x_{i-1/2} + \\Delta x] \\times [y_{j-1/2}, y_{j-1/2} + \\Delta y].\n",
497 | "$$\n",
498 | "Integrating around the edges of this cell we have\n",
499 | "$$\\begin{aligned}\n",
500 | "\\frac{\\text{d}}{\\text{d}t} \\int\\int_{\\mathcal{C}_{ij}} q(x, y, t) dx dy &= \\int^{y_{j+1/2}}_{y_{j-1/2}} f(q(x_{i+1/2}, y, t)) dy - \\int^{y_{j+1/2}}_{y_{j-1/2}} f(q(x_{i-1/2}, y, t)) dy \\\\\n",
501 | "&\\quad \\int^{x_{i+1/2}}_{x_{i-1/2}} g(q(x, y_{j+1/2}, t)) dx - \\int^{x_{i+1/2}}_{x_{i-1/2}} g(q(x, y_{j-1/2}, t)) dx.\n",
502 | "\\end{aligned}$$\n",
503 | "\n",
504 | "Integrating in time and dividing by the cell area we then are lead to\n",
505 | "$$\n",
506 | " Q^{n+1}_{ij} = Q^n_{ij} - \\frac{\\Delta t}{\\Delta x} [F^n_{i-1/2,j} - F^n_{i+1/2,j}] - \\frac{\\Delta t}{\\Delta y} [G^n_{i,j-1/2} - G^n_{i,j+1/2}]\n",
507 | "$$\n",
508 | "where\n",
509 | "$$\\begin{aligned}\n",
510 | " F^n_{i-1/2,j} &\\approx \\frac{1}{\\Delta t \\Delta y} \\int^{t_{n+1}}_{t_n} \\int^{y_{j+1/2}}_{y_{j-1/2}} f(q(x_{i-1/2}, y ,t) dy dt\\\\\n",
511 | " G^n_{i,j-1/2} &\\approx \\frac{1}{\\Delta t \\Delta x} \\int^{t_{n+1}}_{t_n} \\int^{x_{i+1/2}}_{x_{i-1/2}} g(q(x, y_{j-1/2} ,t) dx dt.\n",
512 | "\\end{aligned}$$"
513 | ]
514 | },
515 | {
516 | "cell_type": "markdown",
517 | "metadata": {
518 | "slideshow": {
519 | "slide_type": "subslide"
520 | }
521 | },
522 | "source": [
523 | "For the simpler case of a linear system we can also rewrite the Taylor expansion from before as\n",
524 | "$$\\begin{aligned}\n",
525 | " q(x_i, y_j, t_n + \\Delta t) &= q - \\Delta t \\left(Aq - \\frac{\\Delta t}{2} A^2 q_x - \\frac{\\Delta t}{2} A B q_y \\right)_x \\\\\n",
526 | " &\\quad - \\Delta t \\left(Bq - \\frac{\\Delta t}{2} B^2 q_y - \\frac{\\Delta t}{2} BA q_x \\right)_y + \\cdots\n",
527 | "\\end{aligned}\n",
528 | "$$\n",
529 | "suggesting the following forms of the numerical flux functions\n",
530 | "$$\\begin{aligned}\n",
531 | " F^n_{i-1/2,j} &\\approx A q(x_{i-1/2}, y_j, t_n) - \\frac{\\Delta t}{2} A^2 q_x(x_{i-1/2}, y_j, t_n) - \\frac{\\Delta t}{2} A B q_y (x_{i-1/2}, y_j, t_n)\\\\\n",
532 | " G^n_{i,j-1/2} &\\approx B q(x_i, y_{j-1/2}, t_n) - \\frac{\\Delta t}{2} B^2 q_y(x_i, y_{j-1/2}, t_n) - \\frac{\\Delta t}{2} BA q_y (x_i, y_{j-1/2}, t_n)\n",
533 | "\\end{aligned}$$\n",
534 | "that agree with the integral definition to $\\mathcal{O}(\\Delta t^2)$."
535 | ]
536 | },
537 | {
538 | "cell_type": "markdown",
539 | "metadata": {
540 | "slideshow": {
541 | "slide_type": "subslide"
542 | }
543 | },
544 | "source": [
545 | "We can also write the flux-differencing form of the Lax-Wendroff method for a constant coefficient system as the following:\n",
546 | "$$\\begin{aligned}\n",
547 | " F_{i-1/2, j} &= \\frac{1}{2} A (Q_{i-1,j} + Q_{ij}) - \\frac{\\Delta t}{2 \\Delta x} A^2 (Q_{ij} - Q_{i-1,j}) \\\\\n",
548 | " &\\quad -\\frac{\\Delta t}{8 \\Delta y} AB [(Q_{i,j+1} - Q_{ij}) + Q_{i-1,j+1} - Q_{i-1, j} \\\\\n",
549 | " &\\quad \\quad + (Q_{ij} - Q_{i,j-1}) + (Q_{i-1,j} - Q_{i-1, j-1})] \\\\\n",
550 | " G_{i, j-1/2} &= \\frac{1}{2} B (Q_{i,j-1} + Q_{ij}) - \\frac{\\Delta t}{2 \\Delta y} B^2 (Q_{ij} - Q_{i,j-1}) \\\\\n",
551 | " &\\quad -\\frac{\\Delta t}{8 \\Delta x} BA [(Q_{i+1,j} - Q_{ij}) + Q_{i+1,j-1} - Q_{i, j-1} \\\\\n",
552 | " &\\quad \\quad + (Q_{ij} - Q_{i-1,j}) + (Q_{i,j-1} - Q_{i-1, j-1})] \\\\\n",
553 | "\\end{aligned}$$"
554 | ]
555 | },
556 | {
557 | "cell_type": "markdown",
558 | "metadata": {
559 | "slideshow": {
560 | "slide_type": "subslide"
561 | }
562 | },
563 | "source": [
564 | "#### Godunov's Method\n",
565 | "\n",
566 | "The extension to Godunov's method simply does what we have been doing the entire semester, evaluate the Riemann problem, find the value of $Q$ at the grid cell edge, and evaluate the flux function there\n",
567 | "$$\n",
568 | " F_{i-1/2, j} = f(\\widehat{Q}_{i-1/2, j}) \\quad \\quad G_{i, j-1/2} = g(\\widehat{Q}_{i, j-1/2}).\n",
569 | "$$\n",
570 | "This seems straight forward except that now we have a multidimensional Riemann problem to solve. Instead we often only solve in each direction. In other words we find $\\widehat{Q}_{i-1/2, j}$ from $q_t + f(q)_x = 0$ and $\\widehat{Q}_{i, j-1/2}$ from $q_t + g(q)_y = 0$."
571 | ]
572 | },
573 | {
574 | "cell_type": "markdown",
575 | "metadata": {
576 | "slideshow": {
577 | "slide_type": "subslide"
578 | }
579 | },
580 | "source": [
581 | "If we again consider a linear problem we know that we can as before define\n",
582 | "$$\n",
583 | " A^\\pm = R^x (\\Lambda^x)^\\pm (R^x)^{-1} \\quad \\quad B^\\pm = R^y (\\Lambda^y)^\\pm (R^y)^{-1}\n",
584 | "$$\n",
585 | "that allows us to define our usual fluxes\n",
586 | "$$\n",
587 | " F_{i-1/2, j} = A^+ Q_{i-1,j} + A^- Q_{ij} \\quad \\quad G_{i, j-1/2} = B^+ Q_{i,j-1} + B^- Q_{ij}.\n",
588 | "$$\n",
589 | "This is of course only a first order method."
590 | ]
591 | },
592 | {
593 | "cell_type": "markdown",
594 | "metadata": {
595 | "slideshow": {
596 | "slide_type": "subslide"
597 | }
598 | },
599 | "source": [
600 | "We can also extend the to not only general conservation laws but also add limited corrections easily in our usual notation:\n",
601 | "$$\\begin{aligned}\n",
602 | " Q^{n+1}_{ij} &= Q^n_{ij} - \\frac{\\Delta t}{\\Delta x} \\left (\\mathcal{A}^+\\Delta Q_{i-1/2,j} + \\mathcal{A}^-\\Delta Q_{i+1/2, j} \\right) \\\\\n",
603 | " &\\quad- \\frac{\\Delta t}{\\Delta y} \\left (\\mathcal{B}^+\\Delta Q_{i,j-1/2} + \\mathcal{B}^-\\Delta Q_{i, j+1/2} \\right) \\\\\n",
604 | " &\\quad -\\frac{\\Delta t}{\\Delta x} \\left(\\widetilde{F}_{i+1/2,j} - \\widetilde{F}_{i-1/2,j} \\right ) - \\frac{\\Delta t}{\\Delta y} \\left(\\widetilde{G}_{i,j+1/2} - \\widetilde{G}_{i,j-1/2} \\right )\n",
605 | "\\end{aligned}$$"
606 | ]
607 | },
608 | {
609 | "cell_type": "markdown",
610 | "metadata": {
611 | "slideshow": {
612 | "slide_type": "subslide"
613 | }
614 | },
615 | "source": [
616 | "### Semi-Discrete Approaches\n",
617 | "\n",
618 | "We can also consider semi-discrete, or method-of-lines, discretization where we are instead considering the approximation\n",
619 | "$$\n",
620 | " Q_{ij}(t) = \\int \\int_{\\mathcal{C}_{ij}} q(x, y, t) dx dy\n",
621 | "$$\n",
622 | "leading to \n",
623 | "$$\\begin{aligned}\n",
624 | " F_{i-1/2, j}(Q(t)) &\\approx \\frac{1}{\\Delta y} \\int^{y_{j+1/2}}_{y_{j-1/2}} f(q(x_{i-1/2},y,t)) dy \\\\\n",
625 | " G_{i, j-1/2}(Q(t)) &\\approx \\frac{1}{\\Delta x} \\int^{x_{i+1/2}}_{x_{i-1/2}} g(q(x,y_{j-1/2},t)) dx.\n",
626 | "\\end{aligned}$$"
627 | ]
628 | },
629 | {
630 | "cell_type": "markdown",
631 | "metadata": {
632 | "slideshow": {
633 | "slide_type": "subslide"
634 | }
635 | },
636 | "source": [
637 | "This can also be rewritten in a more familiar, semi-discrete form as\n",
638 | "$$\\begin{aligned}\n",
639 | " \\frac{\\text{d}}{\\text{d} t} Q_{ij}(t) = &-\\frac{1}{\\Delta x} \\left [ F_{i+1/2,j} (Q(t)) - F_{i-1/2, j}(Q(t)) \\right] \\\\\n",
640 | " &-\\frac{1}{\\Delta y} \\left [ G_{i,j+1/2} (Q(t)) - G_{i, j-1/2}(Q(t)) \\right] \\\\\n",
641 | "\\end{aligned}$$"
642 | ]
643 | },
644 | {
645 | "cell_type": "markdown",
646 | "metadata": {
647 | "slideshow": {
648 | "slide_type": "subslide"
649 | }
650 | },
651 | "source": [
652 | "### Dimensional Splitting\n",
653 | "\n",
654 | "The final alternative to what we eventually discuss is simply to use dimensional splitting. The primary idea is to split the different dimensions into sweeps and combine their changes. The basic algorithm for this is to split\n",
655 | "$$\n",
656 | " q_t + A q_x + B q_y = 0\n",
657 | "$$\n",
658 | "into subproblems\n",
659 | "$$\\begin{aligned}\n",
660 | " &x-\\text{sweeps:} \\quad q_t + A q_x = 0 \\\\\n",
661 | " &y-\\text{sweeps:} \\quad q_t + B q_y = 0.\n",
662 | "\\end{aligned}$$"
663 | ]
664 | },
665 | {
666 | "cell_type": "markdown",
667 | "metadata": {
668 | "slideshow": {
669 | "slide_type": "subslide"
670 | }
671 | },
672 | "source": [
673 | "This amount to evolving the function in two steps where\n",
674 | "$$\\begin{aligned}\n",
675 | " Q^*_{ij} &= Q^n_{ij} - \\frac{\\Delta t}{\\Delta x} (F^n_{i+1/2, j} - F^n_{i-1/2,j}) \\\\\n",
676 | " Q^{n+1}_{ij} &= Q^*_{ij} - \\frac{\\Delta t}{\\Delta y} (G^*_{i+1/2, j} - G^*_{i-1/2,j}).\n",
677 | "\\end{aligned}$$\n",
678 | "The primary question those is what error we impose by picking a direction to use first.\n",
679 | "\n",
680 | "This splitting is know as Godunov splitting. We know that we can formally achieve second order convergence with Strang splitting but is this going to work?"
681 | ]
682 | },
683 | {
684 | "cell_type": "markdown",
685 | "metadata": {
686 | "slideshow": {
687 | "slide_type": "slide"
688 | }
689 | },
690 | "source": [
691 | "## Multidimensional Finite Volume Advection Methods\n",
692 | "\n",
693 | "In order to illustrate the ideas of fully multidimensional methods that do not depend on our previous approaches we will focus on the constant coefficient advection equation\n",
694 | "$$\n",
695 | " q_t + u q_x + v q_y = 0\n",
696 | "$$\n",
697 | "as it can provide the basic generalizations needed for our more general discussion."
698 | ]
699 | },
700 | {
701 | "cell_type": "markdown",
702 | "metadata": {
703 | "slideshow": {
704 | "slide_type": "subslide"
705 | }
706 | },
707 | "source": [
708 | "A useful analytical tool (as usual) will be the Taylor series expansion of the solution\n",
709 | "$$\\begin{aligned}\n",
710 | " q(x, y ,t_{n+1}) &= q + \\Delta t q_t + \\frac{\\Delta t^2}{2} q_{tt} + \\cdots \\\\\n",
711 | " &= q - u \\Delta t q_x - v \\Delta t q_y + \\frac{\\Delta t^2}{2} [u^2 q_{xx} + vu q_{xy} + uv q_{yx} + v^2 q_{yy}] + \\cdots\n",
712 | "\\end{aligned}$$\n",
713 | "despite the fact we know the true solution is\n",
714 | "$$\n",
715 | " q(x,y,t) = q(x-ut, y-vt, 0).\n",
716 | "$$"
717 | ]
718 | },
719 | {
720 | "cell_type": "markdown",
721 | "metadata": {
722 | "slideshow": {
723 | "slide_type": "subslide"
724 | }
725 | },
726 | "source": [
727 | "### Donor-Cell Upwind Method\n",
728 | "\n",
729 | "The first and most straight-forward FV method for advection is first-order upwind and can be written as\n",
730 | "$$\n",
731 | " Q^{n+1}_{ij} = Q^n_{ij} - \\frac{\\Delta t}{\\Delta x} [u^+(Q^n_{ij} - Q^n_{i-1,j}) + u^- (Q^n_{i+1,j} - Q^n_{ij})] - \\frac{\\Delta t}{\\Delta y} [v^+(Q^n_{i,j-1} - Q^n_{ij}) + v^- (Q^n_{i,j+1} - Q^n_{ij})].\n",
732 | "$$\n",
733 | "This is method has the fluctuations specified as\n",
734 | "$$\n",
735 | " \\mathcal{A}^\\pm \\Delta Q_{i-1/2,j} = u^\\pm(Q_{ij} - Q_{i-1, j}) \\quad \\mathcal{B}^\\pm \\Delta Q_{i,j-1/2} = v^\\pm(Q_{ij} - Q_{i, j-1}) \n",
736 | "$$\n",
737 | "that agrees with Godunov's method as described before."
738 | ]
739 | },
740 | {
741 | "cell_type": "markdown",
742 | "metadata": {
743 | "slideshow": {
744 | "slide_type": "subslide"
745 | }
746 | },
747 | "source": [
748 | "As we might expect this method can be problematic given that we do not expect that waves that should be moving at some angle to the grid will yield a true CFL stable solution. In fact this method is only stable when\n",
749 | "$$\n",
750 | " \\left | \\frac{u\\Delta t}{\\Delta x}\\right | + \\left | \\frac{v\\Delta t}{\\Delta y}\\right | \\leq 1.\n",
751 | "$$\n",
752 | "Note that this is not simply the maximum by additive greatly reducing the time step we can take depending on the value of $u$ and $v$."
753 | ]
754 | },
755 | {
756 | "cell_type": "markdown",
757 | "metadata": {
758 | "slideshow": {
759 | "slide_type": "subslide"
760 | }
761 | },
762 | "source": [
763 | "### Corner-Transport Upwind Method\n",
764 | "\n",
765 | "Instead of the Donor-Cell method we can fall back to the REA approach and extend it to two dimensions:\n",
766 | "1. Define a piecewise constant function $\\widetilde{q}^n(x, y, t_n)$ with constant value $Q^n_{ij}$ defined over $\\mathcal{C}_{ij}$.\n",
767 | "1. Evolve the full advection equation exactly over $\\Delta t$.\n",
768 | "1. Average the resulting solution $\\widetilde{q}^n(x,y,t_{n+1})$ back onto the grid."
769 | ]
770 | },
771 | {
772 | "cell_type": "markdown",
773 | "metadata": {
774 | "slideshow": {
775 | "slide_type": "subslide"
776 | }
777 | },
778 | "source": [
779 | "We exactly know the approximation that arises from this approximation evolution as\n",
780 | "$$\n",
781 | " \\widetilde{q}^n(x, y, t_{n+1}) = \\widetilde{q}^n(x - u \\Delta t, y - v \\Delta t, t_n).\n",
782 | "$$\n",
783 | "We also therefore know that the piecewise constant representation of the solution to the advection problem is simply shifted by $(u \\Delta t, v \\Delta t)$ so that we have\n",
784 | "$$\\begin{aligned}\n",
785 | " Q^{n+1}_{ij} &= \\frac{1}{\\Delta x \\Delta y} \\int^{x_{i+1/2}}_{x_{i-1/2}} \\int^{y_{j+1/2}}_{y_{j-1/2}} \\widetilde{q}^n(x - u \\Delta t, y - v \\Delta t, t_n) dx dy \\\\\n",
786 | " &= \\frac{1}{\\Delta x \\Delta y} \\int^{x_{i+1/2} - u \\Delta t}_{x_{i-1/2} - u \\Delta t} \\int^{y_{j+1/2} - v \\Delta t}_{y_{j-1/2} - v \\Delta t} \\widetilde{q}^n(x, y, t_n) dx dy\n",
787 | "\\end{aligned}$$\n",
788 | "\n",
789 | "This leads to the final update formula\n",
790 | "$$\\begin{aligned}\n",
791 | " Q^{n+1}_{ij} &= \\frac{1}{\\Delta x}{\\Delta y} \\left[ (\\Delta x - u \\Delta t)(\\Delta y - v \\Delta t) Q^n_{ij} + (\\Delta x - u \\Delta t)( v \\Delta t) Q^n_{i,j-1} \\right . \\\\\n",
792 | " & \\left . \\quad \\quad + (\\Delta y - v \\Delta t)(u \\Delta t) Q^n_{i-1,j} + (u \\Delta t) (v \\Delta t) Q^n_{i-1, j-1}\\right].\n",
793 | "\\end{aligned}$$"
794 | ]
795 | },
796 | {
797 | "cell_type": "markdown",
798 | "metadata": {
799 | "slideshow": {
800 | "slide_type": "subslide"
801 | }
802 | },
803 | "source": [
804 | "### Wave-Propagation Implementation of Corner-Transport\n",
805 | "\n",
806 | "How does this work into our wave-propagation formulation beyond first order? We can actually define correction fluxes as the following\n",
807 | "$$\\begin{aligned}\n",
808 | " &\\widetilde{F}_{i-1/2, j} = -\\frac{\\Delta t}{2 \\Delta y} uv(Q_{i-1,j} - Q_{i-1,j-1}) \\\\\n",
809 | " &\\widetilde{F}_{i+1/2, j} = -\\frac{\\Delta t}{2 \\Delta y} uv(Q_{i,j} - Q_{i,j-1}) \\\\\n",
810 | " &\\widetilde{F}_{i, j-1/2} = -\\frac{\\Delta t}{2 \\Delta y} uv(Q_{i,j-1} - Q_{i-1,j-1}) \\\\\n",
811 | " &\\widetilde{G}_{i, j+1/2} = -\\frac{\\Delta t}{2 \\Delta y} uv(Q_{i,j} - Q_{i-1,j})\n",
812 | "\\end{aligned}$$"
813 | ]
814 | }
815 | ],
816 | "metadata": {
817 | "celltoolbar": "Slideshow",
818 | "kernelspec": {
819 | "display_name": "Python 3",
820 | "language": "python",
821 | "name": "python3"
822 | },
823 | "language_info": {
824 | "codemirror_mode": {
825 | "name": "ipython",
826 | "version": 3
827 | },
828 | "file_extension": ".py",
829 | "mimetype": "text/x-python",
830 | "name": "python",
831 | "nbconvert_exporter": "python",
832 | "pygments_lexer": "ipython3",
833 | "version": "3.9.8"
834 | }
835 | },
836 | "nbformat": 4,
837 | "nbformat_minor": 2
838 | }
839 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Attribution 4.0 International
2 |
3 | =======================================================================
4 |
5 | Creative Commons Corporation ("Creative Commons") is not a law firm and
6 | does not provide legal services or legal advice. Distribution of
7 | Creative Commons public licenses does not create a lawyer-client or
8 | other relationship. Creative Commons makes its licenses and related
9 | information available on an "as-is" basis. Creative Commons gives no
10 | warranties regarding its licenses, any material licensed under their
11 | terms and conditions, or any related information. Creative Commons
12 | disclaims all liability for damages resulting from their use to the
13 | fullest extent possible.
14 |
15 | Using Creative Commons Public Licenses
16 |
17 | Creative Commons public licenses provide a standard set of terms and
18 | conditions that creators and other rights holders may use to share
19 | original works of authorship and other material subject to copyright
20 | and certain other rights specified in the public license below. The
21 | following considerations are for informational purposes only, are not
22 | exhaustive, and do not form part of our licenses.
23 |
24 | Considerations for licensors: Our public licenses are
25 | intended for use by those authorized to give the public
26 | permission to use material in ways otherwise restricted by
27 | copyright and certain other rights. Our licenses are
28 | irrevocable. Licensors should read and understand the terms
29 | and conditions of the license they choose before applying it.
30 | Licensors should also secure all rights necessary before
31 | applying our licenses so that the public can reuse the
32 | material as expected. Licensors should clearly mark any
33 | material not subject to the license. This includes other CC-
34 | licensed material, or material used under an exception or
35 | limitation to copyright. More considerations for licensors:
36 | wiki.creativecommons.org/Considerations_for_licensors
37 |
38 | Considerations for the public: By using one of our public
39 | licenses, a licensor grants the public permission to use the
40 | licensed material under specified terms and conditions. If
41 | the licensor's permission is not necessary for any reason--for
42 | example, because of any applicable exception or limitation to
43 | copyright--then that use is not regulated by the license. Our
44 | licenses grant only permissions under copyright and certain
45 | other rights that a licensor has authority to grant. Use of
46 | the licensed material may still be restricted for other
47 | reasons, including because others have copyright or other
48 | rights in the material. A licensor may make special requests,
49 | such as asking that all changes be marked or described.
50 | Although not required by our licenses, you are encouraged to
51 | respect those requests where reasonable. More_considerations
52 | for the public:
53 | wiki.creativecommons.org/Considerations_for_licensees
54 |
55 | =======================================================================
56 |
57 | Creative Commons Attribution 4.0 International Public License
58 |
59 | By exercising the Licensed Rights (defined below), You accept and agree
60 | to be bound by the terms and conditions of this Creative Commons
61 | Attribution 4.0 International Public License ("Public License"). To the
62 | extent this Public License may be interpreted as a contract, You are
63 | granted the Licensed Rights in consideration of Your acceptance of
64 | these terms and conditions, and the Licensor grants You such rights in
65 | consideration of benefits the Licensor receives from making the
66 | Licensed Material available under these terms and conditions.
67 |
68 |
69 | Section 1 -- Definitions.
70 |
71 | a. Adapted Material means material subject to Copyright and Similar
72 | Rights that is derived from or based upon the Licensed Material
73 | and in which the Licensed Material is translated, altered,
74 | arranged, transformed, or otherwise modified in a manner requiring
75 | permission under the Copyright and Similar Rights held by the
76 | Licensor. For purposes of this Public License, where the Licensed
77 | Material is a musical work, performance, or sound recording,
78 | Adapted Material is always produced where the Licensed Material is
79 | synched in timed relation with a moving image.
80 |
81 | b. Adapter's License means the license You apply to Your Copyright
82 | and Similar Rights in Your contributions to Adapted Material in
83 | accordance with the terms and conditions of this Public License.
84 |
85 | c. Copyright and Similar Rights means copyright and/or similar rights
86 | closely related to copyright including, without limitation,
87 | performance, broadcast, sound recording, and Sui Generis Database
88 | Rights, without regard to how the rights are labeled or
89 | categorized. For purposes of this Public License, the rights
90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
91 | Rights.
92 |
93 | d. Effective Technological Measures means those measures that, in the
94 | absence of proper authority, may not be circumvented under laws
95 | fulfilling obligations under Article 11 of the WIPO Copyright
96 | Treaty adopted on December 20, 1996, and/or similar international
97 | agreements.
98 |
99 | e. Exceptions and Limitations means fair use, fair dealing, and/or
100 | any other exception or limitation to Copyright and Similar Rights
101 | that applies to Your use of the Licensed Material.
102 |
103 | f. Licensed Material means the artistic or literary work, database,
104 | or other material to which the Licensor applied this Public
105 | License.
106 |
107 | g. Licensed Rights means the rights granted to You subject to the
108 | terms and conditions of this Public License, which are limited to
109 | all Copyright and Similar Rights that apply to Your use of the
110 | Licensed Material and that the Licensor has authority to license.
111 |
112 | h. Licensor means the individual(s) or entity(ies) granting rights
113 | under this Public License.
114 |
115 | i. Share means to provide material to the public by any means or
116 | process that requires permission under the Licensed Rights, such
117 | as reproduction, public display, public performance, distribution,
118 | dissemination, communication, or importation, and to make material
119 | available to the public including in ways that members of the
120 | public may access the material from a place and at a time
121 | individually chosen by them.
122 |
123 | j. Sui Generis Database Rights means rights other than copyright
124 | resulting from Directive 96/9/EC of the European Parliament and of
125 | the Council of 11 March 1996 on the legal protection of databases,
126 | as amended and/or succeeded, as well as other essentially
127 | equivalent rights anywhere in the world.
128 |
129 | k. You means the individual or entity exercising the Licensed Rights
130 | under this Public License. Your has a corresponding meaning.
131 |
132 |
133 | Section 2 -- Scope.
134 |
135 | a. License grant.
136 |
137 | 1. Subject to the terms and conditions of this Public License,
138 | the Licensor hereby grants You a worldwide, royalty-free,
139 | non-sublicensable, non-exclusive, irrevocable license to
140 | exercise the Licensed Rights in the Licensed Material to:
141 |
142 | a. reproduce and Share the Licensed Material, in whole or
143 | in part; and
144 |
145 | b. produce, reproduce, and Share Adapted Material.
146 |
147 | 2. Exceptions and Limitations. For the avoidance of doubt, where
148 | Exceptions and Limitations apply to Your use, this Public
149 | License does not apply, and You do not need to comply with
150 | its terms and conditions.
151 |
152 | 3. Term. The term of this Public License is specified in Section
153 | 6(a).
154 |
155 | 4. Media and formats; technical modifications allowed. The
156 | Licensor authorizes You to exercise the Licensed Rights in
157 | all media and formats whether now known or hereafter created,
158 | and to make technical modifications necessary to do so. The
159 | Licensor waives and/or agrees not to assert any right or
160 | authority to forbid You from making technical modifications
161 | necessary to exercise the Licensed Rights, including
162 | technical modifications necessary to circumvent Effective
163 | Technological Measures. For purposes of this Public License,
164 | simply making modifications authorized by this Section 2(a)
165 | (4) never produces Adapted Material.
166 |
167 | 5. Downstream recipients.
168 |
169 | a. Offer from the Licensor -- Licensed Material. Every
170 | recipient of the Licensed Material automatically
171 | receives an offer from the Licensor to exercise the
172 | Licensed Rights under the terms and conditions of this
173 | Public License.
174 |
175 | b. No downstream restrictions. You may not offer or impose
176 | any additional or different terms or conditions on, or
177 | apply any Effective Technological Measures to, the
178 | Licensed Material if doing so restricts exercise of the
179 | Licensed Rights by any recipient of the Licensed
180 | Material.
181 |
182 | 6. No endorsement. Nothing in this Public License constitutes or
183 | may be construed as permission to assert or imply that You
184 | are, or that Your use of the Licensed Material is, connected
185 | with, or sponsored, endorsed, or granted official status by,
186 | the Licensor or others designated to receive attribution as
187 | provided in Section 3(a)(1)(A)(i).
188 |
189 | b. Other rights.
190 |
191 | 1. Moral rights, such as the right of integrity, are not
192 | licensed under this Public License, nor are publicity,
193 | privacy, and/or other similar personality rights; however, to
194 | the extent possible, the Licensor waives and/or agrees not to
195 | assert any such rights held by the Licensor to the limited
196 | extent necessary to allow You to exercise the Licensed
197 | Rights, but not otherwise.
198 |
199 | 2. Patent and trademark rights are not licensed under this
200 | Public License.
201 |
202 | 3. To the extent possible, the Licensor waives any right to
203 | collect royalties from You for the exercise of the Licensed
204 | Rights, whether directly or through a collecting society
205 | under any voluntary or waivable statutory or compulsory
206 | licensing scheme. In all other cases the Licensor expressly
207 | reserves any right to collect such royalties.
208 |
209 |
210 | Section 3 -- License Conditions.
211 |
212 | Your exercise of the Licensed Rights is expressly made subject to the
213 | following conditions.
214 |
215 | a. Attribution.
216 |
217 | 1. If You Share the Licensed Material (including in modified
218 | form), You must:
219 |
220 | a. retain the following if it is supplied by the Licensor
221 | with the Licensed Material:
222 |
223 | i. identification of the creator(s) of the Licensed
224 | Material and any others designated to receive
225 | attribution, in any reasonable manner requested by
226 | the Licensor (including by pseudonym if
227 | designated);
228 |
229 | ii. a copyright notice;
230 |
231 | iii. a notice that refers to this Public License;
232 |
233 | iv. a notice that refers to the disclaimer of
234 | warranties;
235 |
236 | v. a URI or hyperlink to the Licensed Material to the
237 | extent reasonably practicable;
238 |
239 | b. indicate if You modified the Licensed Material and
240 | retain an indication of any previous modifications; and
241 |
242 | c. indicate the Licensed Material is licensed under this
243 | Public License, and include the text of, or the URI or
244 | hyperlink to, this Public License.
245 |
246 | 2. You may satisfy the conditions in Section 3(a)(1) in any
247 | reasonable manner based on the medium, means, and context in
248 | which You Share the Licensed Material. For example, it may be
249 | reasonable to satisfy the conditions by providing a URI or
250 | hyperlink to a resource that includes the required
251 | information.
252 |
253 | 3. If requested by the Licensor, You must remove any of the
254 | information required by Section 3(a)(1)(A) to the extent
255 | reasonably practicable.
256 |
257 | 4. If You Share Adapted Material You produce, the Adapter's
258 | License You apply must not prevent recipients of the Adapted
259 | Material from complying with this Public License.
260 |
261 |
262 | Section 4 -- Sui Generis Database Rights.
263 |
264 | Where the Licensed Rights include Sui Generis Database Rights that
265 | apply to Your use of the Licensed Material:
266 |
267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
268 | to extract, reuse, reproduce, and Share all or a substantial
269 | portion of the contents of the database;
270 |
271 | b. if You include all or a substantial portion of the database
272 | contents in a database in which You have Sui Generis Database
273 | Rights, then the database in which You have Sui Generis Database
274 | Rights (but not its individual contents) is Adapted Material; and
275 |
276 | c. You must comply with the conditions in Section 3(a) if You Share
277 | all or a substantial portion of the contents of the database.
278 |
279 | For the avoidance of doubt, this Section 4 supplements and does not
280 | replace Your obligations under this Public License where the Licensed
281 | Rights include other Copyright and Similar Rights.
282 |
283 |
284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
285 |
286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
296 |
297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
306 |
307 | c. The disclaimer of warranties and limitation of liability provided
308 | above shall be interpreted in a manner that, to the extent
309 | possible, most closely approximates an absolute disclaimer and
310 | waiver of all liability.
311 |
312 |
313 | Section 6 -- Term and Termination.
314 |
315 | a. This Public License applies for the term of the Copyright and
316 | Similar Rights licensed here. However, if You fail to comply with
317 | this Public License, then Your rights under this Public License
318 | terminate automatically.
319 |
320 | b. Where Your right to use the Licensed Material has terminated under
321 | Section 6(a), it reinstates:
322 |
323 | 1. automatically as of the date the violation is cured, provided
324 | it is cured within 30 days of Your discovery of the
325 | violation; or
326 |
327 | 2. upon express reinstatement by the Licensor.
328 |
329 | For the avoidance of doubt, this Section 6(b) does not affect any
330 | right the Licensor may have to seek remedies for Your violations
331 | of this Public License.
332 |
333 | c. For the avoidance of doubt, the Licensor may also offer the
334 | Licensed Material under separate terms or conditions or stop
335 | distributing the Licensed Material at any time; however, doing so
336 | will not terminate this Public License.
337 |
338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
339 | License.
340 |
341 |
342 | Section 7 -- Other Terms and Conditions.
343 |
344 | a. The Licensor shall not be bound by any additional or different
345 | terms or conditions communicated by You unless expressly agreed.
346 |
347 | b. Any arrangements, understandings, or agreements regarding the
348 | Licensed Material not stated herein are separate from and
349 | independent of the terms and conditions of this Public License.
350 |
351 |
352 | Section 8 -- Interpretation.
353 |
354 | a. For the avoidance of doubt, this Public License does not, and
355 | shall not be interpreted to, reduce, limit, restrict, or impose
356 | conditions on any use of the Licensed Material that could lawfully
357 | be made without permission under this Public License.
358 |
359 | b. To the extent possible, if any provision of this Public License is
360 | deemed unenforceable, it shall be automatically reformed to the
361 | minimum extent necessary to make it enforceable. If the provision
362 | cannot be reformed, it shall be severed from this Public License
363 | without affecting the enforceability of the remaining terms and
364 | conditions.
365 |
366 | c. No term or condition of this Public License will be waived and no
367 | failure to comply consented to unless expressly agreed to by the
368 | Licensor.
369 |
370 | d. Nothing in this Public License constitutes or may be interpreted
371 | as a limitation upon, or waiver of, any privileges and immunities
372 | that apply to the Licensor or You, including from the legal
373 | processes of any jurisdiction or authority.
374 |
375 |
376 | =======================================================================
377 |
378 | Creative Commons is not a party to its public
379 | licenses. Notwithstanding, Creative Commons may elect to apply one of
380 | its public licenses to material it publishes and in those instances
381 | will be considered the “Licensor.” The text of the Creative Commons
382 | public licenses is dedicated to the public domain under the CC0 Public
383 | Domain Dedication. Except for the limited purpose of indicating that
384 | material is shared under a Creative Commons public license or as
385 | otherwise permitted by the Creative Commons policies published at
386 | creativecommons.org/policies, Creative Commons does not authorize the
387 | use of the trademark "Creative Commons" or any other trademark or logo
388 | of Creative Commons without its prior written consent including,
389 | without limitation, in connection with any unauthorized modifications
390 | to any of its public licenses or any other arrangements,
391 | understandings, or agreements concerning use of licensed material. For
392 | the avoidance of doubt, this paragraph does not form part of the
393 | public licenses.
394 |
395 | Creative Commons may be contacted at creativecommons.org.
396 |
--------------------------------------------------------------------------------
/MIT_LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Kyle T. Mandli
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Finite Volume Methods for Hyperbolic PDEs
2 |
3 | Course notes for a course loosely based on R.J. LeVeque's "Finite Volume Methods for Hyperbolic Problems".
4 |
--------------------------------------------------------------------------------
/images/CC-BY.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mandli/finite_volume_methods/a0649f3dc19c08b177bf52b3d34c8af8682c53c1/images/CC-BY.png
--------------------------------------------------------------------------------