|
| 1 | + |
| 2 | +<html> |
| 3 | +<head> |
| 4 | +<script type="text/x-mathjax-config">MathJax.Hub.Config({ tex2jax: {inlineMath: [["$","$"] ]}});</script> |
| 5 | +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_HTML-full"> |
| 6 | +</script> |
| 7 | +<meta charset='utf-8'> |
| 8 | +</head> |
| 9 | +<body> |
| 10 | + |
| 11 | +<h1>Chapter 10</h1> |
| 12 | +<p>Example 1</p> |
| 13 | +<p>A line integral is an integral of a function along a curve in |
| 14 | +space. We usually represent the curve by a parametric equation, |
| 15 | +e.g. $\mathbf{r}(t) = [x(t), y(t), z(t)] = x(t)\mathbf{i} + |
| 16 | +y(t)\mathbf{j} + z(t)\mathbf{k}$. So, in general the curve will be a |
| 17 | +vector function, and the function we want to integrate will also be a |
| 18 | +vector function.</p> |
| 19 | +<p>Then, we can write the line integral definition as:</p> |
| 20 | +<p>$$ |
| 21 | +\int_C \mathbf{F(r)}\cdot d\mathbf{r} = |
| 22 | +\int_a^b \mathbf{F}(\mathbf{r}(t)) \cdot \mathbf{r'}(t) dt |
| 23 | +$$</p> |
| 24 | +<p>where $\mathbf{r'}(t) = \frac{d\mathbf{r}}{dt}$. This integrand is a |
| 25 | +scalar function, because of the dot product.</p> |
| 26 | +<p>The following examples are adapted from Chapter 10 in Advanced |
| 27 | +Engineering Mathematics by Kreysig.</p> |
| 28 | +<p>The first example is the evaluation of a line integral in the |
| 29 | +plane. We want to evaluate the integral of $\mathbf{F(r)}=[-y, -xy]$ |
| 30 | +on the curve $\mathbf{r(t)}=[-sin(t), cos(t)]$ from t=0 to t = |
| 31 | +π/2. The answer in the book is given as 0.4521. Here we evaluate this |
| 32 | +numerically, using autograd for the relevant derivative. Since the |
| 33 | +curve has multiple outputs, we have to use the jacobian function to |
| 34 | +get the derivatives. After that, it is a simple bit of matrix |
| 35 | +multiplication, and a call to the quad function.</p> |
| 36 | +<pre><code class="python">import autograd.numpy as np |
| 37 | +from autograd import jacobian |
| 38 | +from scipy.integrate import quad |
| 39 | + |
| 40 | +def F(X): |
| 41 | + x, y = X |
| 42 | + return -y, -x * y |
| 43 | + |
| 44 | +def r(t): |
| 45 | + return np.array([-np.sin(t), np.cos(t)]) |
| 46 | + |
| 47 | +drdt = jacobian(r) |
| 48 | + |
| 49 | +def integrand(t): |
| 50 | + return F(r(t)) @ drdt(t) |
| 51 | + |
| 52 | +I, e = quad(integrand, 0.0, np.pi / 2) |
| 53 | +print(f'The integral is {I:1.4f}.') |
| 54 | +</code></pre> |
| 55 | + |
| 56 | +<pre><code class="text">The integral is 0.4521. |
| 57 | +</code></pre> |
| 58 | + |
| 59 | +<p>We get the same result as the analytical solution.</p> |
| 60 | +<p>The next example is in three dimensions. Find the line integral along |
| 61 | +$\mathbf{r}(t)=[cos(t), sin(t), 3t]$ of the function |
| 62 | +$\mathbf{F(r)}=[z, x, y]$ from t=0 to t=2 π. The solution is given as |
| 63 | +21.99.</p> |
| 64 | +<pre><code class="python">import autograd.numpy as np |
| 65 | +from autograd import elementwise_grad, grad, jacobian |
| 66 | + |
| 67 | +def F(X): |
| 68 | + x, y, z = X |
| 69 | + return [z, x, y] |
| 70 | + |
| 71 | +def C(t): |
| 72 | + return np.array([np.cos(t), np.sin(t), 3 * t]) |
| 73 | + |
| 74 | +dCdt = jacobian(C, 0) |
| 75 | + |
| 76 | +def integrand(t): |
| 77 | + return F(C(t)) @ dCdt(t) |
| 78 | + |
| 79 | +I, e = quad(integrand, 0, 2 * np.pi) |
| 80 | +print(f'The integral is {I:1.2f}.') |
| 81 | +</code></pre> |
| 82 | + |
| 83 | +<pre><code class="text">The integral is 21.99. |
| 84 | +</code></pre> |
| 85 | + |
| 86 | +<p>That is also the same as the analytical solution. Note the real |
| 87 | +analytical solution was 7 π, which is nearly equivalent to our answer.</p> |
| 88 | +<pre><code class="python">print (7 * np.pi - I) |
| 89 | +</code></pre> |
| 90 | + |
| 91 | +<pre><code class="text">3.552713678800501e-15 |
| 92 | +</code></pre> |
| 93 | + |
| 94 | +<p>As a final example, we consider an alternate form of the line |
| 95 | +integral. In this form we do not use a dot product, so the integral |
| 96 | +results in a vector. This doesn't require anything from autograd, but |
| 97 | +does require us to be somewhat clever in how to do the integrals since |
| 98 | +quad can only integrate scalar functions. We need to integrate each |
| 99 | +component of the integrand independently. Here is one approach where |
| 100 | +we use lambda functions for each component. You could also manually |
| 101 | +separate the components.</p> |
| 102 | +<pre><code class="python">def F(r): |
| 103 | + x, y, z = r |
| 104 | + return x * y, y * z, z |
| 105 | + |
| 106 | +def r(t): |
| 107 | + return np.array([np.cos(t), np.sin(t), 3 * t]) |
| 108 | + |
| 109 | +def integrand(t): |
| 110 | + return F(r(t)) |
| 111 | + |
| 112 | +[quad(lambda t: integrand(t)[i], 0, 2 * np.pi)[0] for i in [0, 1, 2]] |
| 113 | +</code></pre> |
| 114 | + |
| 115 | +<pre><code class="text">Out[1]: [-6.845005548807377e-17, -18.849555921538755, 59.21762640653615] |
| 116 | +</code></pre> |
| 117 | + |
| 118 | +<pre><code class="python">[0, -6 * np.pi, 6 * np.pi**2] |
| 119 | +</code></pre> |
| 120 | + |
| 121 | +<pre><code class="text">Out[1]: [0, -18.84955592153876, 59.21762640653615] |
| 122 | +</code></pre> |
| 123 | + |
| 124 | +<p>which is evidently the same as our numerical solution.</p> |
| 125 | +<p>Maybe an alternative, but more verbose is this vectorized integrate |
| 126 | +function. We still make temporary functions for integrating, and the |
| 127 | +vectorization is essentially like the list comprehension above, but we |
| 128 | +avoid the lambda functions.</p> |
| 129 | +<pre><code class="python">@np.vectorize |
| 130 | +def integrate(i): |
| 131 | + def integrand(t): |
| 132 | + return F(r(t))[i] |
| 133 | + I, e = quad(integrand, 0, 2 * np.pi) |
| 134 | + return I |
| 135 | + |
| 136 | +integrate([0, 1, 2]) |
| 137 | +</code></pre> |
| 138 | + |
| 139 | +<pre><code class="text">Out[1]: array([-6.84500555e-17, -1.88495559e+01, 5.92176264e+01]) |
| 140 | +</code></pre> |
| 141 | + |
| 142 | +</body> |
| 143 | +</html> |
| 144 | + |
0 commit comments