/
reproduction.R
214 lines (207 loc) · 9.07 KB
/
reproduction.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#' Get density-independent rate of reproduction needed to project standard
#' mizer model
#'
#' Calculates the density-independent rate of total egg production
#' \eqn{R_{di}}{R_di} (units 1/year) before density dependence, by species.
#' You would not usually call this
#' function directly but instead use [getRDI()], which then calls this
#' function unless an alternative function has been registered, see below.
#'
#' This rate is obtained by taking the per capita rate \eqn{E_r(w)\psi(w)} at
#' which energy is invested in reproduction, as calculated by [getERepro()],
#' multiplying it by the number of individuals\eqn{N(w)} and integrating over
#' all sizes \eqn{w} and then multiplying by the reproductive efficiency
#' \eqn{\epsilon} and dividing by the egg size `w_min`, and by a factor of two
#' to account for the two sexes:
#' \deqn{R_{di} = \frac{\epsilon}{2 w_{min}} \int N(w) E_r(w) \psi(w) \, dw}{R_di = (\epsilon/(2 w_min)) \int N(w) E_r(w) \psi(w) dw}
#'
#' Used by [getRDD()] to calculate the actual, density dependent rate.
#' See [setReproduction()] for more details.
#'
#'
#' @section Your own reproduction function:
#' By default [getRDI()] calls [mizerRDI()]. However you can
#' replace this with your own alternative reproduction function. If
#' your function is called `"myRDI"` then you register it in a MizerParams
#' object `params` with
#' ```
#' params <- setRateFunction(params, "RDI", "myRDI")
#' ```
#' Your function will then be called instead of [mizerRDI()], with the
#' same arguments. For an example of an alternative reproduction function
#' see `constantEggRDI()`.
#'
#' @inheritParams mizerRates
#' @param e_repro An array (species x size) with the energy available for
#' reproduction as calculated by [getERepro()].
#' @param e_growth An array (species x size) with the energy available for
#' growth as calculated by [getEGrowth()]. Unused.
#' @param mort An array (species x size) with the mortality rate as calculated
#' by [getMort()]. Unused.
#'
#' @return A numeric vector with the rate of egg production for each species.
#' @export
#' @family mizer rate functions
mizerRDI <- function(params, n, n_pp, n_other, t,
e_growth, mort, e_repro, ...) {
# Calculate total energy from per capita energy
e_repro_pop <- drop((e_repro * n) %*% params@dw)
# Assume sex_ratio = 0.5
rdi <- 0.5 * (e_repro_pop * params@species_params$erepro) /
params@w[params@w_min_idx]
return(rdi)
}
#' Choose egg production to keep egg density constant
#'
#' `r lifecycle::badge("experimental")`
#' The new egg production is set to compensate for the loss of individuals from
#' the smallest size class through growth and mortality. The result should not
#' be modified by density dependence, so this should be used together with
#' the `noRDD()` function, see example.
#'
#' @param params A MizerParams object
#' @param n A matrix of species abundances (species x size).
#' @param e_growth A two dimensional array (species x size) holding the energy
#' available for growth as calculated by [mizerEGrowth()].
#' @param mort A two dimensional array (species x size) holding the mortality
#' rate as calculated by [mizerMort()].
#' @param ... Unused
#' @return Vector with the value for each species
#' @export
#' @family functions calculating density-dependent reproduction rate
#' @examples
#' \donttest{
#' # choose an example params object
#' params <- NS_params
#' # We set the reproduction rate functions
#' params <- setRateFunction(params, "RDI", "constantEggRDI")
#' params <- setRateFunction(params, "RDD", "noRDD")
#' # Now the egg density should stay fixed no matter how we fish
#' sim <- project(params, effort = 10, progress_bar = FALSE)
#' # To check that indeed the egg densities have not changed, we first construct
#' # the indices for addressing the egg densities
#' no_sp <- nrow(params@@species_params)
#' idx <- (params@w_min_idx - 1) * no_sp + (1:no_sp)
#' # Now we can check equality between egg densities at the start and the end
#' all.equal(finalN(sim)[idx], initialN(params)[idx])
#' }
constantEggRDI <- function(params, n, e_growth, mort, ...) {
no_sp <- nrow(params@species_params) # number of species
# Hacky shortcut to access the correct element of a 2D array
# using 1D notation
idx <- (params@w_min_idx - 1) * no_sp + (1:no_sp)
rdi <- n[idx] * (e_growth[idx] + mort[idx] * params@dw[params@w_min_idx])
rdi
}
#' Beverton Holt function to calculate density-dependent reproduction rate
#'
#' Takes the density-independent rates \eqn{R_{di}}{R_di} of egg production (as
#' calculated by [getRDI()]) and returns
#' reduced, density-dependent reproduction rates \eqn{R_{dd}}{R_dd} given as
#' \deqn{R_{dd} = R_{di}
#' \frac{R_{max}}{R_{di} + R_{max}}}{R_dd = R_di R_max/(R_di + R_max)} where
#' \eqn{R_{max}}{R_max} are the maximum possible reproduction rates that must be
#' specified in a column in the species parameter dataframe.
#' (All quantities in the above equation are species-specific but we dropped
#' the species index for simplicity.)
#'
#' This is only one example of a density-dependence. You can write your own
#' function based on this example, returning different density-dependent
#' reproduction rates. Three other examples provided are [RickerRDD()],
#' [SheperdRDD()], [noRDD()] and [constantRDD()]. For more explanation see
#' [setReproduction()].
#'
#' @param rdi Vector of density-independent reproduction rates
#' \eqn{R_{di}}{R_di} for all species.
#' @param species_params A species parameter dataframe. Must contain a column
#' `R_max` holding the maximum reproduction rate \eqn{R_{max}}{R_max} for each
#' species.
#' @param ... Unused
#'
#' @return Vector of density-dependent reproduction rates.
#' @export
#' @family functions calculating density-dependent reproduction rate
BevertonHoltRDD <- function(rdi, species_params, ...) {
if (!("R_max" %in% names(species_params))) {
stop("The R_max column is missing in species_params.")
}
return(rdi / (1 + rdi / species_params$R_max))
}
#' Ricker function to calculate density-dependent reproduction rate
#'
#' `r lifecycle::badge("experimental")`
#' Takes the density-independent rates \eqn{R_{di}}{R_di} of egg production and
#' returns reduced, density-dependent rates \eqn{R_{dd}}{R_dd} given as
#' \deqn{R_{dd} = R_{di} \exp(- b R_{di})}{R_dd = R_di exp(- b R_di)}
#'
#' @param rdi Vector of density-independent reproduction rates
#' \eqn{R_{di}}{R_di} for all species.
#' @param species_params A species parameter dataframe. Must contain a column
#' `ricker_b` holding the coefficient b.
#' @param ... Unused
#'
#' @return Vector of density-dependent reproduction rates.
#' @export
#' @family functions calculating density-dependent reproduction rate
RickerRDD <- function(rdi, species_params, ...) {
if (!("ricker_b" %in% names(species_params))) {
stop("The ricker_b column is missing in species_params")
}
return(rdi * exp(-species_params$ricker_b * rdi))
}
#' Sheperd function to calculate density-dependent reproduction rate
#'
#' `r lifecycle::badge("experimental")`
#' Takes the density-independent rates \eqn{R_{di}}{R_di} of egg production and returns
#' reduced, density-dependent rates \eqn{R_{dd}}{R_dd} given as
#' \deqn{R_{dd} = \frac{R_{di}}{1+(b\ R_{di})^c}}{R_dd = R_di / (1 + (b R_di)^c)}
#'
#' With \eqn{b = 1/R_{max}} and \eqn{c = 1} this reduces to the Beverton-Holt
#' reproduction rate, see [BevertonHoltRDD()].
#'
#' @param rdi Vector of density-independent reproduction rates
#' \eqn{R_{di}}{R_di} for all species.
#' @param species_params A species parameter dataframe. Must contain columns
#' `sheperd_b` and `sheperd_c` with the parameters b and c.
#' @param ... Unused
#'
#' @return Vector of density-dependent reproduction rates.
#' @export
#' @family functions calculating density-dependent reproduction rate
SheperdRDD <- function(rdi, species_params, ...) {
if (!all(c("sheperd_b", "sheperd_c") %in% names(species_params))) {
stop("The species_params dataframe must contain columns sheperd_b and sheperd_c.")
}
return(rdi / (1 + (species_params$sheperd_b * rdi)^species_params$sheperd_c))
}
#' Give density-independent reproduction rate
#'
#' Simply returns its `rdi` argument.
#'
#' @param rdi Vector of density-independent reproduction rates
#' \eqn{R_{di}}{R_di} for all species.
#' @param ... Not used.
#'
#' @return Vector of density-dependent reproduction rates.
#' @export
#' @family functions calculating density-dependent reproduction rate
noRDD <- function(rdi, ...) {
return(rdi)
}
#' Give constant reproduction rate
#'
#' `r lifecycle::badge("experimental")`
#' Simply returns the value from `species_params$constant_reproduction`.
#'
#' @param rdi Vector of density-independent reproduction rates
#' \eqn{R_{di}}{R_di} for all species.
#' @param species_params A species parameter dataframe. Must contain a column
#' `constant_reproduction`.
#' @param ... Unused
#'
#' @return Vector `species_params$constant_reproduction`
#' @export
#' @family functions calculating density-dependent reproduction rate
constantRDD <- function(rdi, species_params, ...) {
return(species_params$constant_reproduction)
}