├── .gitignore ├── figures ├── mantissa.key └── mantissa.png ├── topics ├── initial-value-problems │ ├── sharp-transient-exact.pdf │ ├── cyclical-system-example.pdf │ ├── motivation for implicit dt=0.0005.pdf │ ├── __pycache__ │ │ └── odeintegrate.cpython-36.pyc │ ├── odeintegrate.py │ ├── System of Equations - Kinetics.ipynb │ └── System of Equations Example - SIR Epidemic Model - With Gaps.ipynb ├── regression │ └── gpa_data.txt └── boundary value problems │ └── Boundary Value Problem Example - Heated Rod - With Gaps.ipynb ├── README.md ├── LICENSE ├── styles └── custom.css └── misc ├── 01. Numbers and Computers.ipynb ├── 03. Errors.ipynb └── Ex01. Projectile Motion.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints -------------------------------------------------------------------------------- /figures/mantissa.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saadtony/NumericalMethods/HEAD/figures/mantissa.key -------------------------------------------------------------------------------- /figures/mantissa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saadtony/NumericalMethods/HEAD/figures/mantissa.png -------------------------------------------------------------------------------- /topics/initial-value-problems/sharp-transient-exact.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saadtony/NumericalMethods/HEAD/topics/initial-value-problems/sharp-transient-exact.pdf -------------------------------------------------------------------------------- /topics/initial-value-problems/cyclical-system-example.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saadtony/NumericalMethods/HEAD/topics/initial-value-problems/cyclical-system-example.pdf -------------------------------------------------------------------------------- /topics/initial-value-problems/motivation for implicit dt=0.0005.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saadtony/NumericalMethods/HEAD/topics/initial-value-problems/motivation for implicit dt=0.0005.pdf -------------------------------------------------------------------------------- /topics/initial-value-problems/__pycache__/odeintegrate.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saadtony/NumericalMethods/HEAD/topics/initial-value-problems/__pycache__/odeintegrate.cpython-36.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Numerical Methods @ the U 2 | Numerical Methods @ the University of Utah (CHEN 2450)
3 | Prof. Tony Saad
4 | Assistant Professor of Chemical Engineering
5 | University of Utah
6 | 7 | This repository contains material related to the undergraduate numerical methods class in Chemical Engineering at the University of Utah (CHEN2450). 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tony Saad 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. 22 | -------------------------------------------------------------------------------- /topics/initial-value-problems/odeintegrate.py: -------------------------------------------------------------------------------- 1 | """odeintegrate.py: Implements a few time integration routines for ODEs.""" 2 | 3 | __author__ = "Tony Saad" 4 | __copyright__ = "Copyright 2018, Tony Saad under the MIT license" 5 | 6 | import numpy as np 7 | from scipy.optimize import fsolve 8 | 9 | def forward_euler(rhs, f0, tend, dt): 10 | ''' Computes the forward_euler method ''' 11 | nsteps = int(tend/dt) 12 | f = np.zeros(nsteps) 13 | f[0] = f0 14 | time = np.linspace(0,tend,nsteps) 15 | for n in np.arange(nsteps-1): 16 | f[n+1] = f[n] + dt * rhs(f[n], time[n]) 17 | return time, f 18 | 19 | def forward_euler_system(rhsvec, f0vec, tend, dt): 20 | ''' 21 | Solves a system of ODEs using the Forward Euler method 22 | ''' 23 | nsteps = int(tend/dt) 24 | neqs = len(f0vec) 25 | f = np.zeros( (neqs, nsteps) ) 26 | f[:,0] = f0vec 27 | time = np.linspace(0,tend,nsteps) 28 | for n in np.arange(nsteps-1): 29 | t = time[n] 30 | f[:,n+1] = f[:,n] + dt * rhsvec(f[:,n], t) 31 | return time, f 32 | 33 | def be_residual(fnp1, rhs, fn, dt, tnp1): 34 | ''' 35 | Nonlinear residual function for the backward Euler implicit time integrator 36 | ''' 37 | return fnp1 - fn - dt * rhs(fnp1, tnp1) 38 | 39 | def backward_euler(rhs, f0, tend, dt): 40 | ''' 41 | Computes the backward euler method 42 | :param rhs: an rhs function 43 | ''' 44 | nsteps = int(tend/dt) 45 | f = np.zeros(nsteps) 46 | f[0] = f0 47 | time = np.linspace(0,tend,nsteps) 48 | for n in np.arange(nsteps-1): 49 | fn = f[n] 50 | tnp1 = time[n+1] 51 | fnew = fsolve(be_residual, fn, (rhs, fn, dt, tnp1)) 52 | f[n+1] = fnew 53 | return time, f 54 | 55 | def cn_residual(fnp1, rhs, fn, dt, tnp1, tn): 56 | ''' 57 | Nonlinear residual function for the Crank-Nicolson implicit time integrator 58 | ''' 59 | return fnp1 - fn - 0.5 * dt * ( rhs(fnp1, tnp1) + rhs(fn, tn) ) 60 | 61 | def crank_nicolson(rhs,f0,tend,dt): 62 | nsteps = int(tend/dt) 63 | f = np.zeros(nsteps) 64 | f[0] = f0 65 | time = np.linspace(0,tend,nsteps) 66 | for n in np.arange(nsteps-1): 67 | fn = f[n] 68 | tnp1 = time[n+1] 69 | tn = time[n] 70 | fnew = fsolve(cn_residual, fn, (rhs, fn, dt, tnp1, tn)) 71 | f[n+1] = fnew 72 | return time, f -------------------------------------------------------------------------------- /topics/regression/gpa_data.txt: -------------------------------------------------------------------------------- 1 | #Variable Description 2 | #high_GPA High school grade point average 3 | #math_SAT Math SAT score 4 | #verb_SAT Verbal SAT score 5 | #comp_GPA Computer science grade point average 6 | #univ_GPA Overall university grade point average 7 | #high_GPA math_SAT verb_SAT comp_GPA univ_GPA 8 | 3.45 643 589 3.76 3.52 9 | 2.78 558 512 2.87 2.91 10 | 2.52 583 503 2.54 2.4 11 | 3.67 685 602 3.83 3.47 12 | 3.24 592 538 3.29 3.47 13 | 2.1 562 486 2.64 2.37 14 | 2.82 573 548 2.86 2.4 15 | 2.36 559 536 2.03 2.24 16 | 2.42 552 583 2.81 3.02 17 | 3.51 617 591 3.41 3.32 18 | 3.48 684 649 3.61 3.59 19 | 2.14 568 592 2.48 2.54 20 | 2.59 604 582 3.21 3.19 21 | 3.46 619 624 3.52 3.71 22 | 3.51 642 619 3.41 3.58 23 | 3.68 683 642 3.52 3.4 24 | 3.91 703 684 3.84 3.73 25 | 3.72 712 652 3.64 3.49 26 | 2.15 564 501 2.14 2.25 27 | 2.48 557 549 2.21 2.37 28 | 3.09 591 584 3.17 3.29 29 | 2.71 599 562 3.01 3.19 30 | 2.46 607 619 3.17 3.28 31 | 3.32 619 558 3.01 3.37 32 | 3.61 700 721 3.72 3.61 33 | 3.82 718 732 3.78 3.81 34 | 2.64 580 538 2.51 2.4 35 | 2.19 562 507 2.1 2.21 36 | 3.34 683 648 3.21 3.58 37 | 3.48 717 724 3.68 3.51 38 | 3.56 701 714 3.48 3.62 39 | 3.81 691 684 3.71 3.6 40 | 3.92 714 706 3.81 3.65 41 | 4 689 673 3.84 3.76 42 | 2.52 554 507 2.09 2.27 43 | 2.71 564 543 2.17 2.35 44 | 3.15 668 604 2.98 3.17 45 | 3.22 691 662 3.28 3.47 46 | 2.29 573 591 2.74 3 47 | 2.03 568 517 2.19 2.74 48 | 3.14 607 624 3.28 3.37 49 | 3.52 651 683 3.68 3.54 50 | 2.91 604 583 3.17 3.28 51 | 2.83 560 542 3.17 3.39 52 | 2.65 604 617 3.31 3.28 53 | 2.41 574 548 3.07 3.19 54 | 2.54 564 500 2.38 2.52 55 | 2.66 607 528 2.94 3.08 56 | 3.21 619 573 2.84 3.01 57 | 3.34 647 608 3.17 3.42 58 | 3.68 651 683 3.72 3.6 59 | 2.84 571 543 2.17 2.4 60 | 2.74 583 510 2.42 2.83 61 | 2.71 554 538 2.49 2.38 62 | 2.24 568 519 3.38 3.21 63 | 2.48 574 602 2.07 2.24 64 | 3.14 605 619 3.22 3.4 65 | 2.83 591 584 2.71 3.07 66 | 3.44 642 608 3.31 3.52 67 | 2.89 608 573 3.28 3.47 68 | 2.67 574 538 3.19 3.08 69 | 3.24 643 607 3.24 3.38 70 | 3.29 608 649 3.53 3.41 71 | 3.87 709 688 3.72 3.64 72 | 3.94 691 645 3.98 3.71 73 | 3.42 667 583 3.09 3.01 74 | 3.52 656 609 3.42 3.37 75 | 2.24 554 542 2.07 2.34 76 | 3.29 692 563 3.17 3.29 77 | 3.41 684 672 3.51 3.4 78 | 3.56 717 649 3.49 3.38 79 | 3.61 712 708 3.51 3.28 80 | 3.28 641 608 3.4 3.31 81 | 3.21 675 632 3.38 3.42 82 | 3.48 692 698 3.54 3.39 83 | 3.62 684 609 3.48 3.51 84 | 2.92 564 591 3.09 3.17 85 | 2.81 554 509 3.14 3.2 86 | 3.11 685 694 3.28 3.41 87 | 3.28 671 609 3.41 3.29 88 | 2.7 571 503 3.02 3.17 89 | 2.62 582 591 2.97 3.12 90 | 3.72 621 589 4 3.71 91 | 3.42 651 642 3.34 3.5 92 | 3.51 673 681 3.28 3.34 93 | 3.28 651 640 3.32 3.48 94 | 3.42 672 607 3.51 3.44 95 | 3.9 591 587 3.68 3.59 96 | 3.12 582 612 3.07 3.28 97 | 2.83 609 555 2.78 3 98 | 2.09 554 480 3.68 3.42 99 | 3.17 612 590 3.3 3.41 100 | 3.28 628 580 3.34 3.49 101 | 3.02 567 602 3.17 3.28 102 | 3.42 619 623 3.07 3.17 103 | 3.06 691 683 3.19 3.24 104 | 2.76 564 549 2.15 2.34 105 | 3.19 650 684 3.11 3.28 106 | 2.23 551 554 2.17 2.29 107 | 2.48 568 541 2.14 2.08 108 | 3.76 605 590 3.74 3.64 109 | 3.49 692 683 3.27 3.42 110 | 3.07 680 692 3.19 3.25 111 | 2.19 617 503 2.98 2.76 112 | 3.46 516 528 3.28 3.41 -------------------------------------------------------------------------------- /styles/custom.css: -------------------------------------------------------------------------------- 1 | CSS style adapted from https://github.com/barbagroup/CFDPython. Copyright (c) Barba group 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 103 | 104 | 121 | -------------------------------------------------------------------------------- /misc/01. Numbers and Computers.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "nbpresent": { 7 | "id": "25797aec-dbcc-4861-8e0f-eb550f6f6e3d" 8 | }, 9 | "slideshow": { 10 | "slide_type": "slide" 11 | } 12 | }, 13 | "source": [ 14 | "# Significant Digits\n", 15 | "The significant digits of a number are those that we know with confidence. Numbers on a computer are not different.\n" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "nbpresent": { 22 | "id": "ffe668aa-0d49-42de-8865-fc808cdd7ab3" 23 | }, 24 | "slideshow": { 25 | "slide_type": "slide" 26 | } 27 | }, 28 | "source": [ 29 | "Floating point numbers are represented in the the form\n", 30 | "\\begin{equation}\n", 31 | "m \\times b^e\n", 32 | "\\end{equation}\n", 33 | "where $m$ is called the mantissa and represents the digits of the number, $b$ is the base (10 for decial, 2 for binary, 8 for octal...), and $e$ is the exponent." 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": { 39 | "nbpresent": { 40 | "id": "6dbdd4d2-64f2-4663-bc5e-de6c53cb24aa" 41 | }, 42 | "slideshow": { 43 | "slide_type": "slide" 44 | } 45 | }, 46 | "source": [ 47 | "These numbers are stored in a computer as a series of digits to represent the sign of the number, the mantissa, and the exponent, such that\n", 48 | "\n", 49 | "This representation divides the memory into bits or registers and each digit occupies one of those bits. The digits in a number will occupy the manitssa up to however many places are allowed by the computer. For example, if a computer has a 7 bit representation where 1 bit is reserved for the sign of the number, 2 bits are reserved for the signed exponent, and 4 bits are reserved for the mantissa, then, the number 0.5468113287 is represented as:\n", 50 | "++00547\n", 51 | "\n", 52 | "Note how the computer had to round (or chop) the last digit. This chopping or rounding leads to round of errors (discussed later), but keep that in mind for the moment. The implications of this are very important." 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": { 58 | "nbpresent": { 59 | "id": "58de0105-a65c-4ec2-9e10-7eabd48398ec" 60 | }, 61 | "slideshow": { 62 | "slide_type": "slide" 63 | } 64 | }, 65 | "source": [ 66 | "## Example 1" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": { 72 | "nbpresent": { 73 | "id": "20cb4a15-3217-4606-84d7-96ec95181dd8" 74 | }, 75 | "slideshow": { 76 | "slide_type": "slide" 77 | } 78 | }, 79 | "source": [ 80 | "When two floating-point numbers are added, the mantissa of the number with the smaller exponent is modified so that the exponents are the same. This will align the decimal points to make addition straightforward. Suppose we wanted to add \n", 81 | "\n", 82 | "$0.1557\\times 10^1 + 0.4381 \\times 10^{-1}$ \n", 83 | "\n", 84 | "on a computer that with a four digit mantissa and a one digit exponent. First the computer will align the number with the smallest exponent to the number with the larger one, such that:\n", 85 | "\n", 86 | "$0.4381 \\times 10^{-1} \\to 0.004381 \\times 10^1$\n", 87 | "\n", 88 | "But this result can't fit on the mantissa, so the number either gets chopped ($0.004381 \\to 0.0043$ or rounded $0.004381 \\to 0.0044$). Now the addition returns $0.1600\\times 10^1$." 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": { 94 | "nbpresent": { 95 | "id": "2dc66772-30ec-459e-b2cb-0871bc33eca1" 96 | }, 97 | "slideshow": { 98 | "slide_type": "slide" 99 | } 100 | }, 101 | "source": [ 102 | "In practice, numbers in a computer are represented using a binary system following the same idea for the exponent and mantissa discussed above." 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": { 108 | "nbpresent": { 109 | "id": "e7beeeca-27c8-41ba-aac7-97214855be44" 110 | }, 111 | "slideshow": { 112 | "slide_type": "slide" 113 | } 114 | }, 115 | "source": [ 116 | "Modern computers can deal with a huge mantissas and can represent very large and very small numbers. For a 32bit representation (default float in Python and Matlab), the mantissa is a whopping 24 bits! But still, round off errors are present!" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": { 122 | "nbpresent": { 123 | "id": "f8774eb6-d662-4d58-b746-24edbfaaaac6" 124 | }, 125 | "slideshow": { 126 | "slide_type": "slide" 127 | } 128 | }, 129 | "source": [ 130 | "## Example 2\n", 131 | "Let's add a large number to a small number" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 39, 137 | "metadata": { 138 | "nbpresent": { 139 | "id": "5203efbe-6412-4c82-830e-87f111b14e4a" 140 | }, 141 | "slideshow": { 142 | "slide_type": "slide" 143 | } 144 | }, 145 | "outputs": [ 146 | { 147 | "data": { 148 | "text/plain": [ 149 | "1e+18" 150 | ] 151 | }, 152 | "execution_count": 39, 153 | "metadata": {}, 154 | "output_type": "execute_result" 155 | } 156 | ], 157 | "source": [ 158 | "x = 1e18\n", 159 | "x - 1" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": { 165 | "nbpresent": { 166 | "id": "7d886522-e22f-481e-b475-b0516ee2af84" 167 | }, 168 | "slideshow": { 169 | "slide_type": "slide" 170 | } 171 | }, 172 | "source": [ 173 | "now try to evaluate $ x - x + 1$ and compare that to $x - (x-1)$" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 40, 179 | "metadata": { 180 | "nbpresent": { 181 | "id": "b5be5fa6-120a-481e-996c-b50bfc3484a4" 182 | }, 183 | "slideshow": { 184 | "slide_type": "slide" 185 | } 186 | }, 187 | "outputs": [ 188 | { 189 | "data": { 190 | "text/plain": [ 191 | "1.0" 192 | ] 193 | }, 194 | "execution_count": 40, 195 | "metadata": {}, 196 | "output_type": "execute_result" 197 | } 198 | ], 199 | "source": [ 200 | "x - x + 1" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 43, 206 | "metadata": { 207 | "nbpresent": { 208 | "id": "8362bb85-4b73-4f98-93b9-0424638f0d1f" 209 | }, 210 | "slideshow": { 211 | "slide_type": "slide" 212 | } 213 | }, 214 | "outputs": [ 215 | { 216 | "data": { 217 | "text/plain": [ 218 | "0.0" 219 | ] 220 | }, 221 | "execution_count": 43, 222 | "metadata": {}, 223 | "output_type": "execute_result" 224 | } 225 | ], 226 | "source": [ 227 | "x - (x-1)" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": { 233 | "nbpresent": { 234 | "id": "83c479f9-ecb8-4d86-b594-5b62bff86724" 235 | }, 236 | "slideshow": { 237 | "slide_type": "slide" 238 | } 239 | }, 240 | "source": [ 241 | "The impact of the binary representation also has other effects. Fractions for example cannot be fully represented in binary digits and have to be roudned on chopped!\n", 242 | "For example, the true value of \n", 243 | "\n", 244 | "$1/10 = 0.1 = 0.000 11 00 11 00 11 00 11 00 11 00 \\ldots $\n", 245 | "\n", 246 | "but in practice, on a 32-bit representation, this number gets chopped or rounded. Here's an example of how this could induce error." 247 | ] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": { 252 | "nbpresent": { 253 | "id": "55a25382-954d-4d6f-956a-3244b0f46688" 254 | } 255 | }, 256 | "source": [ 257 | "## Example 3\n", 258 | "In numerical methods, we often have to iterate and repeat calculations hundreds of thousands of times. This leads to accumulation of round off errors. Consider for example evaluating the sum\n", 259 | "\n", 260 | "$\\sum_1^{10^5} 10^{-5} = 10^{-5} + 10^{-5} + \\ldots + 10^{-5} = 100,000 \\times 10^{-5} = 1$\n", 261 | "\n", 262 | "Perform this summation using half (np.float16), single (np.float32), double (np.float64), and triple precision (np.float128)" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": 16, 268 | "metadata": { 269 | "nbpresent": { 270 | "id": "82db3330-9771-4c0b-ac3b-808979863bd7" 271 | } 272 | }, 273 | "outputs": [ 274 | { 275 | "name": "stdout", 276 | "output_type": "stream", 277 | "text": [ 278 | "9997.55859375\n", 279 | "10000.000149011612\n", 280 | "10000.000000018848\n", 281 | "9999.999999999998721\n" 282 | ] 283 | } 284 | ], 285 | "source": [ 286 | "import numpy as np # we need numpy to define the different floats\n", 287 | "x = 0.1\n", 288 | "s16 = s32 = s64 = s128 = 0.0\n", 289 | "ntotal = 100000\n", 290 | "exactval = x*ntotal\n", 291 | "for i in range(0,ntotal):\n", 292 | " s16 = s16 + np.float16(x)\n", 293 | " s32 = s32 + np.float32(x)\n", 294 | " s64 = s64 + np.float64(x) \n", 295 | " s128 = s128 + np.float128(x) \n", 296 | "print(s16)\n", 297 | "print(s32)\n", 298 | "print(s64)\n", 299 | "print(s128)" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": 17, 305 | "metadata": {}, 306 | "outputs": [ 307 | { 308 | "name": "stdout", 309 | "output_type": "stream", 310 | "text": [ 311 | "-2.44140625\n", 312 | "0.00014901161193847656\n", 313 | "1.8848368199542165e-08\n", 314 | "-1.2789769243681803346e-12\n" 315 | ] 316 | } 317 | ], 318 | "source": [ 319 | "print((s16 - exactval))\n", 320 | "print((s32 - exactval))\n", 321 | "print((s64 - exactval))\n", 322 | "print((s128 - exactval))" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": 14, 328 | "metadata": {}, 329 | "outputs": [ 330 | { 331 | "name": "stdout", 332 | "output_type": "stream", 333 | "text": [ 334 | "0.3333\n" 335 | ] 336 | } 337 | ], 338 | "source": [ 339 | "print(np.float16(1.0/3.0))" 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": null, 345 | "metadata": {}, 346 | "outputs": [], 347 | "source": [] 348 | } 349 | ], 350 | "metadata": { 351 | "anaconda-cloud": {}, 352 | "celltoolbar": "Slideshow", 353 | "kernelspec": { 354 | "display_name": "Python [default]", 355 | "language": "python", 356 | "name": "python3" 357 | }, 358 | "language_info": { 359 | "codemirror_mode": { 360 | "name": "ipython", 361 | "version": 3 362 | }, 363 | "file_extension": ".py", 364 | "mimetype": "text/x-python", 365 | "name": "python", 366 | "nbconvert_exporter": "python", 367 | "pygments_lexer": "ipython3", 368 | "version": "3.6.5" 369 | }, 370 | "toc": { 371 | "base_numbering": 1, 372 | "nav_menu": {}, 373 | "number_sections": true, 374 | "sideBar": true, 375 | "skip_h1_title": false, 376 | "title_cell": "Table of Contents", 377 | "title_sidebar": "Contents", 378 | "toc_cell": false, 379 | "toc_position": {}, 380 | "toc_section_display": true, 381 | "toc_window_display": false 382 | } 383 | }, 384 | "nbformat": 4, 385 | "nbformat_minor": 2 386 | } 387 | -------------------------------------------------------------------------------- /misc/03. Errors.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Introduction\n", 8 | "In the falling parachutist problem we encountered an error - there was a difference between the numerical calculation and the analytical solution. There are numerous types of errors associated with an engineering mathematical model:\n", 9 | "1. Modeling errors: These have to do with the fact that we can never describe reality exactely and/or our model neglects certain effects (e.g. sidewind in the parachutist example).\n", 10 | "2. Numerical errors: These have to do directly with the numerical method used and can be generally categorized as\n", 11 | " * Round-off errors: due to the limited representation of numbers on computers\n", 12 | " * Truncation error: due to approximating exact mathematical operators" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "## Errors\n", 20 | "The basic definition of an error is\n", 21 | "\\begin{equation}\n", 22 | "\\text{True Error = True Value - Approximation}\n", 23 | "\\end{equation}" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "For simplicity, denote the \"True Error\" as $E_\\text{t}$.\n", 31 | "There is a problem with this definition however - it does not take into account the \"magnitude\" of the true value. For example, an error of one centimeter is much more significant if we are measuring a rivet rather than a bridge. To fix this, we define the true relative error, $\\epsilon_\\text{t}$:\n", 32 | "\\begin{equation}\n", 33 | "\\text{True Relative Error} = \\frac{\\text{True Error}}{\\text{True Value}}\n", 34 | "\\end{equation}\n", 35 | "or\n", 36 | "\\begin{equation}\n", 37 | "\\epsilon_\\text{t} = \\frac{E_\\text{t}}{\\text{True Value}}\n", 38 | "\\end{equation}" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "### Example\n", 46 | "Suppose that you have the task of measuring the lengths of a bridge and a rivet and come up with 9999 and 9 cm, respectively. If the true values are 10,000 and 10 cm, respectively, compute (a) the true error and (b) the true percent relative error for each case.\n", 47 | "\n", 48 | "#### Solution\n", 49 | "For the bridge, the True Error is:\n", 50 | "\\begin{equation}\n", 51 | "E_\\text{t} = 10,000 - 9999 = 1 \\text{cm}\n", 52 | "\\end{equation}\n", 53 | "while for the rivet\n", 54 | "\\begin{equation}\n", 55 | "E_\\text{t} = 10 - 9 = 1 \\text{cm}\n", 56 | "\\end{equation}\n", 57 | "Both measurements have the same true error. But we known intuitively that the 1 cm is a bigger deal for the rivet. We can show this by using the relative error.\n", 58 | "For the bridge, we have\n", 59 | "\\begin{equation}\n", 60 | "\\epsilon_\\text{t} = \\frac{E_\\text{t}}{\\text{True Value}} \\times 100\\%= \\frac{1}{10,000} \\times 100\\% = 0.01 \\%\n", 61 | "\\end{equation}\n", 62 | "while for the rivet,\n", 63 | "\\begin{equation}\n", 64 | "\\epsilon_\\text{t} = \\frac{1}{10}\\times 100\\% = 10 \\%\n", 65 | "\\end{equation}" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "Note that we used the words \"True Error\" - this is because the definition is based on the \"True Value\" - but this doesn't make sense since if we know the true value then we don't need an approximation! \n", 73 | "\n", 74 | "This definition is still important however because it lays the foundations of error analysis. In addition, when testing any numerical method, we first try it out on problems where the True Value is known (e.g. analytical solution). What we often do is figure out an approximation for the true value or find the best estimate of the true value.\n", 75 | "\n", 76 | "Another common situation in numerical methods is iteration: repeating the same task over and over again. What we can do in that case is define an iterative error as the difference between current and previous iterations:\n", 77 | "\\begin{equation}\n", 78 | "\\epsilon_\\text{a} = \\frac{ \\text{current approximation} - \\text{previous approximation} }{ \\text{current approximation} }\\times 100\\%\n", 79 | "\\end{equation}" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "The usefulness of this definition is that it allows us to get an idea of how good our approximation is. Specifically, one can use a well known formula to determine the number of significant digits in an error. If your computed error $|\\epsilon_\\text{a}|$ (in \\%) is less than\n", 87 | "\\begin{equation}\n", 88 | "\\epsilon_\\text{s} = (0.5\\times 10^{2-n})\\%\n", 89 | "\\end{equation}\n", 90 | "then your results are accurate to at least $n$ significant digits.\n", 91 | "\n", 92 | "For example, if you want your results to be significant up to at least four digits, ($n = 4$) then your results must satify $ |\\epsilon_\\text{a}| < 0.5\\times10^{-2}\\%$ or $ |\\epsilon_\\text{a}| < 0.005\\%$.\n", 93 | "\n", 94 | "This formula can be inverted to obtain the number of significant digits. Taking the logarigthm\n", 95 | "\\begin{equation}\n", 96 | "\\log \\epsilon_\\text{s} = \\log 0.5 + 2 - n\n", 97 | "\\end{equation}\n", 98 | "and\n", 99 | "\\begin{equation}\n", 100 | "n = \\log 0.5 + 2 - \\log \\epsilon_\\text{s}\n", 101 | "\\end{equation}" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "## Example\n", 109 | "The exponential function $e^x$ can be approximated with the following (Taylor) series:\n", 110 | "\\begin{equation}\n", 111 | "e^x = 1 + x + \\frac{x^2}{2} + \\frac{x^3}{3!} + \\frac{x^4}{4!} + \\frac{x^5}{5!} + \\ldots\n", 112 | "\\end{equation}\n", 113 | "Compute the true and approximate relative errors when using this formula for 1, 2, 3, 4, 5, and 6 terms. Use this formula to compute $e^{0.5}$ up to four significant digits" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "### Solution\n", 121 | "We will first need to define a function that computes the exponential up to a certain number of terms" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 4, 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "# need to import the factorial and exponential functions from the math module\n", 131 | "import math\n", 132 | "from math import factorial, exp\n", 133 | "def my_exponential(x,n):\n", 134 | " '''x is the exponent and n is the number of terms'''\n", 135 | " result = 0.0 # initialize the result to zero\n", 136 | " for i in range(0,n): # loop over the number of terms: this goes from 0 to n-1 (n terms)\n", 137 | " result = result + x**i/factorial(i) # add each term at a time \n", 138 | " return result" 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": 5, 144 | "metadata": {}, 145 | "outputs": [], 146 | "source": [ 147 | "def sig_fig(error):\n", 148 | " return math.floor(math.log10(0.5) + 2 - math.log10(error))" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": 6, 154 | "metadata": {}, 155 | "outputs": [ 156 | { 157 | "name": "stdout", 158 | "output_type": "stream", 159 | "text": [ 160 | "1 \t 1.00000000 \t 39.34693403 \t 100.00000000 \t -1\n", 161 | "2 \t 1.50000000 \t 9.02040104 \t 33.33333333 \t 0\n", 162 | "3 \t 1.62500000 \t 1.43876780 \t 7.69230769 \t 0\n", 163 | "4 \t 1.64583333 \t 0.17516226 \t 1.26582278 \t 1\n", 164 | "5 \t 1.64843750 \t 0.01721156 \t 0.15797788 \t 2\n", 165 | "6 \t 1.64869792 \t 0.00141649 \t 0.01579529 \t 3\n", 166 | "7 \t 1.64871962 \t 0.00010024 \t 0.00131626 \t 4\n", 167 | "8 \t 1.64872117 \t 0.00000622 \t 0.00009402 \t 5\n", 168 | "9 \t 1.64872127 \t 0.00000034 \t 0.00000588 \t 6\n" 169 | ] 170 | } 171 | ], 172 | "source": [ 173 | "# Now run the function for different number of terms\n", 174 | "oldval = 0.0\n", 175 | "x = 0.5\n", 176 | "trueval = exp(x)\n", 177 | "for n in range(1,10):\n", 178 | " val = my_exponential(x,n)\n", 179 | " ϵt = abs( (val - trueval)/trueval ) * 100\n", 180 | " ϵa = abs( (val - oldval)/val ) * 100\n", 181 | " oldval = val\n", 182 | " print (n,'\\t', \"%.8f\" % val, '\\t', \"%.8f\" % ϵt, '\\t', \"%.8f\" % ϵa, '\\t', sig_fig(ϵa))" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": 2, 188 | "metadata": {}, 189 | "outputs": [ 190 | { 191 | "name": "stdout", 192 | "output_type": "stream", 193 | "text": [ 194 | "0 100.0 %\n", 195 | "1 66.66666666666666 %\n", 196 | "2 40.0 %\n", 197 | "3 21.052631578947363 %\n", 198 | "4 9.523809523809527 %\n", 199 | "5 3.669724770642201 %\n", 200 | "6 1.2084592145015065 %\n", 201 | "7 0.34408602150537515 %\n", 202 | "8 0.08594757198109124 %\n", 203 | "9 0.019095813242941077 %\n" 204 | ] 205 | } 206 | ], 207 | "source": [ 208 | "from math import factorial, exp\n", 209 | "oldval = 0.0\n", 210 | "x = 2.0\n", 211 | "nterms = 10\n", 212 | "for n in range(0,nterms):\n", 213 | " newval = oldval + x**n/ factorial(n)\n", 214 | " ϵa = abs( (newval - oldval)/newval) * 100\n", 215 | " oldval = newval\n", 216 | " print(n, ϵa,'%')" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": 3, 222 | "metadata": {}, 223 | "outputs": [ 224 | { 225 | "name": "stdout", 226 | "output_type": "stream", 227 | "text": [ 228 | "1 100.0 %\n", 229 | "2 66.66666666666666 %\n", 230 | "3 40.0 %\n", 231 | "4 21.052631578947363 %\n", 232 | "5 9.523809523809527 %\n", 233 | "6 3.669724770642201 %\n", 234 | "7 1.2084592145015065 %\n", 235 | "8 0.34408602150537515 %\n", 236 | "9 0.08594757198109124 %\n", 237 | "10 0.019095813242941077 %\n", 238 | "11 0.0038190167941204627 %\n" 239 | ] 240 | } 241 | ], 242 | "source": [ 243 | "from math import factorial, exp\n", 244 | "oldval = 0.0\n", 245 | "x = 2.0\n", 246 | "nterms = 100\n", 247 | "tol = 0.01 # percent\n", 248 | "ϵa = 10000\n", 249 | "n = 0\n", 250 | "while ϵa > tol:\n", 251 | " newval = oldval + x**n/ factorial(n)\n", 252 | " ϵa = abs( (newval - oldval)/newval) * 100\n", 253 | " oldval = newval\n", 254 | " n = n + 1\n", 255 | " print(n, ϵa,'%')" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": 4, 261 | "metadata": {}, 262 | "outputs": [], 263 | "source": [ 264 | "def mycos(x, nterms):\n", 265 | " result = 0.0\n", 266 | " for n in range(0,nterms):\n", 267 | " result += (-1)**n * x**(2*n) / factorial(2*n)\n", 268 | " return result" 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": 5, 274 | "metadata": {}, 275 | "outputs": [ 276 | { 277 | "ename": "NameError", 278 | "evalue": "name 'math' is not defined", 279 | "output_type": "error", 280 | "traceback": [ 281 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 282 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", 283 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmycos\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcos\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 284 | "\u001b[0;31mNameError\u001b[0m: name 'math' is not defined" 285 | ] 286 | } 287 | ], 288 | "source": [ 289 | "print(mycos(3, 5), math.cos(3))" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": {}, 296 | "outputs": [], 297 | "source": [] 298 | } 299 | ], 300 | "metadata": { 301 | "anaconda-cloud": {}, 302 | "kernelspec": { 303 | "display_name": "Python [default]", 304 | "language": "python", 305 | "name": "python3" 306 | }, 307 | "language_info": { 308 | "codemirror_mode": { 309 | "name": "ipython", 310 | "version": 3 311 | }, 312 | "file_extension": ".py", 313 | "mimetype": "text/x-python", 314 | "name": "python", 315 | "nbconvert_exporter": "python", 316 | "pygments_lexer": "ipython3", 317 | "version": "3.6.5" 318 | }, 319 | "toc": { 320 | "base_numbering": 1, 321 | "nav_menu": {}, 322 | "number_sections": true, 323 | "sideBar": true, 324 | "skip_h1_title": false, 325 | "title_cell": "Table of Contents", 326 | "title_sidebar": "Contents", 327 | "toc_cell": false, 328 | "toc_position": {}, 329 | "toc_section_display": true, 330 | "toc_window_display": false 331 | } 332 | }, 333 | "nbformat": 4, 334 | "nbformat_minor": 2 335 | } 336 | -------------------------------------------------------------------------------- /topics/initial-value-problems/System of Equations - Kinetics.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Systems of ODEs\n", 8 | "## CH EN 2450 - Numerical Methods\n", 9 | "**Prof. Tony Saad (www.tsaad.net)
Department of Chemical Engineering
University of Utah**\n", 10 | "
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "import numpy as np\n", 20 | "from numpy import *\n", 21 | "%matplotlib inline\n", 22 | "%config InlineBackend.figure_format = 'svg'\n", 23 | "\n", 24 | "import matplotlib.pyplot as plt\n", 25 | "from odeintegrate import *\n", 26 | "from scipy.integrate import odeint" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "# Kinetics Example\n", 34 | "Solve the system of ODEs:\n", 35 | "\\begin{equation}\n", 36 | "\\frac{\\text{d}A}{\\text{d}t} = -k_1 A + k_3 B C \\\\\n", 37 | "\\frac{\\text{d}B}{\\text{d}t} = k_1 A - k_2 B^2 - k_3 B C \\\\\n", 38 | "\\frac{\\text{d}C}{\\text{d}t} = k_2 B^2\n", 39 | "\\end{equation}" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 2, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "def forward_euler_system(rhsvec, f0vec, tend, dt):\n", 49 | " '''\n", 50 | " Solves a system of ODEs using the Forward Euler method\n", 51 | " '''\n", 52 | " nsteps = int(tend/dt)\n", 53 | " neqs = len(f0vec)\n", 54 | " f = np.zeros( (neqs, nsteps) )\n", 55 | " f[:,0] = f0vec\n", 56 | " time = np.linspace(0,tend,nsteps)\n", 57 | " for n in np.arange(nsteps-1):\n", 58 | " t = time[n]\n", 59 | " f[:,n+1] = f[:,n] + dt * rhsvec(f[:,n], t)\n", 60 | " return time, f\n" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 3, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "def rhs_kinetics(f,t):\n", 70 | " A = f[0]\n", 71 | " B = f[1]\n", 72 | " C = f[2]\n", 73 | " k1 = 0.04\n", 74 | " k2 = 3e7\n", 75 | " k3 = 1e4\n", 76 | " rhs1 = - k1*A + k3*B*C\n", 77 | " rhs2 = k1*A - k2*B*B - k3*B*C\n", 78 | " rhs3 = k2*B*B\n", 79 | " return np.array([rhs1,rhs2,rhs3])" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": 4, 85 | "metadata": {}, 86 | "outputs": [ 87 | { 88 | "data": { 89 | "image/svg+xml": [ 90 | "\n", 91 | "\n", 93 | "\n", 94 | "\n", 95 | " \n", 96 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 360 | " \n", 361 | " \n", 362 | " \n", 363 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 399 | " \n", 402 | " \n", 403 | " \n", 404 | " \n", 405 | " \n", 406 | " \n", 407 | " \n", 408 | " \n", 409 | " \n", 410 | " \n", 416 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | " \n", 425 | " \n", 426 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 445 | " \n", 446 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 489 | " \n", 490 | " \n", 491 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | " \n", 500 | " \n", 501 | " \n", 502 | " \n", 503 | " \n", 504 | " \n", 505 | " \n", 506 | " \n", 509 | " \n", 510 | " \n", 511 | " \n", 512 | " \n", 513 | " \n", 514 | " \n", 515 | " \n", 516 | " \n", 517 | " \n", 518 | " \n", 519 | " \n", 520 | " \n", 521 | " \n", 522 | " \n", 523 | " \n", 524 | " \n", 525 | " \n", 526 | " \n", 537 | " \n", 538 | " \n", 539 | " \n", 550 | " \n", 551 | " \n", 552 | " \n", 563 | " \n", 564 | " \n", 565 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | "\n" 613 | ], 614 | "text/plain": [ 615 | "
" 616 | ] 617 | }, 618 | "metadata": {}, 619 | "output_type": "display_data" 620 | } 621 | ], 622 | "source": [ 623 | "import time\n", 624 | "tic = time.clock()\n", 625 | "toc = time.clock()\n", 626 | "toc - tic\n", 627 | "tend = 10\n", 628 | "dt = 1e-5\n", 629 | "t = np.linspace(0,10,10)\n", 630 | "y0 = np.array([1,0,0])\n", 631 | "sol = odeint(rhs_kinetics,y0,t) # use odeint\n", 632 | "timefe, solfe = forward_euler_system(rhs_kinetics,y0,tend,dt)\n", 633 | "plt.plot(t,sol[:,0],t,sol[:,1],t,sol[:,2],timefe,solfe[0])\n", 634 | "plt.grid()" 635 | ] 636 | } 637 | ], 638 | "metadata": { 639 | "anaconda-cloud": {}, 640 | "kernelspec": { 641 | "display_name": "Python [default]", 642 | "language": "python", 643 | "name": "python3" 644 | }, 645 | "language_info": { 646 | "codemirror_mode": { 647 | "name": "ipython", 648 | "version": 3 649 | }, 650 | "file_extension": ".py", 651 | "mimetype": "text/x-python", 652 | "name": "python", 653 | "nbconvert_exporter": "python", 654 | "pygments_lexer": "ipython3", 655 | "version": "3.6.5" 656 | }, 657 | "toc": { 658 | "colors": { 659 | "hover_highlight": "#DAA520", 660 | "navigate_num": "#000000", 661 | "navigate_text": "#333333", 662 | "running_highlight": "#FF0000", 663 | "selected_highlight": "#FFD700", 664 | "sidebar_border": "#EEEEEE", 665 | "wrapper_background": "#FFFFFF" 666 | }, 667 | "moveMenuLeft": true, 668 | "nav_menu": { 669 | "height": "30px", 670 | "width": "252px" 671 | }, 672 | "navigate_menu": true, 673 | "number_sections": true, 674 | "sideBar": true, 675 | "threshold": 4, 676 | "toc_cell": false, 677 | "toc_section_display": "block", 678 | "toc_window_display": false, 679 | "widenNotebook": false 680 | } 681 | }, 682 | "nbformat": 4, 683 | "nbformat_minor": 2 684 | } 685 | -------------------------------------------------------------------------------- /misc/Ex01. Projectile Motion.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Projectile Motion\n", 8 | "\n", 9 | "Recall that the equation for projectile motion when acceleration is constant can be written as $$y=y_{0}+v_{0}t+\\frac{a}{2}t^{2}.$$\n", 10 | "\n", 11 | "1. Create a Matlab or Python function that generates a plot of $y(t)$. You should be able to easily change the initial velocity, the initial position, and the acceleration. Be sure to include axis labels as appropriate. The function should take $y_{0}$, $v_{0}$, $a$ and a vector of $t$ as arguments. The function should:\n", 12 | "\n", 13 | " (a) Plot $y(t)$ with labeled axes and a grid on the plot.\n", 14 | " \n", 15 | " (b) Return the vector $y(t)$.\n", 16 | " \n", 17 | "2. Determine $t_{\\mathrm{end}}$ such that $y(t_{\\mathrm{end}})=0$. In the event that there are two times that produce $y=0$ you should use the larger of the two. HINT: Solve the quadratic equation for the projectile.\n", 18 | "\n", 19 | "You do not need to submit a report for this problem - only your Matlab or Python files." 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Solution" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "## Question 1\n", 34 | "Create a Matlab or Python function that generates a plot of $y(t)$. You should be able to easily change the initial velocity, the initial position, and the acceleration. Be sure to include axis labels as appropriate. The function should take $y_{0}$, $v_{0}$, $a$ and a vector of $t$ as arguments. The function should:\n", 35 | "\n", 36 | " (a) Plot $y(t)$ with labeled axes and a grid on the plot.\n", 37 | " \n", 38 | " (b) Return the vector $y(t)$." 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 8, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "%matplotlib inline\n", 48 | "import numpy as np\n", 49 | "import matplotlib.pyplot as plt" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 18, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "def projectile(y0,v0,a,t):\n", 59 | " \"\"\"The method's docstring\n", 60 | " params:\n", 61 | " y0: value\n", 62 | " v0: value 2\n", 63 | " \"\"\"\n", 64 | " result = y0 + v0 * t + a/2.0 * t * t\n", 65 | " plt.title('Projectile')\n", 66 | " plt.xlabel('time (s)', fontsize=18)\n", 67 | " plt.ylabel('Height (m)', fontsize=16)\n", 68 | " plt.plot(t,result)\n", 69 | " return result" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 20, 75 | "metadata": {}, 76 | "outputs": [ 77 | { 78 | "data": { 79 | "image/png": "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\n", 80 | "text/plain": [ 81 | "
" 82 | ] 83 | }, 84 | "metadata": {}, 85 | "output_type": "display_data" 86 | } 87 | ], 88 | "source": [ 89 | "y0=0.1\n", 90 | "v0=10\n", 91 | "a=-9.81\n", 92 | "t = np.linspace(0,2,200)\n", 93 | "y = projectile(y0,v0,a,t)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "## Question 2\n", 101 | "Determine $t_{\\mathrm{end}}$ such that $y(t_{\\mathrm{end}})=0$. In the event that there are two times that produce $y=0$ you should use the larger of the two. HINT: Solve the quadratic equation for the projectile.\n", 102 | "\n", 103 | "What we can do here is use numpy's roots function" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 23, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "The Projectile will reach the ground in: 2.048687409049999\n" 116 | ] 117 | }, 118 | { 119 | "data": { 120 | "image/png": "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\n", 121 | "text/plain": [ 122 | "
" 123 | ] 124 | }, 125 | "metadata": {}, 126 | "output_type": "display_data" 127 | } 128 | ], 129 | "source": [ 130 | "tend = np.max(np.roots([a/2,v0,y0]))\n", 131 | "print('The Projectile will reach the ground in:', tend)\n", 132 | "t = np.linspace(0,tend,200)\n", 133 | "y = projectile(y0,v0,a,t)" 134 | ] 135 | } 136 | ], 137 | "metadata": { 138 | "anaconda-cloud": {}, 139 | "kernelspec": { 140 | "display_name": "Python [default]", 141 | "language": "python", 142 | "name": "python3" 143 | }, 144 | "language_info": { 145 | "codemirror_mode": { 146 | "name": "ipython", 147 | "version": 3 148 | }, 149 | "file_extension": ".py", 150 | "mimetype": "text/x-python", 151 | "name": "python", 152 | "nbconvert_exporter": "python", 153 | "pygments_lexer": "ipython3", 154 | "version": "3.6.5" 155 | }, 156 | "toc": { 157 | "base_numbering": 1, 158 | "nav_menu": { 159 | "height": "12px", 160 | "width": "252px" 161 | }, 162 | "number_sections": true, 163 | "sideBar": true, 164 | "skip_h1_title": false, 165 | "title_cell": "Table of Contents", 166 | "title_sidebar": "Contents", 167 | "toc_cell": false, 168 | "toc_position": {}, 169 | "toc_section_display": "block", 170 | "toc_window_display": false 171 | } 172 | }, 173 | "nbformat": 4, 174 | "nbformat_minor": 2 175 | } 176 | -------------------------------------------------------------------------------- /topics/boundary value problems/Boundary Value Problem Example - Heated Rod - With Gaps.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Boundary Value Problem Example - Heated Rod\n", 8 | "## CH EN 2450 - Numerical Methods\n", 9 | "**Prof. Tony Saad (www.tsaad.net)
Department of Chemical Engineering
University of Utah**\n", 10 | "
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "%matplotlib inline\n", 20 | "%config InlineBackend.figure_format = 'svg'\n", 21 | "import matplotlib.pyplot as plt\n", 22 | "import numpy as np" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "# Dirichlet Boundary Conditions" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "The coefficient matrix looks like\n", 37 | "\\begin{equation}\n", 38 | "\\left[ {\\begin{array}{*{20}{c}}\n", 39 | "1&0&0& \\cdots &0\\\\\n", 40 | "1& - \\left( 2 + \\Delta {x^2}H \\right)&1&0& \\vdots \\\\\n", 41 | "0& \\ddots & \\ddots & \\ddots &0\\\\\n", 42 | " \\vdots &0&1& - \\left( 2 + \\Delta x^2H \\right)&1\\\\\n", 43 | "0& \\cdots &0&0&1\n", 44 | "\\end{array}} \\right]\n", 45 | "\\left( {\\begin{array}{*{20}{c}}\n", 46 | "T_1\\\\\n", 47 | "\\begin{array}{l}\n", 48 | "T_2\\\\\n", 49 | "T_3\n", 50 | "\\end{array}\\\\\n", 51 | "\\begin{array}{l}\n", 52 | " \\vdots \\\\\n", 53 | " \\vdots \n", 54 | "\\end{array}\\\\\n", 55 | "T_{n - 1}\\\\\n", 56 | "T_n\n", 57 | "\\end{array}} \\right) \n", 58 | "= \\left( {\\begin{array}{*{20}{c}}\n", 59 | "T_\\rm{left}\\\\\n", 60 | "- T_\\infty \\Delta {x^2}H\\\\\n", 61 | " \\vdots \\\\\n", 62 | "- T_\\infty\\Delta {x^2}H\\\\\n", 63 | "T_\\rm{right}\n", 64 | "\\end{array}} \\right)\n", 65 | "\\end{equation}" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 19, 71 | "metadata": { 72 | "scrolled": true 73 | }, 74 | "outputs": [ 75 | { 76 | "data": { 77 | "image/svg+xml": [ 78 | "\n", 79 | "\n", 81 | "\n", 82 | "\n", 83 | " \n", 84 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 147 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 370 | " \n", 371 | " \n", 372 | " \n", 373 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 401 | " \n", 402 | " \n", 403 | " \n", 404 | " \n", 407 | " \n", 408 | " \n", 409 | " \n", 410 | " \n", 411 | " \n", 412 | " \n", 413 | " \n", 414 | " \n", 415 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | " \n", 513 | " \n", 514 | " \n", 515 | " \n", 516 | " \n", 517 | " \n", 518 | " \n", 519 | " \n", 520 | " \n", 521 | " \n", 522 | " \n", 523 | " \n", 526 | " \n", 527 | " \n", 528 | " \n", 529 | " \n", 530 | " \n", 531 | " \n", 532 | " \n", 533 | " \n", 534 | " \n", 535 | " \n", 536 | " \n", 537 | " \n", 538 | " \n", 539 | " \n", 540 | " \n", 541 | " \n", 542 | " \n", 543 | " \n", 546 | " \n", 547 | " \n", 548 | " \n", 549 | " \n", 550 | " \n", 551 | " \n", 552 | " \n", 553 | " \n", 554 | " \n", 555 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 636 | " \n", 637 | " \n", 638 | " \n", 639 | " \n", 640 | " \n", 641 | " \n", 642 | " \n", 643 | " \n", 644 | " \n", 645 | " \n", 646 | " \n", 649 | " \n", 650 | " \n", 651 | " \n", 652 | " \n", 653 | " \n", 654 | " \n", 655 | " \n", 656 | " \n", 657 | " \n", 658 | " \n", 659 | " \n", 660 | " \n", 661 | " \n", 662 | " \n", 663 | " \n", 664 | " \n", 665 | " \n", 666 | " \n", 709 | " \n", 710 | " \n", 711 | " \n", 714 | " \n", 715 | " \n", 716 | " \n", 719 | " \n", 720 | " \n", 721 | " \n", 724 | " \n", 725 | " \n", 726 | " \n", 729 | " \n", 730 | " \n", 731 | " \n", 732 | " \n", 733 | " \n", 734 | " \n", 735 | " \n", 736 | " \n", 737 | "\n" 738 | ], 739 | "text/plain": [ 740 | "
" 741 | ] 742 | }, 743 | "metadata": { 744 | "needs_background": "light" 745 | }, 746 | "output_type": "display_data" 747 | } 748 | ], 749 | "source": [ 750 | "n = 200 # number of desired grid points\n", 751 | "L = 1.0 # rod length\n", 752 | "Tleft = 300\n", 753 | "Tright = 300\n", 754 | "Tinf = 100\n", 755 | "h = 1 # heat transfer coefficient, due to advection of surrounding air\n", 756 | "beta = 0\n", 757 | "\n", 758 | "x = np.linspace(0,L,n) # create an array for the grid points x_i\n", 759 | "dx = x[1] - x[0] # calculate grid spacing (grid spacing is constant here)\n", 760 | "\n", 761 | "# create lower diagonal vector\n", 762 | "ld = np.ones(n-1)\n", 763 | "ld[-1] =2.0 # fix the end point\n", 764 | "\n", 765 | "# create main diagonal vector\n", 766 | "d = -(2.0 + dx*dx * h)*np.ones(n)\n", 767 | "d[0] = 1.0 # fix the end point\n", 768 | "# d[-1] = 1.0 # fix the end point\n", 769 | "\n", 770 | "# create upper diagonal vector\n", 771 | "ud = np.ones(n-1)\n", 772 | "ud[0] = 0.0 # fix the end point\n", 773 | "\n", 774 | "# combine those into a matrix\n", 775 | "A = np.diag(ld,-1) + np.diag(d, 0) + np.diag(ud, 1)\n", 776 | "\n", 777 | "# build the RHS array\n", 778 | "rhs = -Tinf*dx*dx*h*np.ones(n)\n", 779 | "rhs[0] = Tleft # fix the left boundary\n", 780 | "rhs[-1] = -Tinf*dx*dx*h - 2.0*beta*dx # fix the right boundary\n", 781 | "\n", 782 | "# solve the system of equations\n", 783 | "sol = np.linalg.solve(A, rhs)\n", 784 | "\n", 785 | "plt.plot(x, sol)\n", 786 | "# plt.ylim([250,350])\n", 787 | "plt.grid()" 788 | ] 789 | }, 790 | { 791 | "cell_type": "code", 792 | "execution_count": 20, 793 | "metadata": {}, 794 | "outputs": [ 795 | { 796 | "data": { 797 | "text/plain": [ 798 | "" 799 | ] 800 | }, 801 | "execution_count": 20, 802 | "metadata": {}, 803 | "output_type": "execute_result" 804 | }, 805 | { 806 | "data": { 807 | "image/svg+xml": [ 808 | "\n", 809 | "\n", 811 | "\n", 812 | "\n", 813 | " \n", 814 | " \n", 817 | " \n", 818 | " \n", 819 | " \n", 820 | " \n", 826 | " \n", 827 | " \n", 828 | " \n", 829 | " \n", 835 | " \n", 836 | " \n", 837 | " \n", 839 | " \n", 840 | " \n", 841 | " \n", 842 | " \n", 843 | " \n", 844 | " \n", 847 | " \n", 848 | " \n", 849 | " \n", 850 | " \n", 851 | " \n", 852 | " \n", 853 | " \n", 854 | " \n", 855 | " \n", 876 | " \n", 877 | " \n", 878 | " \n", 879 | " \n", 880 | " \n", 881 | " \n", 882 | " \n", 883 | " \n", 884 | " \n", 885 | " \n", 886 | " \n", 887 | " \n", 888 | " \n", 889 | " \n", 890 | " \n", 891 | " \n", 915 | " \n", 939 | " \n", 940 | " \n", 941 | " \n", 942 | " \n", 943 | " \n", 944 | " \n", 945 | " \n", 946 | " \n", 947 | " \n", 948 | " \n", 949 | " \n", 950 | " \n", 951 | " \n", 952 | " \n", 953 | " \n", 954 | " \n", 955 | " \n", 956 | " \n", 957 | " \n", 958 | " \n", 959 | " \n", 960 | " \n", 961 | " \n", 962 | " \n", 963 | " \n", 964 | " \n", 965 | " \n", 966 | " \n", 967 | " \n", 968 | " \n", 969 | " \n", 978 | " \n", 979 | " \n", 980 | " \n", 981 | " \n", 982 | " \n", 983 | " \n", 984 | " \n", 985 | " \n", 986 | " \n", 987 | " \n", 988 | " \n", 989 | " \n", 990 | " \n", 991 | " \n", 992 | " \n", 993 | " \n", 994 | " \n", 1007 | " \n", 1008 | " \n", 1009 | " \n", 1010 | " \n", 1011 | " \n", 1012 | " \n", 1013 | " \n", 1014 | " \n", 1015 | " \n", 1016 | " \n", 1017 | " \n", 1018 | " \n", 1019 | " \n", 1020 | " \n", 1021 | " \n", 1022 | " \n", 1023 | " \n", 1024 | " \n", 1025 | " \n", 1026 | " \n", 1027 | " \n", 1028 | " \n", 1029 | " \n", 1030 | " \n", 1031 | " \n", 1032 | " \n", 1033 | " \n", 1034 | " \n", 1035 | " \n", 1036 | " \n", 1037 | " \n", 1038 | " \n", 1039 | " \n", 1040 | " \n", 1041 | " \n", 1042 | " \n", 1043 | " \n", 1044 | " \n", 1045 | " \n", 1046 | " \n", 1047 | " \n", 1048 | " \n", 1049 | " \n", 1050 | " \n", 1051 | " \n", 1052 | " \n", 1053 | " \n", 1054 | " \n", 1055 | " \n", 1056 | " \n", 1057 | " \n", 1058 | " \n", 1059 | " \n", 1060 | " \n", 1061 | " \n", 1062 | " \n", 1063 | " \n", 1064 | " \n", 1065 | " \n", 1068 | " \n", 1069 | " \n", 1070 | " \n", 1071 | " \n", 1072 | " \n", 1073 | " \n", 1074 | " \n", 1075 | " \n", 1076 | " \n", 1077 | " \n", 1078 | " \n", 1079 | " \n", 1080 | " \n", 1081 | " \n", 1082 | " \n", 1083 | " \n", 1084 | " \n", 1085 | " \n", 1086 | " \n", 1087 | " \n", 1088 | " \n", 1089 | " \n", 1090 | " \n", 1091 | " \n", 1092 | " \n", 1093 | " \n", 1094 | " \n", 1095 | " \n", 1096 | " \n", 1099 | " \n", 1100 | " \n", 1101 | " \n", 1104 | " \n", 1105 | " \n", 1106 | " \n", 1109 | " \n", 1110 | " \n", 1111 | " \n", 1114 | " \n", 1115 | " \n", 1116 | " \n", 1117 | " \n", 1118 | " \n", 1119 | " \n", 1120 | " \n", 1121 | " \n", 1122 | "\n" 1123 | ], 1124 | "text/plain": [ 1125 | "
" 1126 | ] 1127 | }, 1128 | "metadata": { 1129 | "needs_background": "light" 1130 | }, 1131 | "output_type": "display_data" 1132 | } 1133 | ], 1134 | "source": [ 1135 | "temperature = np.tile(sol,(40,1))\n", 1136 | "plt.imshow(temperature,cmap='jet')" 1137 | ] 1138 | }, 1139 | { 1140 | "cell_type": "code", 1141 | "execution_count": null, 1142 | "metadata": {}, 1143 | "outputs": [], 1144 | "source": [] 1145 | } 1146 | ], 1147 | "metadata": { 1148 | "hide_input": false, 1149 | "kernelspec": { 1150 | "display_name": "Python 3 (ipykernel)", 1151 | "language": "python", 1152 | "name": "python3" 1153 | }, 1154 | "language_info": { 1155 | "codemirror_mode": { 1156 | "name": "ipython", 1157 | "version": 3 1158 | }, 1159 | "file_extension": ".py", 1160 | "mimetype": "text/x-python", 1161 | "name": "python", 1162 | "nbconvert_exporter": "python", 1163 | "pygments_lexer": "ipython3", 1164 | "version": "3.9.7" 1165 | } 1166 | }, 1167 | "nbformat": 4, 1168 | "nbformat_minor": 2 1169 | } 1170 | -------------------------------------------------------------------------------- /topics/initial-value-problems/System of Equations Example - SIR Epidemic Model - With Gaps.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# System of Equations Example - SIR Epidemic Model\n", 8 | "## CH EN 2450 - Numerical Methods\n", 9 | "**Prof. Tony Saad (www.tsaad.net)
Department of Chemical Engineering
University of Utah**\n", 10 | "
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "import numpy as np\n", 20 | "from numpy import *\n", 21 | "%matplotlib inline\n", 22 | "%config InlineBackend.figure_format = 'svg'\n", 23 | "import matplotlib.pyplot as plt\n", 24 | "from scipy.integrate import odeint" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "# The SIR Model for Epidemics" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "The SIR model for epidemics consists of three ODEs\n", 39 | "\\begin{equation}\n", 40 | "\\frac{\\text{d}S}{\\text{d}t} = -\\beta I S\n", 41 | "\\end{equation}\n", 42 | "\\begin{equation}\n", 43 | "\\frac{\\text{d}I}{\\text{d}t} = \\beta I S - \\gamma I\n", 44 | "\\end{equation}\n", 45 | "\\begin{equation}\n", 46 | "\\frac{\\text{d}R}{\\text{d}t} = \\gamma I\n", 47 | "\\end{equation}" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 2, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "def rhs_sir(PHI, t, beta, gamma, N):\n", 57 | " # PHI is the vector of dependent variables containing the 3 dependent vars: PHI=[S,I,R]\n", 58 | " S = PHI[0]\n", 59 | " I = PHI[1]\n", 60 | " R = PHI[2]\n", 61 | " dSdt = -beta/N * S * I\n", 62 | " dIdt = beta/N * S * I - gamma * I\n", 63 | " dRdt = gamma * I\n", 64 | " # you must return the RHS in a consistent order with PHI - rhs0 corresponds to phi0, etc...\n", 65 | " return [dSdt, dIdt, dRdt]" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 15, 71 | "metadata": {}, 72 | "outputs": [], 73 | "source": [ 74 | "N = 3e3 # total population\n", 75 | "I0 = 10 # 10 sick individuals\n", 76 | "R0 = 0 # 0 people recovered\n", 77 | "S0 = N - I0 # we need to conserve the total population\n", 78 | "β = 0.3\n", 79 | "γ = 1/40.0\n", 80 | "tend = 100 # days\n", 81 | "\n", 82 | "t = np.linspace(0,tend,100)\n", 83 | "# Initial conditions vector\n", 84 | "y0 = [S0, I0, R0]\n", 85 | "sol = odeint(rhs_sir, y0, t, args=(β, γ, N))\n", 86 | "S = sol[:, 0]\n", 87 | "I = sol[:, 1]\n", 88 | "R = sol[:, 2]" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 16, 94 | "metadata": {}, 95 | "outputs": [ 96 | { 97 | "data": { 98 | "image/svg+xml": [ 99 | "\n", 100 | "\n", 102 | "\n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " 2022-04-12T15:14:45.455893\n", 108 | " image/svg+xml\n", 109 | " \n", 110 | " \n", 111 | " Matplotlib v3.5.1, https://matplotlib.org/\n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | " \n", 281 | " \n", 282 | " \n", 283 | " \n", 284 | " \n", 285 | " \n", 286 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 411 | " \n", 412 | " \n", 413 | " \n", 414 | " \n", 415 | " \n", 416 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 459 | " \n", 460 | " \n", 486 | " \n", 519 | " \n", 536 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | " \n", 628 | " \n", 629 | " \n", 630 | " \n", 631 | " \n", 632 | " \n", 633 | " \n", 634 | " \n", 637 | " \n", 638 | " \n", 639 | " \n", 640 | " \n", 641 | " \n", 642 | " \n", 643 | " \n", 644 | " \n", 645 | " \n", 646 | " \n", 647 | " \n", 648 | " \n", 649 | " \n", 650 | " \n", 651 | " \n", 652 | " \n", 653 | " \n", 654 | " \n", 657 | " \n", 658 | " \n", 659 | " \n", 660 | " \n", 661 | " \n", 662 | " \n", 663 | " \n", 664 | " \n", 665 | " \n", 666 | " \n", 667 | " \n", 668 | " \n", 669 | " \n", 670 | " \n", 671 | " \n", 672 | " \n", 673 | " \n", 674 | " \n", 677 | " \n", 678 | " \n", 679 | " \n", 680 | " \n", 681 | " \n", 682 | " \n", 683 | " \n", 684 | " \n", 685 | " \n", 686 | " \n", 687 | " \n", 688 | " \n", 689 | " \n", 690 | " \n", 691 | " \n", 692 | " \n", 693 | " \n", 694 | " \n", 697 | " \n", 698 | " \n", 699 | " \n", 700 | " \n", 701 | " \n", 702 | " \n", 703 | " \n", 704 | " \n", 705 | " \n", 706 | " \n", 707 | " \n", 708 | " \n", 709 | " \n", 710 | " \n", 711 | " \n", 712 | " \n", 713 | " \n", 714 | " \n", 715 | " \n", 716 | " \n", 729 | " \n", 746 | " \n", 767 | " \n", 788 | " \n", 801 | " \n", 822 | " \n", 841 | " \n", 862 | " \n", 883 | " \n", 909 | " \n", 931 | " \n", 938 | " \n", 939 | " \n", 940 | " \n", 941 | " \n", 942 | " \n", 943 | " \n", 944 | " \n", 945 | " \n", 946 | " \n", 947 | " \n", 948 | " \n", 949 | " \n", 950 | " \n", 951 | " \n", 952 | " \n", 953 | " \n", 954 | " \n", 955 | " \n", 956 | " \n", 957 | " \n", 958 | " \n", 959 | " \n", 960 | " \n", 961 | " \n", 962 | " \n", 963 | " \n", 964 | " \n", 965 | " \n", 1066 | " \n", 1067 | " \n", 1068 | " \n", 1169 | " \n", 1170 | " \n", 1171 | " \n", 1272 | " \n", 1273 | " \n", 1274 | " \n", 1277 | " \n", 1278 | " \n", 1279 | " \n", 1282 | " \n", 1283 | " \n", 1284 | " \n", 1287 | " \n", 1288 | " \n", 1289 | " \n", 1292 | " \n", 1293 | " \n", 1294 | " \n", 1295 | " \n", 1296 | " \n", 1297 | " \n", 1328 | " \n", 1335 | " \n", 1363 | " \n", 1379 | " \n", 1404 | " \n", 1434 | " \n", 1435 | " \n", 1436 | " \n", 1437 | " \n", 1438 | " \n", 1439 | " \n", 1440 | " \n", 1441 | " \n", 1442 | " \n", 1443 | " \n", 1444 | " \n", 1445 | " \n", 1446 | " \n", 1447 | " \n", 1448 | " \n", 1449 | " \n", 1450 | " \n", 1451 | " \n", 1452 | " \n", 1453 | " \n", 1454 | " \n", 1455 | " \n", 1456 | " \n", 1457 | " \n", 1458 | " \n", 1459 | " \n", 1460 | " \n", 1461 | " \n", 1462 | " \n", 1473 | " \n", 1474 | " \n", 1475 | " \n", 1479 | " \n", 1480 | " \n", 1481 | " \n", 1482 | " \n", 1483 | " \n", 1484 | " \n", 1510 | " \n", 1511 | " \n", 1512 | " \n", 1513 | " \n", 1514 | " \n", 1515 | " \n", 1516 | " \n", 1517 | " \n", 1518 | " \n", 1519 | " \n", 1520 | " \n", 1521 | " \n", 1522 | " \n", 1523 | " \n", 1524 | " \n", 1525 | " \n", 1529 | " \n", 1530 | " \n", 1531 | " \n", 1532 | " \n", 1533 | " \n", 1534 | " \n", 1535 | " \n", 1536 | " \n", 1537 | " \n", 1538 | " \n", 1539 | " \n", 1540 | " \n", 1541 | " \n", 1542 | " \n", 1543 | " \n", 1544 | " \n", 1548 | " \n", 1549 | " \n", 1550 | " \n", 1551 | " \n", 1552 | " \n", 1553 | " \n", 1563 | " \n", 1579 | " \n", 1598 | " \n", 1599 | " \n", 1600 | " \n", 1601 | " \n", 1602 | " \n", 1603 | " \n", 1604 | " \n", 1605 | " \n", 1606 | " \n", 1607 | " \n", 1608 | " \n", 1609 | " \n", 1610 | " \n", 1611 | " \n", 1612 | " \n", 1613 | " \n", 1614 | " \n", 1615 | " \n", 1616 | " \n", 1617 | " \n", 1618 | " \n", 1619 | " \n", 1620 | " \n", 1621 | " \n", 1622 | " \n", 1623 | " \n", 1624 | " \n", 1625 | " \n", 1626 | " \n", 1627 | " \n", 1628 | " \n", 1629 | " \n", 1630 | " \n", 1631 | " \n", 1632 | "\n" 1633 | ], 1634 | "text/plain": [ 1635 | "
" 1636 | ] 1637 | }, 1638 | "metadata": { 1639 | "needs_background": "light" 1640 | }, 1641 | "output_type": "display_data" 1642 | } 1643 | ], 1644 | "source": [ 1645 | "plt.plot(t, S/N, 'b', alpha=0.65, lw=2, label='Susceptible')\n", 1646 | "plt.plot(t, I/N, 'r', alpha=0.65, lw=2, label='Infected')\n", 1647 | "plt.plot(t, R/N, 'g', alpha=0.65, lw=2, label='Recovered with immunity')\n", 1648 | "plt.xlabel('# days')\n", 1649 | "plt.ylabel('Fraction of Population')\n", 1650 | "plt.xlim(0,tend)\n", 1651 | "plt.ylim(0,1.1)\n", 1652 | "plt.legend()\n", 1653 | "plt.title('SIR Model for Pandemics')\n", 1654 | "plt.grid()\n", 1655 | "# plt.savefig('SIR model.pdf')\n", 1656 | "# plt.show()" 1657 | ] 1658 | }, 1659 | { 1660 | "cell_type": "markdown", 1661 | "metadata": {}, 1662 | "source": [ 1663 | "# Interactive Simulation" 1664 | ] 1665 | }, 1666 | { 1667 | "cell_type": "code", 1668 | "execution_count": 18, 1669 | "metadata": {}, 1670 | "outputs": [ 1671 | { 1672 | "data": { 1673 | "application/vnd.jupyter.widget-view+json": { 1674 | "model_id": "205f9aeea963498296384ec4f19883cb", 1675 | "version_major": 2, 1676 | "version_minor": 0 1677 | }, 1678 | "text/plain": [ 1679 | "HBox(children=(FloatSlider(value=0.143, continuous_update=False, description='$\\\\beta$:', max=1.0, min=0.001, …" 1680 | ] 1681 | }, 1682 | "metadata": {}, 1683 | "output_type": "display_data" 1684 | }, 1685 | { 1686 | "data": { 1687 | "application/vnd.jupyter.widget-view+json": { 1688 | "model_id": "f4aeec9f93324679a14788f96ec7c701", 1689 | "version_major": 2, 1690 | "version_minor": 0 1691 | }, 1692 | "text/plain": [ 1693 | "HBox(children=(FloatSlider(value=12.0, continuous_update=False, description='Simulation Time (months):', max=3…" 1694 | ] 1695 | }, 1696 | "metadata": {}, 1697 | "output_type": "display_data" 1698 | }, 1699 | { 1700 | "data": { 1701 | "application/vnd.jupyter.widget-view+json": { 1702 | "model_id": "7c4c190176eb45928d87394f13054a01", 1703 | "version_major": 2, 1704 | "version_minor": 0 1705 | }, 1706 | "text/plain": [ 1707 | "Output()" 1708 | ] 1709 | }, 1710 | "metadata": {}, 1711 | "output_type": "display_data" 1712 | } 1713 | ], 1714 | "source": [ 1715 | "def plot_sir(β,days,tend,semilogy=False):\n", 1716 | " N = 10 # total population\n", 1717 | " I0 = 1 # 10 sick individuals\n", 1718 | " R0 = 0 # 0 people recovered\n", 1719 | " S0 = N - I0 # we need to conserve the total population\n", 1720 | " tend = tend*30 # tend is given in months\n", 1721 | " t = np.linspace(0,tend,2*int(tend))\n", 1722 | " γ = 1.0/days\n", 1723 | " # Initial conditions vector\n", 1724 | " y0 = [S0, I0, R0]\n", 1725 | " # Integrate the SIR equations over the time grid, t.\n", 1726 | " sol = odeint(rhs_sir, y0, t, args=(N, β, γ))\n", 1727 | " [S, I, R] = sol.T\n", 1728 | " \n", 1729 | " f = plt.plot\n", 1730 | " if (semilogy):\n", 1731 | " f =plt.semilogy\n", 1732 | " f(t/30, S, 'b', alpha=0.65, lw=2, label='Susceptible')\n", 1733 | " f(t/30, I, 'r', alpha=0.65, lw=2, label='Infected')\n", 1734 | " f(t/30, R, 'g', alpha=0.65, lw=2, label='Recovered')\n", 1735 | " plt.xlabel('# months since outbreak')\n", 1736 | " plt.ylabel('# Population (1000s)')\n", 1737 | "# plt.xlim(0,tend/30)\n", 1738 | " plt.ylim(bottom=1e-4)\n", 1739 | " plt.legend()\n", 1740 | " plt.title('SIR Model for Epidemics')\n", 1741 | " plt.grid()\n", 1742 | " # plt.savefig('SIR model.pdf')\n", 1743 | " # plt.show()\n", 1744 | "import ipywidgets as widgets\n", 1745 | "from ipywidgets import interact, interact_manual\n", 1746 | "style = {'description_width': 'initial'}\n", 1747 | "β = widgets.FloatSlider(value=0.143,min=0.001,max=1,step=0.001,description='$\\\\beta$:',continuous_update=False)\n", 1748 | "days = widgets.FloatSlider(value=14,min=1,max=24,step=0.1, description='Recovery (days):' ,style=style,continuous_update=False)\n", 1749 | "tend = widgets.FloatSlider(value=12,min=1,max=32,step=0.5, description='Simulation Time (months):',style=style,continuous_update=False)\n", 1750 | "semilogy = widgets.Checkbox(value=False,description='semilogy plot', style=style)\n", 1751 | "ui1 = widgets.HBox([β,days])\n", 1752 | "ui2 = widgets.HBox([tend,semilogy])\n", 1753 | "out = widgets.interactive_output(plot_sir, {'β': β, 'days': days, 'tend': tend, 'semilogy':semilogy})\n", 1754 | "\n", 1755 | "display(ui1,ui2, out)" 1756 | ] 1757 | }, 1758 | { 1759 | "cell_type": "code", 1760 | "execution_count": null, 1761 | "metadata": {}, 1762 | "outputs": [], 1763 | "source": [] 1764 | } 1765 | ], 1766 | "metadata": { 1767 | "hide_input": false, 1768 | "kernelspec": { 1769 | "display_name": "Python 3 (ipykernel)", 1770 | "language": "python", 1771 | "name": "python3" 1772 | }, 1773 | "language_info": { 1774 | "codemirror_mode": { 1775 | "name": "ipython", 1776 | "version": 3 1777 | }, 1778 | "file_extension": ".py", 1779 | "mimetype": "text/x-python", 1780 | "name": "python", 1781 | "nbconvert_exporter": "python", 1782 | "pygments_lexer": "ipython3", 1783 | "version": "3.8.3" 1784 | } 1785 | }, 1786 | "nbformat": 4, 1787 | "nbformat_minor": 2 1788 | } 1789 | --------------------------------------------------------------------------------