Files
cds-numerical-methods/Week 5/9 Ordinary Differential Equations.ipynb
2022-03-08 10:26:52 +01:00

15 KiB

CDS: Numerical Methods Assignments

  • See lecture notes and documentation on Brightspace for Python and Jupyter basics. If you are stuck, try to google or get in touch via Discord.

  • Solutions must be submitted via the Jupyter Hub.

  • Make sure you fill in any place that says YOUR CODE HERE or "YOUR ANSWER HERE".

Submission

  1. Name all team members in the the cell below
  2. make sure everything runs as expected
  3. restart the kernel (in the menubar, select Kernel$\rightarrow$Restart)
  4. run all cells (in the menubar, select Cell$\rightarrow$Run All)
  5. Check all outputs (Out[*]) for errors and resolve them if necessary
  6. submit your solutions in time (before the deadline)
team_members = ""

Ordinary Differential Equations - Initial Value Problems

In the following you will implement your own easy-to-extend ordinary differential equation (ODE) solver, which can be used to solve first order ODE systems of the form

\begin{align*} \vec{y}'(x) = \vec{f}(x, \vec{y}), \end{align*}

for $x = x_0, x_1, \dots, x_n$ with $x_i = i h$, step size $h$, and an initial condition of the form $\vec{y}(x=0)$. The solver will be capable of using single-step as well as multi-step approaches.

In [ ]:
# Import packages here ...

# YOUR CODE HERE
raise NotImplementedError()

Task 1

Implement the Euler method in a general Python function $\text{integrator(x, y0, f, phi)}$, which takes as input a one-dimensional array $x$ of size $n+1$, the initial condition $y_0$, the callable function $f(x, y)$, and the integration scheme $\Phi(x, y, f, i)$. It should return the approximated function $\tilde{y}(x)$.

The integration scheme $\text{phi}$ is supposed to be a callable function as returned from another Python function $\text{phi_euler(x, y, f, i)}$, where $i$ is the step number. In this way we will be able to easily extend the ODE solver to different methods.

In [ ]:
def integrator(x, y0, f, phi):
    # YOUR CODE HERE
    raise NotImplementedError()
In [ ]:
def phi_euler(x, y, f, i):
    # YOUR CODE HERE
    raise NotImplementedError()

Task 2

Debug your implementation by applying it to the following ODE

\begin{align*} \vec{y}'(x) = y - x^2 + 1.0, \end{align*}

with initial condition $y(x=0) = 0.5$. To this end, define the right-hand side of the ODE as a Python function $\text{ODEF(x, y)}$, which in this case returns $f(x,y) = y - x^2 + 1.0$. You can then hand over the function $\text{ODEF}$ to the argument $\text{f}$ of your $\text{integrator}$ function.

Plot the solution you found with the Euler method together with the exact solution $y(x) = (x+1)^2 - 0.5 e^x$.

Then implement a unit test for your $\text{integrator}$ function using this system.

In [ ]:
# Do your plotting and your own testing here ...

# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
def test_integrator():
    # YOUR CODE HERE
    raise NotImplementedError()
    
test_integrator()

Task 3

Extend the set of possible single-step integration schemes to the modified Euler (Collatz), Heun, and 4th-order Runge-Kutta approaches by implementing the functions $\text{phi_euler_modified(x, y, f, i)}$, $\text{phi_heun(x, y, f, i)}$, and $\text{phi_rk4(x, y, f, i)}$. These can be used in your $\text{integrator}$ function instead of $\text{phi_euler}$.

In [ ]:
def phi_euler_modified(x, y, f, i):
    # YOUR CODE HERE
    raise NotImplementedError()
    
def phi_heun(x, y, f, i):
    # YOUR CODE HERE
    raise NotImplementedError()
    
def phi_rk4(x, y, f, i):
    # YOUR CODE HERE
    raise NotImplementedError()

Task 4

Add the possibility to also handle the following multi-step integration schemes:

\begin{align*} \Phi_{AB3}(x, y, f, i) = \frac{1}{12} \left[ 23 f(x_i, y_i) - 16 f(x_{i-1}, y_{i-1}) + 5 f(x_{i-2}, y_{i-2}) \right] \end{align*}

and

\begin{align*} \Phi_{AB4}(x, y, f, i) = \frac{1}{24} \left[ 55 f(x_i, y_i) - 59 f(x_{i-1}, y_{i-1}) + 37 f(x_{i-2}, y_{i-2}) - 9 f(x_{i-3}, y_{i-3}) \right] \end{align*}

In these cases the initial condition $\text{y0}$ must be an array consisting of several initial values corresponding to $y_0$, $y_1$, $y_2$ (and $y_3$). Use the Runga-Kutta method to calculate all of the initial values before you start the AB3 and AB4 integrations.

In [ ]:
def phi_ab3(x, y, f, i):
    # YOUR CODE HERE
    raise NotImplementedError()

def phi_ab4(x, y, f, i):
    # YOUR CODE HERE
    raise NotImplementedError()

Task 5

Plot the absolute errors $\delta(x) = |\tilde{y}(x) - y(x)|$ with a $y$-log scale for all approaches with $0 \leq x \leq 2$ and a step size of $h=0.02$ for the ODE from task 2.

In [ ]:
# YOUR CODE HERE
raise NotImplementedError()

Task 6

Study the accuracies of all approaches as a function of the step size $h$. To this end use your implementations to solve

\begin{align*} \vec{y}'(x) = y \end{align*}

with $y(x=0) = 1.0$ for $0 \leq x \leq 2$.

Plot $\delta(2) = |\tilde{y}(2) - y(2)|$ as a function of $h$ for each integration scheme.

In [ ]:
# YOUR CODE HERE
raise NotImplementedError()

Task 7

Apply the Euler and the Runga-Kutta methods to solve the pendulum problem given by

\begin{align*} \vec{y}'(x) = \vec{f}(x, \vec{y}) \quad \leftrightarrow \quad \begin{pmatrix} y_0'(x) \\ y_1'(x) \end{pmatrix} = \begin{pmatrix} y_1(x) \\ -\operatorname{sin}\left[y_0(x) \right] \end{pmatrix} \end{align*}

To this end the quantities $\text{x}$ and $\text{y0}$ in your $\text{integrator}$ function must become vectors. Depending on your implementation in task 1 you might have to define a new $\text{integrator}$ function that can handle this type of input.

Plot $y_0(x)$ for several oscillation periods. Does the Euler method behave physically?

In [ ]:
# YOUR CODE HERE
raise NotImplementedError()