Load required packages:
library(deSolve)
library(viridis)
## Loading required package: viridisLite
library(diagram)
## Loading required package: shape
The parameters used for each model with an explanation of their terms are:
# Parameters for all initial models:
r1 = 0.9 # Intrinsic growth rate of native sp
r2 = 1.5 # Intrinsic growth rate of invasive sp
K1 = 100 # Carrying capacity of native sp
K2 = 100 # Carrying capacity of invasive sp
alpha12 = 0.8 # Interaction coefficient -invasive sp on native sp - this is altered in Model 3
alpha21 = 0.1 # Interaction coefficient -native sp on invasive sp - this is altered in Model 3
T_opt1 = 11 # Optimal temperature of native sp
T_opt2 = 16 # Optimal temperature of invasive sp
sigma1 = 2.5 # Temperature sensitivity of native sp
sigma2 = 4.5 # Temperature sensitivity of invasive sp
temp_v = seq(10,26,1) # Temperature ranges
N0 <- c(10,1) # Initial population sizes (10 = native, 1 = invasive)
The interaction coefficient in visual form:
forces <- matrix(c(
0, alpha12,
alpha21, 0),
nrow = 2, byrow = TRUE)
colnames(forces) <- c("Native", "Invasive")
plotmat(forces, relsize = 0.83, cex.txt = 0.7, dtext = 0.5,, box.cex = 0.7)
Both models used in this report have a temperature dependant growth rate:
\[ \begin{align*} \text{growth rate_1} &= r_1 *\exp\left(-\frac{{(T - T_{\text{opt1}})^2}}{{2 \cdot \sigma_1^2}}\right) \\ \text{growth rate_2} &= r_2 *\exp\left(-\frac{{(T - T_{\text{opt2}})^2}}{{2 \cdot \sigma_2^2}}\right) \end{align*} \]This means that the growth rate decreases as the temperature deviates from the optimal temperature, with a bell-shaped curve centred at the optimal temperature for the species (as shown below)
# Bell curve of growth rate of Native & Invasive species vs temperature:
# Growth rate equations for both species:
growth_rate1 <- function(T1, r1, T_opt1, sigma1) {
r1 * exp(-((T1 - T_opt1)^2) / (2 * sigma1^2))
}
growth_rate2 <- function(T1, r2, T_opt2, sigma2) {
r2 * exp(-((T1 - T_opt2)^2) / (2 * sigma2^2))
}
# Temperature range
T1 <- seq(0, 40, by = 0.1) # Temperature range
# Calculate growth rates for both species
growth_rates_native <- growth_rate1(T1, r1, T_opt1, sigma1)
growth_rates_invasive <- growth_rate2(T1, r2, T_opt2, sigma2)
# Plot the growth rates of both species on the same graph
plot(T1, growth_rates_native,
type = "l",
col = "dodgerblue",
xlab = "Temperature (°C)",
ylab = "Growth Rate (per capita)",
ylim = c(0,1.7),
lwd = 2)
lines(T1, growth_rates_invasive, col = "orange", lwd = 2)
legend("topright", legend = c("Native", "Invasive"),
col = c("dodgerblue", "orange"),
lty = 1,
lwd = 2)
As shown above, the invasive species has a higher growth rate and is able to still grow at a larger range than the native species. This can be then be implemented into each model.
The basis for this model was the Verhulst (1838) model for continuous density dependence:
\[ \begin{align*} \\\frac{{dN}}{{dt}}\ = N r \left(1-\frac{{N}}{{K}}\right) \end{align*} \]
with \(r\) substituted for the temperature dependant growth rate formula for each species which is defined in the previous section.
# Model 1
# Define the model
independent.model <- function(times, N0, parameters, T) {
N1 <- N0[1]
N2 <- N0 [2]
with(as.list(parameters), {
# Temperature dependant growth rate
growth_rate1 <- r1 * exp(-((T - T_opt1)^2) / (2 * sigma1^2))
growth_rate2 <- r2 * exp(-((T - T_opt2)^2) / (2 * sigma2^2))
# density dependant single species growth
dn1 <- N1 * growth_rate1 * (1 - (N1 / K1 ))
dn2 <- N2 * growth_rate2 * (1 - (N2 / K2 ))
return(list(c(dn1, dn2)))
})
}
# Assign parameters:
parameters <- list(r1, r2,
K1, K2,
T_opt1, T_opt2,
sigma1, sigma2,
alpha12, alpha21)
# Length of simulation
t.values <- seq(0,100, length.out = 501)
# Create empty lists to store results for both species
species1_results <- list()
species2_results <- list()
# Solve the differential equations for each temperature and store the results
for (temp in temp_v) {
independent.model.out <- ode(N0,
t.values,
independent.model,
parms = parameters,
T = temp)
species1_results[[paste("Temp =", temp, "°C")]] <- independent.model.out[, 2]
species2_results[[paste("Temp =", temp, "°C")]] <- independent.model.out[, 3]
}
# Investigate time series
# Plot results for species 1 (native)
par(mfrow=c(1, 1)) # Arrange plots 1x1
matplot(t.values,
sapply(species1_results, function(x) x), # Extract species 1 abundance from the list
type = "l",
lty = 1,
lwd = 2,
ylab = "Abundance (N)",
xlab = "Time (t)",
cex.main = 0.9,
ylim = c(0, 110),
xlim = c(0, 110),
col = viridis(length(temp_v), option = "H"),
main = "Native")
legend("topright",
legend = paste(temp_v, "°C"),
lty = 1,
lwd = 2,
col = viridis(length(temp_v), option = "H"),
cex = 0.6,
title = "Temp")
# Plot results for species 2 (invasive)
matplot(t.values,
sapply(species2_results, function(x) x), # Extract species 2 abundance from the list
type = "l",
lty = 1,
lwd = 2,
ylab = "Abundance (N)",
xlab = "Time (t)",
cex.main = 0.9,
ylim = c(0, 110),
xlim = c(0, 110),
col = viridis(length(temp_v), option = "H"),
main = "Invasive")
legend("topright",
legend = paste(temp_v, "°C"),
lty = 1,
lwd = 2,
col = viridis(length(temp_v), option = "H"),
cex = 0.6,
title = "Temp")
Investigate changes in growth rate over time with temperature
par(mfrow=c(1,1))
# For Native Species
# Plot results for species 1 (native)
plot(NULL,
xlim = c(0, 105),
ylim = c(-2, 8),
main = "Native: Growth Rate change over time",
xlab = "Time (t)",
ylab = "Growth Rate (N(t+1)- N(t)")
# Plot results for species 1 (native) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
independent.model.out <- ode(N0,
t.values,
independent.model,
parms = parameters,
T = temp_v[i])
# Calculate growth rate for species 1 (native)
growth_rateN <- diff(independent.model.out[, 2])
# Add lines for species 1 (native)
lines(t.values[-1], growth_rateN,
col = viridis(length(temp_v), option = "H")[i],
lwd = 2,
lty = 1)
}
legend("topright", legend = paste(temp_v, "°C"),
col = viridis(length(temp_v), option = "H"),
lwd = 2,
title = "Temperature",
cex = 0.6)
### Invasive Species
# Plot results for species 2 (invasive)
plot(NULL,
xlim = c(0, 105),
ylim = c(-2, 8),
main = "Invasive: Growth Rate change over time",
xlab = "Time (t)",
ylab = "Growth Rate (N(t+1)- N(t)")
# Plot results for species 2 (invasive) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
independent.model.out <- ode(N0,
t.values,
independent.model,
parms = parameters,
T = temp_v[i])
# Calculate growth rate for species 2 (invasive)
growth_rateI <- diff(independent.model.out[, 3])
# Add lines for species 2 (invasive)
lines(t.values[-1], growth_rateI,
col = viridis(length(temp_v), option = "H")[i],
lwd = 2,
lty = 1)
}
legend("topright", legend = paste(temp_v, "°C"),
col = viridis(length(temp_v), option = "H"),
lwd = 2,
title = "Temperature",
cex = 0.6)
For native species:
# Create empty lists to store population growth functions and per-capita growth rates
f_N <- list()
pgrN <- list()
# Loop over temperature values
for (temp in temp_v) {
# Create population growth function for the current temperature
N1 <- seq(0, 1.5 * K1, length.out = 101)
growth_rate <- r1 * exp(-((temp - T_opt1)^2) / (2 * sigma1^2))
f_N[[temp]] <- exp(growth_rate * (1 - N1 / K1))
# Calculate per-capita growth rates
pgrN[[temp]] <- log(f_N[[temp]])
}
# Plot the results
par(mfrow = c(1, 1))
plot(NULL, xlim = c(0, 1.5 * K1), ylim = c(0, 1.5 * K1),
xlab = "Population size, N[t]",
ylab = "Population growth function, N[t+1] = N[t] f(N[t])",
main = "Population Growth Function Native")
# Add lines for each temperature
for (i in 1:length(temp_v)) {
lines(N1, N1 * f_N[[temp_v[i]]], col = viridis(length(temp_v), option = "H")[i])
}
legend("topright",
legend = paste(temp_v, "°C"),
lty = 1,
lwd = 2,
col = viridis(length(temp_v), option = "H"),
cex = 0.6,
title = "Temp °C")
grid()
# Plot per-capita growth rates for each temperature
plot(NULL, xlim = c(0, 1.5 * K1), ylim = c(-2, 2),
xlab = "Population size, N[t]",
ylab = "Per-capita growth rate",
main = "Per-capita Growth Rate Native")
for (i in 1:length(temp_v)) {
lines(N1, pgrN[[temp_v[i]]], col = viridis(length(temp_v), option = "H")[i])
}
legend("topright",
legend = paste(temp_v, "°C"),
lty = 1,
lwd = 2,
col = viridis(length(temp_v), option = "H"),
cex = 0.6,
title = "Temp °C")
grid()
For invasive species:
# Create empty lists to store population growth functions and per-capita growth rates
f_I <- list()
pgrI <- list()
# Loop over temperature values
for (temp in temp_v) {
# Create population growth function for the current temperature
N2 <- seq(0, 1.5 * K2, length.out = 101)
growth_rate2 <- r2 * exp(-((temp - T_opt2)^2) / (2 * sigma2^2))
f_I[[temp]] <- exp(growth_rate2 * (1 - N2 / K2))
# Calculate per-capita growth rates
pgrI[[temp]] <- log(f_I[[temp]])
}
# Plot the results
library(viridis)
par(mfrow = c(1, 1))
plot(NULL, xlim = c(0, 1.5 * K2), ylim = c(0, 1.5 * K2),
xlab = "Population size, N[t]",
ylab = "Population growth function, N[t+1] = N[t] f(N[t])",
main = "Population Growth Function Invasive")
# Add lines for each temperature
for (i in 1:length(temp_v)) {
lines(N2, N2 * f_I[[temp_v[i]]], col = viridis(length(temp_v), option = "H")[i])
}
legend("topright",
legend = paste(temp_v, "°C"),
lty = 1,
lwd = 2,
col = viridis(length(temp_v), option = "H"),
cex = 0.6,
title = "Temp °C")
grid()
# Plot per-capita growth rates for each temperature
plot(NULL, xlim = c(0, 1.5 * K2), ylim = c(-2, 2),
xlab = "Population size, N[t]",
ylab = "Per-capita growth rate",
main = "Per-capita Growth Rate Invasive")
for (i in 1:length(temp_v)) {
lines(N2, pgrI[[temp_v[i]]], col = viridis(length(temp_v), option = "H")[i])
}
legend("topright",
legend = paste(temp_v, "°C"),
lty = 1,
lwd = 2,
col = viridis(length(temp_v), option = "H"),
cex = 0.6,
title = "Temp °C")
grid()
To determine the effect of competition on the populations of both species at different temperatures, Lotka Voltera inter-specific competition was uesed as the basis: \[ \begin{align*} \frac{dN_1}{dt} &= r_1 N_1 \left( \frac{K_1 - N_1 - \alpha_{12} N_2}{K_1} \right) \\ \frac{dN_2}{dt} &= r_2 N_2 \left( \frac{K_2- N_2 - \alpha_{21} N_1}{K_2} \right) \\ \end{align*} \]
with the additional growth dependent term used in the previous model:\[ \begin{align*} \text{growth rate_1} &= r_1 \cdot \exp\left(-\frac{{(T - T_{\text{opt1}})^2}}{{2 \cdot \sigma_1^2}}\right) \\ \text{growth rate_2} &= r_2 \cdot \exp\left(-\frac{{(T - T_{\text{opt2}})^2}}{{2 \cdot \sigma_2^2}}\right) \end{align*} \]
To determine the outcome of the competition: results show an equilibrium between the two species.
par(mfrow=c(1,1))
# Create an empty plot
plot(0, type = "n",
xlim = c(0, 1000),
ylim = c(0, 130),
xlab = "Native Abundance",
ylab = "Invasive Abundance")
# Determine intercept point
N_isocline <- K1/alpha12 # intercept of native population on the y axis
I_isocline <- K2/alpha21 # intercept of the invasive species on the x axis
# Add lines representing the nullcine
lines(c(0, K1), c(N_isocline, 0), lwd= 2,
col = "dodgerblue") # Line for species 1
lines(c(I_isocline, 0), c(0, K2), lwd = 2,
col = "orange") # Line for species 2
# Add legend
legend("topright",
legend = c("Native","Invasive "),
lty = 1,
lwd = 2,
col = c("dodgerblue", "orange"))
# Plot arrows showing direction
arrows(x0 = 90, y0 = 70, x1 = 40, y1 = 90, length = 0.1) # Bottom right arrow
arrows(x0 = -15, y0 = 115, x1 = 8, y1 = 105, length = 0.1) # Top left arrow
arrows(x0 = -10, y0 = 85, x1 = 10, y1 = 94, length = 0.1) # Bottom left arrow
arrows(x0 = 70, y0 = 110, x1 = 40, y1 = 100, length = 0.1) # Top right arrow
# Key features of each nullcline:
text(x= 85, y = 0, "K1", cex = 0.5, col = "gray29")
text(x= -5, y = 96, "K2", cex = 0.5, col = "grey29")
text(x = 1000, y = 20, expression(frac(K2, alpha_21)), cex = 0.4, col = "grey29")
text(x = 50, y = 123, expression(frac(K1, alpha_12)), cex = 0.4, col = "grey29")
# Equilibrium point
points(21, 98, pch = 21, col = "black", cex = 1.2)
# Define model
competitive.lotka.volterra <- function(times, N0, parameters, T) {
N1 <- N0[1]
N2 <- N0[2]
with(as.list(parameters), {
# Temperature dependant growth rate (same as previous section)
growth_rate1 <- r1 * exp(-((T - T_opt1)^2) / (2 * sigma1^2))
growth_rate2 <- r2 * exp(-((T - T_opt2)^2) / (2 * sigma2^2))
# Lotka-Voltera inter-specific competition equation
dN1.dt <- growth_rate1 * N1 *((K1-N1-(alpha12*N2))/K1)
dN2.dt <- growth_rate2 * N2 *((K2-N2-(alpha21*N1))/K2)
return(list(c(dN1.dt, dN2.dt)))
})
}
Confirm the initial conditions and parameters, including initial populations (10 for native species as they are already there and 1 for the invasive as they are ‘newer’), and the time vector.
# Set initial conditions and parameters
N0 <- c(10, 1) # Initial population for each species
parameters <- list(r1, r2,
K1, K2,
T_opt1, T_opt2,
sigma1, sigma2,
alpha12, alpha21)
# Time vector
t.values <- seq(0,100, length.out = 501)
Then solve the differential equations for each temperature and plot them. First we plot with one temperature per graph to understand the relationship between the two species.
# Plot results for each temperature
par(mfrow=c(2, 2)) # Arrange plots in a 2x2 grid
for (temp in temp_v) {
# Solve the differential equations for each temperature
lotka.volterra.out <- ode(N0,
t.values,
competitive.lotka.volterra,
parms = parameters,
T = temp)
# Plot results
matplot(t.values, lotka.volterra.out[, c(2, 3)],
type = "l",
lty = 1,
lwd = 2,
ylab = "Abundance (N)",
xlab = "Time (t)",
cex.main = 0.9,
ylim = c(0,150),
col = c("dodgerblue", "orange"))
legend("topright",
c("Native", "Invasive"),
lty = 1,
lwd = 2,
col = c("dodgerblue", "orange"),
cex = 0.9,
title = paste("Temp:", as.character(temp), "°C"))
}
Then plot one graph for each species (with all temperatures on each one).
Abundance vs Time graphs:
par(mfrow = c(1, 1)) # Arrange graphs 1 x 1
# Plot results for species 1 (native)
plot(NULL, xlim = c(0, 105),
ylim = c(-10, 110),
xlab = "Time (t)",
ylab = "Abundance (N)",
main = "Native")
# Plot results for species 1 (native) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
lotka.volterra.out <- ode(N0,
t.values,
competitive.lotka.volterra,
parms = parameters,
T = temp_v[i])
# Add lines for species 1 (native)
lines(t.values, lotka.volterra.out[, 2],
col = viridis(length(temp_v), option = "H")[i],
lwd = 2,
lty = 1,
type = "l")
}
# Add legend for species 1 (native)
legend("topright", legend = temp_v,
col = viridis(length(temp_v), option = "H"),
lwd = 2,
title = "Temp °C",
cex = 0.6)
# Species 2 (invasive)
# Plot results for species 2 (invasive)
plot(NULL, xlim = c(0, 105),
ylim = c(0, 110),
xlab = "Time (t)",
ylab = "Abundance (N)",
main = "Invasive")
# Plot results for species 2 (invasive) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
lotka.volterra.out <- ode(N0,
t.values,
competitive.lotka.volterra,
parms = parameters,
T = temp_v[i])
# Add lines for species 2 (invasive)
lines(t.values, lotka.volterra.out[, 3],
col = viridis(length(temp_v), option = "H")[i],
lwd = 2,
lty = 1,
type = "l")
}
# Add legend for species 2 (invasive)
legend("topright", legend = temp_v,
col = viridis(length(temp_v), option = "H"),
lwd = 2,
title = "Temp °C",
cex = 0.6)
Plotting growth rate change over time:
par(mfrow=c(1,1))
# For Native Species
# Plot results for species 1 (native)
plot(NULL,
xlim = c(0, 105),
ylim = c(-2, 8),
main = "Native: Growth Rate change over time",
xlab = "Time (t)",
ylab = "Growth Rate (N(t+1)- N(t)")
# Plot results for species 1 (native) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
lotka.volterra.out <- ode(N0,
t.values,
competitive.lotka.volterra,
parms = parameters,
T = temp_v[i])
# Calculate growth rate for species 1 (native)
growth_rate <- diff(lotka.volterra.out[, 2])
# Add lines for species 1 (native)
lines(t.values[-1], growth_rate,
col = viridis(length(temp_v), option = "H")[i],
lwd = 2,
lty = 1)
}
legend("topright", legend = temp_v,
col = viridis(length(temp_v), option = "H"),
lwd = 2,
title = "Temp °C",
cex = 0.6)
### Invasive Species
# Plot results for species 2 (invasive)
plot(NULL,
xlim = c(0, 105),
ylim = c(-2, 8),
main = "Invasive: Growth Rate change over time",
xlab = "Time (t)",
ylab = "Growth Rate (N(t+1)- N(t)")
# Plot results for species 2 (invasive) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
lotka.volterra.out <- ode(N0,
t.values,
competitive.lotka.volterra,
parms = parameters,
T = temp_v[i])
# Calculate growth rate for species 2 (invasive)
growth_rate <- diff(lotka.volterra.out[, 3])
# Add lines for species 2 (invasive)
lines(t.values[-1], growth_rate,
col = viridis(length(temp_v), option = "H")[i],
lwd = 2,
lty = 1)
}
legend("topright", legend = temp_v,
col = viridis(length(temp_v), option = "H"),
lwd = 2,
title = "Temp °C",
cex = 0.6)
First, cycle through model 2 with interaction coefficients and plot to determine extinction:
Then determine the alpha12 and alpha21 values where both species are extinct at different temperatures and look closer at them.
# Vary alpha12 and alpha21 sequence to work out when there is extinction for either species.
# Starting with:
alpha12a = seq (0.5, 2, 0.5)
alpha21a = seq (0.1, 2, 0.5)
par(mfrow=c(1,3))
# Define model
competitive.lotka.volterraC <- function(times, N0, parameters, T) {
N1 <- N0[1]
N2 <- N0[2]
with(as.list(parameters), {
# Temperature dependant growth rate (same as previous section)
growth_rate1 <- r1 * exp(-((T - T_opt1)^2) / (2 * sigma1^2))
growth_rate2 <- r2 * exp(-((T - T_opt2)^2) / (2 * sigma2^2))
# Lotka-Voltera inter-specific competition equation
dN1.dtC <- growth_rate1 * N1 *((K1-N1-(alpha12a*N2))/K1) # amended interaction coefficient
dN2.dtC <- growth_rate2 * N2 *((K2-N2-(alpha21a*N1))/K2) # amended interaction coefficient
return(list(c(dN1.dtC, dN2.dtC)))
})
}
###For native species 1:
# Loop through alpha12 and alpha21 combinations
for (a12 in alpha12a) {
for (a21 in alpha21a) {
# Set parameters for this combination
parameters <- list(r1, r2,
K1, K2,
T_opt1, T_opt2,
sigma1, sigma2,
alpha12a = a12, # new coefficients
alpha21a = a21) # new coefficients
# Plot results for species 1 (native)
plot(NULL, xlim = c(0, 105),
ylim = c(-10, 100),
xlab = "Time (t)",
ylab = "Abundance (N)",
main = paste("N a12=", a12, "a21=",a21))
# Plot results for species 1 (native) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
lotka.volterra.outC <- ode(N0,
t.values,
competitive.lotka.volterraC,
parms = parameters,
T = temp_v[i])
# Add lines for species 1 (native)
lines(t.values, lotka.volterra.outC[, 2],
col = viridis(length(temp_v), option = "H")[i],
lwd = 1,
lty = 1,
type = "l")
}
}
}
### Invasive species 2
# Loop through alpha12 and alpha21 combinations
for (a12 in alpha12a) {
for (a21 in alpha21a) {
# Set parameters for this combination
parameters <- list(r1, r2,
K1, K2,
T_opt1, T_opt2,
sigma1, sigma2,
alpha12a = a12, # new coefficients
alpha21a = a21) # new coefficients
# Plot results for species 2 (invasive)
plot(NULL, xlim = c(0, 120),
ylim = c(-10, 100),
xlab = "Time (t)",
ylab = "Abundance (N)",
main = paste("I a12=", a12, "a21=",a21))
# Plot results for species 2 (invasive) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
lotka.volterra.outC <- ode(N0,
t.values,
competitive.lotka.volterraC,
parms = parameters,
T = temp_v[i])
# Add lines for species 2 (invasive)
lines(t.values, lotka.volterra.outC[, 3],
col = viridis(length(temp_v), option = "H")[i],
lwd = 1,
lty = 1,
type = "l")
}
legend("topright", legend = temp_v,
col = viridis(length(temp_v), option = "H"),
lwd = 2,
title = "Temp °C",
cex = 0.6)
}
}
extinction is recorded for species one (NATIVE) with the following interaction coefficients:
a12 = 1 a21 = 0.1 # all
a12 = 1 a21 = 0.6 # all
a12 = 1.5 a21 = 0.1 # all
a12 = 1.5 a21 = 0.6 # all
a12 = 1.5 a21 = 1.1 # not lowest 3 temps
a12 = 1.5 a21 = 1.6 # not lowest 5 temps
a12 = 2 a21 = 0.1 # all
a12 = 2 a21 = 0.6 # all
a12 = 2 a21 = 1.1 # not lowest 2 temps
a12 = 2 a21 = 1.6 # not lowest 5 temps
Extinction in species 2 (INVASIVE)
a12 = 0.5 a21 = 1.1 # only 7 lowest temps
a12 = 0.5 a21 = 1.6 # only lowest 6 temps
a12 = 1 a21 = 1.1 # only lowest 6 temps
a12 = 1 a21 = 1.6 # only lowest 5 temps
a12 = 1.5 a21 = 1.1 # only lowest 3 temps
a12 = 1.5 a21 = 1.6 # only lowest 4 temps
a12 = 2 a21 = 1.1 # only lowest 2 temps
a12 = 2 a21 = 1.6 # only lowest 4 temps
# Look at interesting dynamics where both are extinct at different temperatures (remove # from one variation at a time to produce graphs)
# Variation 1. a12 = 1.5, a21 = 1.1
#alpha12a = 1.5
#alpha21a = 1.1
# Variation 2. a12 = 1.5, a21 = 1.6
# alpha12a = 1.5
# alpha21a = 1.6
# Variation 3. a12 = 2, a21 = 1.1 - utilised in report
alpha12a= 2
alpha21a= 1.1
# Variation 4 a12 = 2, a21 = 1.6
# alpha12a = 2
# alpha21a = 1.6
par(mfrow= c(1,2))
# Define model
competitive.lotka.volterraC <- function(times, N0, parameters, T) {
N1 <- N0[1]
N2 <- N0[2]
with(as.list(parameters), {
# Temperature dependant growth rate (same as previous section)
growth_rate1 <- r1 * exp(-((T - T_opt1)^2) / (2 * sigma1^2))
growth_rate2 <- r2 * exp(-((T - T_opt2)^2) / (2 * sigma2^2))
# Lotka-Voltera inter-specific competition equation
dN1.dtC <- growth_rate1 * N1 *((K1-N1-(alpha12a*N2))/K1) # amended interaction coefficient
dN2.dtC <- growth_rate2 * N2 *((K2-N2-(alpha21a*N1))/K2) # amended interaction coefficient
return(list(c(dN1.dtC, dN2.dtC)))
})
}
###For native species 1:
# Loop through alpha12 and alpha21 combinations
for (a12 in alpha12a) {
for (a21 in alpha21a) {
# Set parameters for this combination
parameters <- list(r1, r2,
K1, K2,
T_opt1, T_opt2,
sigma1, sigma2,
alpha12a = a12, # new coefficients
alpha21a = a21) # new coefficients
# Plot results for species 1 (native)
plot(NULL, xlim = c(0, 105),
ylim = c(-10, 100),
xlab = "Time (t)",
ylab = "Abundance (N)",
main = paste("N a12=", a12, "a21=",a21))
# Plot results for species 1 (native) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
lotka.volterra.outC <- ode(N0,
t.values,
competitive.lotka.volterraC,
parms = parameters,
T = temp_v[i])
# Add lines for species 1 (native)
lines(t.values, lotka.volterra.outC[, 2],
col = viridis(length(temp_v), option = "H")[i],
lwd = 1,
lty = 1,
type = "l")
}
}
}
### Invasive species 2
# Loop through alpha12 and alpha21 combinations
for (a12 in alpha12a) {
for (a21 in alpha21a) {
# Set parameters for this combination
parameters <- list(r1, r2,
K1, K2,
T_opt1, T_opt2,
sigma1, sigma2,
alpha12a = a12, # new coefficients
alpha21a = a21) # new coefficients
# Plot results for species 2 (invasive)
plot(NULL, xlim = c(0, 120),
ylim = c(-10, 100),
xlab = "Time (t)",
ylab = "Abundance (N)",
main = paste("I a12=", a12, "a21=",a21))
# Plot results for species 2 (invasive) for each temperature
for (i in 1:length(temp_v)) {
# Solve the differential equations for each temperature
lotka.volterra.outC <- ode(N0,
t.values,
competitive.lotka.volterraC,
parms = parameters,
T = temp_v[i])
# Add lines for species 2 (invasive)
lines(t.values, lotka.volterra.outC[, 3],
col = viridis(length(temp_v), option = "H")[i],
lwd = 1,
lty = 1,
type = "l")
}
legend("topright", legend = temp_v,
col = viridis(length(temp_v), option = "H"),
lwd = 2,
title = "Temp °C",
cex = 0.6)
}
}
Phase plane graph for different competition coefficients:
alpha12a = 2
alpha21a = 1.1
Results in an unstable equilibrium.
par(mfrow=c(1,1))
alpha12a = 2
alpha21a = 1.1
# Create an empty plot
plot(0, type = "n",
xlim = c(0, 110),
ylim = c(0, 125),
xlab = "Native Abundance",
ylab = "Invasive Abundance")
N_isocline <- K1/alpha12a
I_isocline <- K2/alpha21a
# Add lines representing the nullcine
lines(c(0, K1), c(N_isocline, 0), lwd= 2,
col = "dodgerblue") # Line for species 1
lines(c(I_isocline, 0), c(0, K2), lwd = 2,
col = "orange") # Line for species 2
# Add legend
legend("topright",
legend = c("Native","Invasive "),
lty = 1,
lwd = 2,
col = c("dodgerblue", "orange"))
# Plot arrows showing direction
arrows(x0 = 90, y0 = 3, x1 = 98, y1 = -3, length = 0.1) # Bottom right arrow
arrows(x0 = 75, y0 = 15, x1 = 65, y1 = 23, length = 0.1) # Top left arrow
arrows(x0 = 70, y0 = -4, x1 = 82, y1 = 6, length = 0.1) # Bottom left arrow
arrows(x0 = 90, y0 = 40, x1 = 87, y1 = 20, length = 0.1) # Top right arrow
# Key features of each nullcline:
text(x= 105, y = 0, "K1", cex = 0.5, col = "gray29")
text(x= 0, y = 105, "K2", cex = 0.5, col = "grey29")
text(x = 0, y = 60, expression(frac(K1, alpha_12a)), cex = 0.4, col = "grey29")
# Equilibrium point
points(84, 8, pch = 21, col = "black", cex = 1.2)