End interactive session 3A
| t | P | dPdt |
|---|---|---|
| 0 | 0.2 | 0.024 |
Differential equations and solving them numerically in R: Lotke-Volterra
This lesson is closely based on the article, Numerically solving differential equations with R.
We’ll just do this once to reinforce how numerical integration generally works for approximating a particular solution. Given the differential equation:
\[\frac{dP}{dt}=0.4P(0.5 - P)\]
and the initial condition \(P(0)=0.2\), approximate the solution \(P(t)\) at t = 1, 2.
Here we have the initial condition, \(P(0)=0.2\), which we can use to fill out our first row \(t\) and \(P\) in the table, below
Next, we can use those initial conditions to calculate the slope, \(\frac{dP}{dt}\), using our given differential equation: \(\frac{dP}{dt} = (0.4)(0.2)(0.5-0.2)\)
| t | P | dPdt |
|---|---|---|
| 0 | 0.2 | 0.024 |
Importantly, we assume that the slope is continuing at 0.024.
This means that the approximate value of \(P(1) = P(0) + (\frac{dP}{dt} * \Delta t)\), therefore, \(P(1) = 0.2 + (0.024 * 1) = 0.224\)
At that value of \(P\), the slope is approximated by \(\frac{dP}{dt}=(0.4)(0.224)(0.5 - 0.224) = 0.02473\).
So now, our table is expand to:
| t | P | dPdt |
|---|---|---|
| 0 | 0.200 | 0.02400 |
| 1 | 0.224 | 0.02473 |
Again, we assume that the slope is continuing at the rate determined for the previous time step, 0.02473
We can approximate the value of \(P(2) = P(1) + (\frac{dP}{dt} * \Delta t)\), therefore, \(P(2) = 0.224 + (0.02473*1) = 0.24873\)
At that value of \(P\), the slope is approaximated by \(\frac{dP}{dt}=(0.4)(0.24873)(0.5 - 0.24873)=0.024999\)
Our table is then updated to:
| t | P | dPdt |
|---|---|---|
| 0 | 0.20000 | 0.024000 |
| 1 | 0.22400 | 0.024730 |
| 2 | 0.24873 | 0.024999 |
And we could continue doing that for many incremental values of \(t\) to get an approximate solution for what the function \(P(t)\) looks like. But that would be very tedious. Up next - computer help!
There are many different approaches to numerical approximation of solutions for differential equations. This example is meant to give you an idea of how the iterative approximation works generally.
Now, let’s see how much more quickly we can do this with some computer power!
deSolve::ode() (a basic starter)eds212-day3a
Add either an R script or Quarto doc (your choice) to complete the following exercise in.
Let’s say we have a system modeled by:
\[\frac{dC}{dt}=\lambda C^2-3.1\delta\] and we don’t know how to solve this analytically. Let’s use the {deSolve} package in R to help us find a solution numerically, given an initial condition at \(C(0)=4.8\) and for parameter values \(\lambda = 0.4\) and \(\delta=0.06\).
Here’s what a numeric solution looks like with {deSolve}:
First, we’ll make a time sequence that we want to estimate numerical solutions over:
Then, we’ll store the parameter(s) and initial conditions:
Store the differential equation as a function:
# Prepare differential equation(s) as a function, which take three arguments aka inputs (a sequence of time steps, a vector of our initial conditions, and a vector of our parameter values) ----
df_equation_example <- function(time_seq, init_cond_example, parameter_example) {
# using our initial conditions and parameter values ....
with(as.list(c(init_cond_example, parameter_example)), {
# ... estimate the numerical solutions to this differential equation....
dCdt = lambda * C^2 - 3.1 * delta
# ...and return a list of approximated solutions calculated at each time step for all equations (here we only have 1 equation that we're solving for)
return(list(c(dCdt)))
})
}The structure of our function body looks a bit different than what we’ve practiced in other recent exercises. Let’s break down the body of our function a bit to better understand what’s happening:
c(init_cond_example, parameter_example) combines the initial conditions and parameter values into a single, named vector (both init_cond_example and parameter_example are named vectors)as.list(c(init_cond_example, parameter_example)) converts our named vector into a list, where each element can be accessed by name
delta variable in our list using the syntax, (as.list(c(init_cond_example, parameter_example)))$deltadelta by name when in vector format (e.g. c(init_cond_example, parameter_example)$delta)with(as.list(c(init_cond_example, parameter_example)), { ... }) evaluates the block of code (inside {}) in an environment where the names in our list (i.g. C, lambda, delta) are treated as variables and can be directly referenced by nameUse deSolve::ode() to approximate the solution numerically:
# Find the approximate solution using `deSolve::ode()` ----
approx_df_example <- ode(y = init_cond_example,
times = time_seq,
func = df_equation_example,
parms = parameter_example)
# Check the class ----
class(approx_df_example)[1] "deSolve" "matrix"
# We really want this to be a data frame for plotting (more to come in EDS 221) ----
approx_df_example <- data.frame(approx_df_example)
class(approx_df_example) # you might also consider looking at it using `View(approx_df_example)`[1] "data.frame"

Now let’s try it for something a bit more interesting!
In this session, you will use existing code in a public repo on GitHub that approximates the solution to the Lotka-Volterra equations.
You will make your own copy of the repo by forking it. By making a fork, you create a copy that you can work in separately.
The repo contains a single .qmd (lotka-volterra.qmd), with information and code to numerically approximate solutions to the Lotka-Volterra equations and make a graph.
Open the .qmd and render. We will talk through the code together. A couple of things to note:
.html doesn’t appear in the git pane. Why?Here, we’ll learn a few basic commands to talk with your computer through the command line to navigate around and do some git stuff outside of RStudio.
pwd to see where your Terminal currently sees the working directoryls to see the contents of the directorycd to change to a different downstream directory.. to go back upstreamlotka-volterra-example projectpwd to see your current working directory (it should be your project’s root directory!)git status to see the current git status.qmd in your project and savegit status to see any newly added or modified files (they’ll appear red)git add filename.qmd to stage it (git add . will stage everything)git status again to see all staged files (they should now appear green)git commit -m "a commit message" to commit to local repogit status again to check statusgit pull to pullgit push to push changesgit statusEnd interactive session 3A