Skip to content

Commit 4bebda4

Browse files
committed
Update notes
1 parent d0f8834 commit 4bebda4

File tree

4 files changed

+142
-51
lines changed

4 files changed

+142
-51
lines changed

myst.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ project:
6565
- file: ode/multistep.md
6666
- file: ode/fe_be_stability.md
6767
- file: ode/euler2.md
68+
- file: ode/rk.md
6869
- file: ode/ode_stability.md
6970
- file: ode/stiff1.md
7071
- file: ode/stiff2.md

ode/euler.md

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ numbering:
1818
```
1919

2020
```{code-cell}
21-
import numpy as np
22-
from matplotlib import pyplot as plt
21+
from pylab import *
2322
```
2423

2524
The following function implements Euler method.
@@ -31,8 +30,8 @@ $$
3130
```{code-cell}
3231
def euler(f,t0,T,y0,h):
3332
N = int((T-t0)/h)
34-
y = np.zeros(N)
35-
t = np.zeros(N)
33+
y = zeros(N)
34+
t = zeros(N)
3635
y[0] = y0
3736
t[0] = t0
3837
for n in range(1,N):
@@ -64,29 +63,28 @@ def f(t,y):
6463
return y
6564
6665
def yexact(t):
67-
return np.exp(t)
66+
return exp(t)
6867
```
6968

7069
We run the Euler method for decreasing values of step size.
7170

7271
```{code-cell}
7372
t0,y0,T = 0.0,1.0,5.0
7473
75-
te = np.linspace(t0,T,100)
74+
te = linspace(t0,T,100)
7675
ye = yexact(te)
77-
plt.plot(te,ye,'--',label='Exact')
76+
plot(te,ye,'--',label='Exact')
7877
7978
H = [0.2,0.1,0.05]
8079
8180
for h in H:
8281
t,y = euler(f,t0,T,y0,h)
83-
plt.plot(t,y,label="h="+str(h))
82+
plot(t,y,label="h="+str(h))
8483
85-
plt.legend(loc=2)
86-
plt.xlabel('t')
87-
plt.ylabel('y')
88-
plt.grid(True);
84+
legend(loc=2), xlabel('t'), ylabel('y'), grid(True);
8985
```
86+
87+
Even visually we observe that the numerical solution is converging towards the exact solution as $h \to 0$.
9088
:::
9189

9290
+++
@@ -109,10 +107,10 @@ Right hand side function and exact solution
109107

110108
```{code-cell}
111109
def f(t,y):
112-
return -y + 2.0*np.exp(-t)*np.cos(2.0*t)
110+
return -y + 2.0*exp(-t)*cos(2.0*t)
113111
114112
def yexact(t):
115-
return np.exp(-t)*np.sin(2.0*t)
113+
return exp(-t)*sin(2.0*t)
116114
```
117115

118116
**Solve for a given h**
@@ -122,40 +120,36 @@ t0,y0 = 0.0,0.0
122120
T = 10.0
123121
h = 1.0/20.0
124122
t,y = euler(f,t0,T,y0,h)
125-
te = np.linspace(t0,T,100)
123+
te = linspace(t0,T,100)
126124
ye = yexact(te)
127-
plt.plot(t,y,te,ye,'--')
128-
plt.legend(('Numerical','Exact'))
129-
plt.xlabel('t')
130-
plt.ylabel('y')
131-
plt.grid(True)
132-
plt.title('Step size = ' + str(h));
125+
plot(t,y,te,ye,'--')
126+
legend(('Numerical','Exact'))
127+
xlabel('t'), ylabel('y'), grid(True)
128+
title('Step size = ' + str(h));
133129
```
134130

135131
**Solve for several h**
136132

137133
Study the effect of decreasing step size. The error is plotted in log scale.
138134

139135
```{code-cell}
140-
hh = 0.1/2.0**np.arange(5)
141-
err= np.zeros(len(hh))
136+
hh = 0.1/2.0**arange(5)
137+
err= zeros(len(hh))
142138
for (i,h) in enumerate(hh):
143139
t,y = euler(f,t0,T,y0,h)
144140
ye = yexact(t)
145-
err[i] = np.abs(y-ye).max()
146-
plt.semilogy(t,np.abs(y-ye))
141+
err[i] = abs(y-ye).max()
142+
semilogy(t,abs(y-ye))
147143
148-
plt.legend(hh)
149-
plt.xlabel('t')
150-
plt.ylabel('log(error)')
144+
legend(hh), xlabel('t'), ylabel('log(error)')
151145
152146
for i in range(1,len(hh)):
153-
print('%e %e %e'%(hh[i],err[i],np.log(err[i-1]/err[i])/np.log(2.0)))
147+
print('%e %e %e'%(hh[i],err[i],log(err[i-1]/err[i])/log(2.0)))
154148
155149
# plot error vs h
156-
plt.figure()
157-
plt.loglog(hh,err,'o-',label="Error")
158-
plt.loglog(hh,hh,'--',label="y=h")
159-
plt.legend(), plt.xlabel('h'), plt.ylabel('Error norm');
150+
figure()
151+
loglog(hh,err,'o-',label="Error")
152+
loglog(hh,hh,'--',label="y=h")
153+
legend(), xlabel('h'), ylabel('Error norm');
160154
```
161155
:::

ode/rk.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
exports:
3+
- format: pdf
4+
kernelspec:
5+
display_name: Python 3 (ipykernel)
6+
language: python
7+
name: python3
8+
numbering:
9+
code: false
10+
equation: true
11+
title: true
12+
headings: true
13+
---
14+
15+
# Runge-Kutta method
16+
17+
```{include} ../math.md
18+
```
19+
20+
```{code-cell}
21+
from pylab import *
22+
```
23+
24+
+++
25+
26+
:::{prf:example} Harmonic oscillator
27+
We repeat the previous example with RK method.
28+
29+
```{code-cell}
30+
y0 = 1.0
31+
omega = 4.0
32+
h = 0.1
33+
34+
A = matrix([[0.0, 1.0],
35+
[-omega**2, 0.0]])
36+
hA = h * A
37+
A2 = eye(2) + hA + (1.0/2.0)*hA**2
38+
A4 = eye(2) + hA + (1.0/2.0)*hA**2 + (1.0/6.0)*hA**3 + (1.0/24.0)*hA**4
39+
40+
n = int(2*pi/h)
41+
y2, y4 = zeros((n,2)), zeros((n,2))
42+
y2[0,0] = y0
43+
y4[0,0] = y0
44+
t = zeros(n)
45+
for i in range(1,n):
46+
y2[i,:] = A2 @ y2[i-1,:]
47+
y4[i,:] = A4 @ y4[i-1,:]
48+
t[i] = t[i-1] + h
49+
50+
plot(t, cos(omega*t),'--',label="Exact")
51+
plot(t,y2[:,0],label="RK2")
52+
plot(t,y4[:,0],label="RK4")
53+
axis([0, 2*pi,-2,2])
54+
legend(), xlabel("t"), ylabel("$\\theta$");
55+
```
56+
57+
The solution from RK2 is growing with time, no matter how small a time step we take. RK4 will be conditionally stable, if $h < 2\sqrt{2}/\omega \approx 0.707$.
58+
:::
59+
60+
:::{prf:example} Stability regions of RK
61+
62+
```{code-cell}
63+
r2 = lambda z: 1 + z + z**2/2
64+
r3 = lambda z: 1 + z + z**2/2 + z**3/6
65+
r4 = lambda z: 1 + z + z**2/2 + z**3/6 + z**4/24
66+
67+
n = 100
68+
x = linspace(-3,0.5,n)
69+
y = linspace(-3,3,n)
70+
X,Y = meshgrid(x,y)
71+
Z2 = r2(X + 1j*Y)
72+
Z3 = r3(X + 1j*Y)
73+
Z4 = r4(X + 1j*Y)
74+
contour(X,Y,abs(Z2),levels=[1],colors="black")
75+
contour(X,Y,abs(Z3),levels=[1],colors="blue")
76+
contour(X,Y,abs(Z4),levels=[1],colors="red")
77+
xlabel('real(z)'), ylabel('imag(z)')
78+
title('Stability domain of RK2, RK3, RK4')
79+
grid(True), axis('equal');
80+
```
81+
82+
Zoomed view around the imaginary axis
83+
84+
```{code-cell}
85+
contour(X,Y,abs(Z2),levels=[1],colors="black")
86+
contour(X,Y,abs(Z3),levels=[1],colors="blue")
87+
contour(X,Y,abs(Z4),levels=[1],colors="red")
88+
axis([-0.3, 0.3, -3, 3])
89+
xlabel('real(z)'), ylabel('imag(z)')
90+
title('Stability domain of RK2, RK3, RK4')
91+
grid(True);
92+
```
93+
94+
RK2 does not enclose any portion of the imaginary axis, it is tangential to it, while RK3 and RK4 enclose a part of the imaginary axis. In case of RK4, the interval $[ -\ii 2\sqrt{2}, \ii 2\sqrt{2}]$ is inside the stability domain.
95+
:::

ode/shooting.md

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ kernelspec:
1515

1616
+++
1717

18+
:::{prf:example}
1819
Consider the BVP
1920

2021
$$
@@ -33,11 +34,7 @@ $$
3334
y(x) = (e^x + e^{-x})^{-1}
3435
$$
3536

36-
+++
37-
38-
## Formulate as an initial value problem
39-
40-
+++
37+
**Formulate as an initial value problem**
4138

4239
$$
4340
y'' = -y + \frac{2 (y')^2}{y}, \qquad -1 < x < +1
@@ -55,11 +52,7 @@ $$
5552
\phi(s) = y(1;s) - (e + e^{-1})^{-1} = 0
5653
$$
5754

58-
+++
59-
60-
## Newton method
61-
62-
+++
55+
**Newton method**
6356

6457
To find the root of $\phi(s)$, we use Newton method with an initial guess $s_0$. Then the Newton method updates the guess by
6558

@@ -84,32 +77,37 @@ The derivative of $\phi(s)$ is given by
8477
$$
8578
\frac{d}{ds}\phi(s) = \frac{\partial}{\partial s} y(1;s) = z_s(1)
8679
$$
80+
8781
We can write an equation for $z_s(x)$
82+
8883
$$
8984
z_s'' = \left[ -1 - 2 \left( \frac{y'}{y} \right)^2 \right] z_s + 4 \frac{y'}{y} z_s'
9085
$$
86+
9187
with initial conditions
88+
9289
$$
9390
z_s(-1) = 0, \qquad z_s'(-1) = 1
9491
$$
9592

96-
+++
97-
98-
## First order ODE system
99-
100-
+++
93+
**First order ODE system**
10194

10295
Define the vector
96+
10397
$$
10498
u = \begin{bmatrix}
10599
u_1 \\ u_2 \\ u_3 \\ u_4 \end{bmatrix} = \begin{bmatrix}
106100
y \\ y' \\ z_s \\ z_s' \end{bmatrix}
107101
$$
102+
108103
Then
104+
109105
$$
110106
u_1' = u_2, \qquad u_2' = -u_1 + \frac{2 u_2^2}{u_1}, \qquad u_3' = u_4, \qquad u_4' = \left[ -1 - 2 \left( \frac{u_2}{u_1} \right)^2 \right] u_3 + 4 \frac{u_2}{u_1} u_4
111107
$$
108+
112109
Hence we get the first order ODE system
110+
113111
$$
114112
u' = f(u) = \begin{bmatrix}
115113
u_2 \\
@@ -118,7 +116,9 @@ u_4 \\
118116
\left[ -1 - 2 \left( \frac{u_2}{u_1} \right)^2 \right] u_3 + 4 \frac{u_2}{u_1} u_4
119117
\end{bmatrix}
120118
$$
119+
121120
with initial condition
121+
122122
$$
123123
u(-1) = \begin{bmatrix}
124124
(e+e^{-1})^{-1} \\
@@ -127,14 +127,14 @@ s \\
127127
1
128128
\end{bmatrix}
129129
$$
130+
130131
Once we solve this IVP, we get
132+
131133
$$
132134
\phi(s) = u_1(1) - (e + e^{-1})^{-1}, \qquad \frac{d}{ds}\phi(s) = z_s(1) = u_3(1)
133135
$$
134136

135-
+++
136-
137-
## Now we start coding
137+
**Now we start coding**
138138

139139
```{code-cell}
140140
import numpy as np
@@ -223,3 +223,4 @@ plt.grid(True)
223223
plt.title('Final solution')
224224
plt.legend(("Numerical","Exact"));
225225
```
226+
:::

0 commit comments

Comments
 (0)