<a href="https://colab.research.google.com/github/john-s-butler-dit/Numerical-Analysis-Python/blob/master/Chapter%2004%20-%20Multistep%20Methods/404_Adams%20Moulton%20Population%20Equations.ipynb" target="_parent"></a>

# 1 Step Adams Moulton 
#### John S Butler 
john.s.butler@tudublin.ie  
[Course Notes](https://johnsbutler.netlify.com/files/Teaching/Numerical_Analysis_for_Differential_Equations.pdf)    [Github](https://github.com/john-s-butler-dit/Numerical-Analysis-Python)


This notebook implements the 1 step Adams Moulton method for three different population intial value problems.

# Formula
The general 1 step Adams-Moulton method for the first order differential equation
\begin{equation} y^{'} = f(t,y) \end{equation}
numerical approximates $y$ the at time point $t_i$ as $w_i$
with the  formula:
\begin{equation} w_{i+1}=w_i+\frac{h}{2}\big[f(t_{i+1},w_{i+1})+f(t_{i},w_{i})\big],\end{equation}
for $i=0,...,N-1$, where 

and $h$ is the stepsize.

To illustrate the method we will apply it to three intial value problems:
## 1. Linear 
Consider the linear population Differential Equation
\begin{equation} y^{'}=0.1y, \ \ (2000 \leq t \leq 2020), \end{equation}
with the initial condition,
\begin{equation}y(2000)=6.\end{equation}

## 2. Non-Linear Population Equation 
Consider the non-linear population Differential Equation
\begin{equation} y^{'}=0.2y-0.01y^2, \ \ (2000 \leq t \leq 2020), \end{equation}
with the initial condition,
\begin{equation}y(2000)=6.\end{equation}

## 3. Non-Linear Population Equation with an oscillation 
Consider the non-linear population Differential Equation with an oscillation 
\begin{equation} y^{'}=0.2y-0.01y^2+\sin(2\pi t), \ \ (2000 \leq t \leq 2020), \end{equation}
with the initial condition,
\begin{equation}y(2000)=6.\end{equation}

#### Setting up Libraries


```python
## Library
import numpy as np
import math 
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt # side-stepping mpl backend
import matplotlib.gridspec as gridspec # subplots
import warnings

warnings.filterwarnings("ignore")
```

## Discrete Interval
The continuous time $a\leq t \leq b $ is discretised into $N$ points seperated by a constant stepsize
\begin{equation} h=\frac{b-a}{N}.\end{equation}
Here the interval is $2000\leq t \leq 2020,$ 
\begin{equation} h=\frac{2020-2000}{200}=0.1.\end{equation}
This gives the 201 discrete points:
\begin{equation} t_0=2000, \ t_1=2000.1, \ ... t_{200}=2020. \end{equation}
This is generalised to 
\begin{equation} t_i=2000+i0.1, \ \ \ i=0,1,...,200.\end{equation}
The plot below shows the discrete time steps:


```python
### DISCRETE TIME
N=20
t_end=2020.0
t_start=2000.0
h=((t_end-t_start)/N)
t=np.arange(t_start,t_end+h/2,h)

## PLOTS TIME
fig = plt.figure(figsize=(10,4))
plt.plot(t,0*t,'o:',color='red')
plt.title('Illustration of discrete time points for h=%s'%(h))
plt.show()
len(t)
```

# 1. Linear Population Equation
## Exact Solution 
The linear population equation
\begin{equation} y^{'}=0.1y, \ \ (2000 \leq t \leq 2020), \end{equation}
with the initial condition,
\begin{equation}y(2000)=6.\end{equation}
has a known exact (analytic) solution
\begin{equation} y(t)=6e^{0.1(t-2000)}. \end{equation}

## Specific 1 step Adams Moulton
The specific 1 step Adams Moulton for the linear population equation is:

\begin{equation}w_{i+1}=w_{i}+\frac{h}{2}\big[0.1w_{i+1}+0.1w_i\big] \end{equation}
where
\begin{equation}f(t,y)=0.1y,\end{equation}


```python
## THIS IS THE RIGHT HANDSIDE OF THE LINEAR POPULATION DIFFERENTIAL 
## EQUATION
def linfun(t,w):
    ftw=0.1*w
    return ftw
```

re-arranging,
\begin{equation} \big(1-\frac{h}{2}(0.1)\big)w_{i+1}=w_i+\frac{h}{2}\big[0.1w_i\big], \end{equation}
\begin{equation} w_{i+1}=\frac{w_i+\frac{h}{2}\big[0.1w_i\big]}{\big(1-\frac{h}{2}(0.1)\big)}. \end{equation}





```python
### INSERT METHOD HERE
w=np.zeros(N+1) # a list of 2000+1 zeros
w[0]=6 # INITIAL CONDITION
for i in range(0,N):
    w[i+1]=(w[i]+h/2*(linfun(t[i],w[i])))/(1-0.1*h/2)

```

## Plotting Results


```python
## PLOTTING METHOD
y=6*np.exp(0.1*(t-2000)) # EXACT SOLUTION
fig = plt.figure(figsize=(8,4))
plt.plot(t,w,'o:',color='purple',label='Taylor')
plt.plot(t,y,'s:',color='black',label='Exact')
plt.legend(loc='best')
plt.show()
```

## Table
The table below shows the time, the numerical approximation, $w$,  the exact solution, $y$, and the exact error $|y(t_i)-w_i|$ for the linear population equation:


```python
d = {'time t_i': t, 'Adams Approx w': w}
df = pd.DataFrame(data=d)
df
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>time t_i</th>
      <th>Adams Approx w</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2000.0</td>
      <td>6.000000</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2001.0</td>
      <td>6.631579</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2002.0</td>
      <td>7.329640</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2003.0</td>
      <td>8.101181</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2004.0</td>
      <td>8.953937</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2005.0</td>
      <td>9.896456</td>
    </tr>
    <tr>
      <th>6</th>
      <td>2006.0</td>
      <td>10.938189</td>
    </tr>
    <tr>
      <th>7</th>
      <td>2007.0</td>
      <td>12.089577</td>
    </tr>
    <tr>
      <th>8</th>
      <td>2008.0</td>
      <td>13.362164</td>
    </tr>
    <tr>
      <th>9</th>
      <td>2009.0</td>
      <td>14.768708</td>
    </tr>
    <tr>
      <th>10</th>
      <td>2010.0</td>
      <td>16.323308</td>
    </tr>
    <tr>
      <th>11</th>
      <td>2011.0</td>
      <td>18.041551</td>
    </tr>
    <tr>
      <th>12</th>
      <td>2012.0</td>
      <td>19.940662</td>
    </tr>
    <tr>
      <th>13</th>
      <td>2013.0</td>
      <td>22.039679</td>
    </tr>
    <tr>
      <th>14</th>
      <td>2014.0</td>
      <td>24.359645</td>
    </tr>
    <tr>
      <th>15</th>
      <td>2015.0</td>
      <td>26.923819</td>
    </tr>
    <tr>
      <th>16</th>
      <td>2016.0</td>
      <td>29.757905</td>
    </tr>
    <tr>
      <th>17</th>
      <td>2017.0</td>
      <td>32.890316</td>
    </tr>
    <tr>
      <th>18</th>
      <td>2018.0</td>
      <td>36.352454</td>
    </tr>
    <tr>
      <th>19</th>
      <td>2019.0</td>
      <td>40.179029</td>
    </tr>
    <tr>
      <th>20</th>
      <td>2020.0</td>
      <td>44.408400</td>
    </tr>
  </tbody>
</table>
</div>



## 2. Non-Linear Population Equation 
\begin{equation} y^{'}=0.2y-0.01y^2, \ \ (2000 \leq t \leq 2020), \end{equation}
with the initial condition,
\begin{equation}y(2000)=6.\end{equation}
## Specific 1 step Adams-Moutlon method for the Non-Linear Population Equation
The specific Adams-Moulton difference equation for the non-linear population equations is:

\begin{equation}w_{i+1}=w_{i}+\frac{h}{2}\big[ 0.2 w_{i+1}-0.01 w_{i+1}^2 
                                + 0.2 w_i-0.01 w_i^2\big] \end{equation}
re-arranging 
\begin{equation}w_{i+1}-\frac{h}{2}\big( 0.2 w_{i+1}-0.01 w_{i+1}^2 \big)=w_{i}+\frac{h}{2}
                                \big[ 0.2 w_i-0.01 w_i^2\big] \end{equation}


for $i=0,...,199$, where $w_i$ is the numerical approximation of $y$ at time $t_i$, with step size $h$ and the initial condition
\begin{equation}w_0=6.\end{equation}

PROBLEM WE CANNOT MOVE THE SQUARED (NON-LINEAR TERM) TO THE RIGHT HAND SIDE SO WE CAN SOLVE FOR w[i+1].
For this reason we will use a predictor-corrector method,
The predictor will be the 2-step Adams Bashforth
\begin{equation} w_{i+1}^{p}=w_{i}+\frac{h}{2}\big[ 3(0.2 w_{i}-0.01 w_{i}^2) 
                                - (0.2 w_{i-1}-0.01 w_{i-1}^2) \big], \end{equation}
with the corrector being the 1-step Adams Moulton,
\begin{equation}w_{i+1}=w_{i}+\frac{h}{2}\big[ 0.2 w_{i+1}^p-0.01 (w^p_{i+1})^2 
                                + 0.2 w_i-0.01 w_i^2\big], \end{equation}      
for i=1,...200.
                                


```python
def nonlinfun(t,w):
    ftw=0.2*w-0.01*w*w
    return ftw
```


```python
### INSERT METHOD HERE
w=np.zeros(N+1)
w_p=np.zeros(N+1)
w[0]=6
w[1]=6.084 # FROM THE THE TAYLOR METHOD
w_p[0]=6
w_p[1]=6.084 # FROM THE THE TAYLOR METHOD
for n in range(1,N):
    ## Predictor
    w_p[n+1]=w[n]+h/2*(3*nonlinfun(t[n],w[n])-
                       nonlinfun(t[n-1],w[n-1]))
    ## Corrector
    w[n+1]=w[n]+h/2*(nonlinfun(t[n+1],w_p[n+1])+
                       nonlinfun(t[n],w[n]))
```

## Results
The plot below shows the numerical approximation, $w$ (circles) for the non-linear population equation:


```python
fig = plt.figure(figsize=(8,4))
plt.plot(t,w,'-.',color='purple',label='Correcter ')
plt.plot(t,w_p,':',color='red',label='Predictor ')

plt.title('Non Linear Population Equation')
plt.legend(loc='best')
plt.xlabel('time (yrs)')
plt.ylabel('Population in billions')
plt.show()

fig = plt.figure(figsize=(8,4))
plt.plot(t,np.abs(w-w_p),':',color='purple',label='|w-w_p| ')
plt.title('Comparison of Predictor and Corrector')
plt.legend(loc='best')
plt.xlabel('time (yrs)')
plt.ylabel('Population in billions')
plt.show()


```

## Table
The table below shows the time and the numerical approximation, $w$,  for the non-linear population equation:


```python
d = {'time t_i': t, 'Adams Approx w': w}
df = pd.DataFrame(data=d)
df
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>time t_i</th>
      <th>Adams Approx w</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2000.0</td>
      <td>6.000000</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2001.0</td>
      <td>6.084000</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2002.0</td>
      <td>6.960322</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2003.0</td>
      <td>7.892040</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2004.0</td>
      <td>8.863456</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2005.0</td>
      <td>9.856908</td>
    </tr>
    <tr>
      <th>6</th>
      <td>2006.0</td>
      <td>10.853082</td>
    </tr>
    <tr>
      <th>7</th>
      <td>2007.0</td>
      <td>11.832473</td>
    </tr>
    <tr>
      <th>8</th>
      <td>2008.0</td>
      <td>12.776881</td>
    </tr>
    <tr>
      <th>9</th>
      <td>2009.0</td>
      <td>13.670688</td>
    </tr>
    <tr>
      <th>10</th>
      <td>2010.0</td>
      <td>14.501747</td>
    </tr>
    <tr>
      <th>11</th>
      <td>2011.0</td>
      <td>15.261810</td>
    </tr>
    <tr>
      <th>12</th>
      <td>2012.0</td>
      <td>15.946493</td>
    </tr>
    <tr>
      <th>13</th>
      <td>2013.0</td>
      <td>16.554881</td>
    </tr>
    <tr>
      <th>14</th>
      <td>2014.0</td>
      <td>17.088907</td>
    </tr>
    <tr>
      <th>15</th>
      <td>2015.0</td>
      <td>17.552635</td>
    </tr>
    <tr>
      <th>16</th>
      <td>2016.0</td>
      <td>17.951549</td>
    </tr>
    <tr>
      <th>17</th>
      <td>2017.0</td>
      <td>18.291930</td>
    </tr>
    <tr>
      <th>18</th>
      <td>2018.0</td>
      <td>18.580348</td>
    </tr>
    <tr>
      <th>19</th>
      <td>2019.0</td>
      <td>18.823293</td>
    </tr>
    <tr>
      <th>20</th>
      <td>2020.0</td>
      <td>19.026909</td>
    </tr>
  </tbody>
</table>
</div>



## 3. Non-Linear Population Equation with an oscilation 
\begin{equation} y^{'}=0.2y-0.01y^2+\sin(2\pi t), \ \ (2000 \leq t \leq 2020), \end{equation}
with the initial condition,
\begin{equation}y(2000)=6.\end{equation}

## Specific 2 Step Adams Moulton for the Non-Linear Population Equation with an oscilation

The specific Adams-Moulton difference equation for the non-linear population equations is:

           
\begin{equation}w_{i+1}=w_{i}+\frac{h}{2}\big[ 0.2 w_{i+1}-0.01 w_{i+1}^2 +\sin(2\pi t_{i+1})
                                + 0.2 w_i-0.01 w_i^2+\sin(2\pi t_{i})\big] \end{equation}


for $i=1,...,199$, where $w_i$ is the numerical approximation of $y$ at time $t_i$, with step size $h$ and the initial condition
\begin{equation}w_0=6.\end{equation}

 As $w_1$ is required for the method but unknown we will use the numerical solution of a one step method to approximate the value. Here, we use the 2nd order Runge Kutta approximation (see [Runge Kutta notebook](https://github.com/john-s-butler-dit/Numerical-Analysis-Python/blob/master/Chapter%2003%20-%20Runge%20Kutta/01_2nd%20Order%20Runge%20Kutta%20Population%20Equations.ipynb) )
\begin{equation}w_1=6.11.\end{equation}


PROBLEM WE CANNOT MOVE THE SQUARED (NON-LINEAR TERM) TO THE RIGHT HAND SIDE SO WE CAN SOLVE FOR w[i+1].
For this reason we will use a predictor-corrector method,
The predictor will be the 2-step Adams Bashforth
\begin{equation} w_{i+1}^{p}=w_{i}+\frac{h}{2}\big[ 3(0.2 w_{i}-0.01 w_{i}^2+\sin(2\pi t_{i}) 
                                - (0.2 w_{i-1}-0.01 w_{i-1}^2+\sin(2\pi t_{i-1}) \big] \end{equation}
with the corrector being the 1-step Adams Moulton,
\begin{equation}w_{i+1}=w_{i}+\frac{h}{2}\big[ 0.2 w_{i+1}^p-0.01 (w^p_{i+1})^2 +\sin(2\pi t_{i+1}
                                + 0.2 w_i-0.01 w_i^2+\sin(2\pi t_{i}\big], \end{equation}    

                                






```python
def nonlin_oscfun(t,w):
    ftw=0.2*w-0.01*w*w+np.sin(2*np.math.pi*t)
    return ftw
```


```python
## INSERT METHOD HERE
w=np.zeros(N+1)
w[0]=6
w[1]=6.11
for n in range(1,N):
    w[n+1]=w[n]+h/2
```

## Results
The plot below shows the  numerical approximation, $w$ (circles) for the non-linear population equation:


```python
fig = plt.figure(figsize=(8,4))
plt.plot(t,w,'o:',color='purple',label='Adams-Moulton')
plt.title('Population Equation with seasonal oscilation')
plt.xlabel('time (yrs)')
plt.ylabel('Population in Billions')
plt.legend(loc='best')
plt.show()
```

## Table
The table below shows the time and the numerical approximation, $w$,  for the non-linear population equation:


```python
d = {'time t_i': t, 'Adams Approx w': w}
df = pd.DataFrame(data=d)
df

```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>time t_i</th>
      <th>Adams Approx w</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2000.0</td>
      <td>6.00</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2001.0</td>
      <td>6.11</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2002.0</td>
      <td>6.61</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2003.0</td>
      <td>7.11</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2004.0</td>
      <td>7.61</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2005.0</td>
      <td>8.11</td>
    </tr>
    <tr>
      <th>6</th>
      <td>2006.0</td>
      <td>8.61</td>
    </tr>
    <tr>
      <th>7</th>
      <td>2007.0</td>
      <td>9.11</td>
    </tr>
    <tr>
      <th>8</th>
      <td>2008.0</td>
      <td>9.61</td>
    </tr>
    <tr>
      <th>9</th>
      <td>2009.0</td>
      <td>10.11</td>
    </tr>
    <tr>
      <th>10</th>
      <td>2010.0</td>
      <td>10.61</td>
    </tr>
    <tr>
      <th>11</th>
      <td>2011.0</td>
      <td>11.11</td>
    </tr>
    <tr>
      <th>12</th>
      <td>2012.0</td>
      <td>11.61</td>
    </tr>
    <tr>
      <th>13</th>
      <td>2013.0</td>
      <td>12.11</td>
    </tr>
    <tr>
      <th>14</th>
      <td>2014.0</td>
      <td>12.61</td>
    </tr>
    <tr>
      <th>15</th>
      <td>2015.0</td>
      <td>13.11</td>
    </tr>
    <tr>
      <th>16</th>
      <td>2016.0</td>
      <td>13.61</td>
    </tr>
    <tr>
      <th>17</th>
      <td>2017.0</td>
      <td>14.11</td>
    </tr>
    <tr>
      <th>18</th>
      <td>2018.0</td>
      <td>14.61</td>
    </tr>
    <tr>
      <th>19</th>
      <td>2019.0</td>
      <td>15.11</td>
    </tr>
    <tr>
      <th>20</th>
      <td>2020.0</td>
      <td>15.61</td>
    </tr>
  </tbody>
</table>
</div>




```python

```


```python

```


```python

```

4444326a69388c49ca164cc19d7af89343d38de2
ipynb
Jupyter Notebook
Chapter 04 - Multistep Methods/404_Adams Moulton Population Equations.ipynb
jjcrofts77/Numerical-Analysis-Python
97e4b9274397f969810581ff95f4026f361a56a2
MIT
2019-09-05T21:39:12.000Z
2022-03-26T14:00:25.000Z
Chapter 04 - Multistep Methods/404_Adams Moulton Population Equations.ipynb
jjcrofts77/Numerical-Analysis-Python
97e4b9274397f969810581ff95f4026f361a56a2
MIT
Chapter 04 - Multistep Methods/404_Adams Moulton Population Equations.ipynb
jjcrofts77/Numerical-Analysis-Python
97e4b9274397f969810581ff95f4026f361a56a2
MIT
2021-06-17T15:34:04.000Z
2022-01-14T14:53:43.000Z
Qwen/Qwen-72B
1. YES
2. YES