\section{Up up and away! Adding More Layers to the Atmosphere}
Up until now we have neglected any vertical movement. This hampers the model, as the rising of warm air that then flows to the poles, cools down and flows back to the tropics is not possible
as the warm air cannot rise. So let us change that, let's add some vertical motion and some more layers to the atmosphere.

Remember \autoref{eq:atmos change}? We need this equation for every layer in the atmosphere. This also means that we have to adjust the main loop of the code, which is described  in 
\autoref{alg:temperature with density}. The $T_a$ needs to change, we need to either add a dimension (to indicate which layer of the atmosphere we are talking about) or we need to add different
matrices for each atmosphere layer. Let us define some useful variables in \autoref{alg:more layers}. We opt for adding a dimension as that costs less memory than defining new arrays 
\footnote{This has to do with pointers, creating a new object always costs a bit more space than adding a dimension as we need a pointer to the object and what type of object it is whereas with 
adding a dimension we do not need this additional information as it has already been defined}. So $T_a$, and all other matrices that have to do with the atmosphere (so not $T_p$ for instance) 
are no longer indexed by $lat, lon$ but are indexed by $lat, lon, layer$.

\begin{algorithm}
    $nlevels \leftarrow 4$ \;
    $heights \leftarrow \text{Array with } nlevels \text{ layers, each with a uniform thickness of } \frac{100 \cdot 10^3}{nlevels} m$ \;
    \caption{Definition of variables that are used throughout the code}
    \label{alg:more layers}
\end{algorithm}



As you can see, we have used $\delta z$ however, we have not defined it yet. Let us do that in \autoref{alg:gradient z}.

\begin{algorithm}[hbt]
    \For{$k \in [0, nlevels - 1]$}{
        $\delta z[k] \leftarrow heights[k + 1] - heights[k]$ \;
    }
    $\delta z[nlevels - 1] \leftarrow \delta z [nlevels - 2]$ \;
    \caption{Defining $\delta z$ for later use throughout the code}
    \label{alg:gradient z}
\end{algorithm}

Of course we also need to incorporate the new layers in the divergence operator (\autoref{alg:divergence}). The new changes can be found in \autoref{alg:divergence layer}. Here we use $w$, the 
vertical wind velocity. We define $w$ in the same way as $u$ and $v$, it is all zeroes (in the beginning) and has the same dimensions as $u$ and $v$.



With all those changes in the functions done, let us incorporate the changes into the model itself. We now need to account for the temperature change throughout the layers. Let us look at the 
atmospheric temperature equation again (\autoref{eq:atmos change}). We need to account for one more thing, the absorbtion of energy from another layer. The new equation is shown in 
\autoref{eq:atmos change layer}. Here $k$ is the layer of the atmosphere, $k = -1$ means that you use $T_p$ and $k = nlevels$ means that $T_{a_{nlevels}} = 0$ as that is space. Also, let us
rewrite the equation a bit such that the variables that are repeated are only written once and stuff that is divided out is removed, which is done in \autoref{eq:atmos change layer improved}.
Let us also clean up the equation for the change in the surface temperature (\autoref{eq:surface change}) in \autoref{eq:surface change improved}.

\begin{subequations}
    \begin{equation}
        \Delta T_{a_k} = \frac{\delta t (\sigma \epsilon_{k - 1}T_{a_{k - 1}}^4 + \sigma \epsilon_{k + 1}T_{a_{k + 1}}^4 - 2\epsilon_k\sigma T_{a_k}^4)}{C_a}
        \label{eq:atmos change layer}
    \end{equation}
    \begin{equation}
        \Delta T_{a_k} = \frac{\delta t \sigma (\epsilon_{k - 1}T_{a_{k - 1}}^4 + \epsilon_{k + 1}T_{a_{k + 1}}^4 - 2\epsilon_kT_{a_k}^4)}{C_a}
        \label{eq:atmos change layer improved}
    \end{equation}
    \begin{equation}
        \Delta T_p = \frac{\delta t (S + \sigma(4\epsilon_pT_a^4 - 4T_p^4))}{4C_p}
        \label{eq:surface change improved}
    \end{equation}
\end{subequations}

With the changes made to the equation, we need to make those changes in the code as well. We need to add the new dimension to all matrices except $T_p$ and $a$ as they are unaffected (with 
regards to the storage of the values) by the addition of multiple atmospheric layers. Every other matrix is affected. The new code can be found in \autoref{alg:temperature layer}.

\begin{algorithm}[hbt]
    \SetAlgoLined

    \While{\texttt{TRUE}}{
        \For{$lat \in [-nlat, nlat]$}{
            \For{$lon \in [0, nlot]$}{
                \For{$layer \in [0, nlevels]$}{
                    $T_p[lat, lon] \leftarrow T_p[lat, lon] + \frac{\delta t ((1 - a[lat, lon])S + \sigma(4\epsilon[0](T_a[lat, lon, 0])^4 - 4(T_p[lat, lon])^4))}
                    {4C_p[lat, lon]}$ \;
                    \uIf{$layer == 0$}{
                        $T_a[lat, lon, layer] \leftarrow T_a[lat, lon, layer] + \frac{\delta t \sigma((T_p[lat, lon])^4 - 2\epsilon[layer](T_a[lat, lon, layer])^4)}
                        {\rho[lat, lon, layer]C_a\delta z[layer]}$ \;
                    }\uElseIf{$layer == nlevels - 1$}{
                        $T_a[lat, lon, layer] \leftarrow T_a[lat, lon, layer] + \frac{\delta t \sigma(\epsilon[layer - 1](T_a[lat, lon, layer - 1])^4 - 2\epsilon[layer](T_a[lat, lon, layer])^4)}
                        {\rho[lat, lon, layer]C_a\delta z[layer]}$ \;
                    }\uElse{
                        $T_a[lat, lon, layer] \leftarrow T_a[lat, lon, layer] + \frac{\delta t \sigma(\epsilon[layer - 1](T_a[lat, lon, layer - 1])^4 + \epsilon[layer + 1]T_a[lat, lon, layer + 1] 
                        - 2\epsilon[layer](T_a[lat, lon, layer])^4)}{\rho[lat, lon, layer]C_a\delta z[layer]}$ \;
                    }
                    $t \leftarrow t + \delta t$ \;
                }
            }
        }
    }
    \caption{The main loop of the temperature calculations}
    \label{alg:temperature layer}
\end{algorithm}

We also need to initialise the $\epsilon$ value for each layer. We do that in \autoref{alg:epsilon}.

\begin{algorithm}
    $\epsilon[0] \leftarrow 0.75$ \;
    \For{$i \in [1, nlevels]$}{
        $\epsilon[i] \leftarrow 0.5\epsilon[i - 1]$
    }
    \caption{Intialisation of the insulation of each layer (also known as $\epsilon$)}
    \label{alg:epsilon}
\end{algorithm}

Now we need to add vertical winds, or in other words add the $w$ component of the velocity vectors. We do that by editing \autoref{alg:stream3}. We change it to \autoref{alg:velocity}. Here we 
use gravity ($g$) instead of the coriolis force ($f$) and calculate the change in pressure. Therefore we need to store a copy of the pressure before we do any calculations. This needs to be a
copy due to aliasing \footnote{Aliasing is assigning a different name to a variable, while it remains the same variable. Take for instance that we declare a variable $x$ and set it to be $4$. 
Then we say $y \leftarrow x$, which you might think is the same as saying they $y \leftarrow 4$ but behind the screen it is pointing to $x$. So if $x$ changes, then so does $y$.}

\begin{algorithm}
    $S_{xu} \leftarrow \texttt{gradient\_x}(u, lan, lon)$ \;
    $S_{yu} \leftarrow \texttt{gradient\_y}(u, lan, lon)$ \;
    $S_{xv} \leftarrow \texttt{gradient\_x}(v, lan, lon)$ \;
    $S_{yv} \leftarrow \texttt{gradient\_y}(v, lan, lon)$ \;
    $S_{px} \leftarrow \texttt{gradient\_x}(p, lan, lon)$ \;
    $S_{py} \leftarrow \texttt{gradient\_y}(p, lan, lon)$ \;
    \While{\texttt{TRUE}}{
        \For{$lat \in [1, nlat - 1]$}{
            \For{$lon \in [0, nlon]$}{
                \For{$layer \in [0, nlevels]$}{
                    $u[lan, lon, layer] \leftarrow u[lat, lon, layer] + \delta t \frac{-u[lat, lon, layer]S_{xu} - v[lat, lon, layer]S_{yu} + f[lat]v[lat, lon, layer] - S_{px}}{\rho}$ \;
                    $v[lan, lon, layer] \leftarrow v[lat, lon, layer] + \delta t \frac{-u[lat, lon, layer]S_{xv} - v[lat, lon, layer]S_{yv} - f[lat]u[lat, lon, layer] - S_{py}}{\rho}$ \;
                    $w[lan, lon, layer] \leftarrow w[lat, lon, layer] - \frac{p[lat, lon, layer] - p_o[lat, lon, layer]}{\delta t\rho[lat, lon, layer]g}$ \;
                }
            }
        }

        $p_o \leftarrow copy(p)$ \;
    }
    \caption{Calculating the flow of the atmosphere (wind)}
    \label{alg:velocity}
\end{algorithm}

Lastly, we need to add the correct indices to the advection algorithm \autoref{alg:advectionfix}. Let us add it, with \autoref{alg:advection layer} as a result. Here the ':' means all indices 
of the 3 dimensional matrix.

\begin{algorithm}
    $\alpha_a \leftarrow 2 \cdot 10^{-5}$ \;
    $\alpha_p \leftarrow 1.5 \cdot 10^{-6}$ \;
    $boundary \leftarrow 7$ \;
    \While{\texttt{TRUE}}{
        $T_{add} \leftarrow T_a + \delta t \alpha_a \nabla^2(T_a) + \nabla(T_a)$ \;
        $T_a \leftarrow T_a - 0.5T_{add}[boundary:-boundary, :, :] \text{ //Only subtract } T_{add} \text{ to } T_a \text{ for indices in the interval } [-nlat + boundary, nlat - boundary]$. \;
        $\rho[boundary: -boundary, :, :] \leftarrow \rho - 0.5(\delta t \nabla \rho) \text{ //Only change the density for indices in the interval } [-nlat + boundary, nlat - boundary]$ \;
        $T_p \leftarrow T_p + \delta t \alpha_p \nabla^2(T_p)$ \;
    }
    \caption{The main loop for calculating the effects of advection}
    \label{alg:advection layer}
\end{algorithm}