Skip to contents

As part of the model_options list that is a required input to the MSE function, users must specify a recruitment function as well as relevant parameter values for the OM to project future recruitment. Some simple recruitment functions are prepackaged with the model – a Beverton-Holt stock recruit function, a function that resamples from the historical recruitment timeseries, and two different functions that specify distinct recruitment regimes – but users are also able to specify their own custom recruitment functions, as necesarry.

A simple example of specifying a recruitment function for the MSE is as follows:

resample_recruits <- function(hist_recruits, nyears, seed){
    set.seed(seed)
    return(sample(hist_recruits, size=nyears, replace=TRUE))
}

om$recruitment$func <- resample_recruits
om$recruitment$pars <- list(
    hist_recruits = rnorm(100, mean=25, sd=2),
    nyears = 100
)

The om$recruitment$func list element is a reference to the recruitment function that should be used to project recruitment in the future, while om$recruitment$pars is a named list of parameter values spcific to the provided recruitment function. Note that the final required parameter in resample_recruits, “seed”, is not povided in the recruitment$pars list. Instead, this parameter is dynmically passed to the recruitment function within the MSE loop, thus ensuring that recruitment timeseries remain reproducible across multiple simpulations.

Working with Existing Recruitment functions

Four recruitment functions come pre-packaged with the repository:

  1. resample_recruits - randomly resample from a known recruitment timeseries
  2. resample_regime_recruits - randomly resample recruits form a known recruitment timeseries with pre-defined regimes
  3. regime_recruits - randonly draw recruitment from regime-specific distributions
  4. beverton_holt - a Beverton-Holt stock recruit relationships, parameterized with steepness

The first three functions all function in the same way as in the example above, where users simple provide the function name, and a named parameter list (without the final seed parameter).

The beverton_holt function works differently however, due to it specifying a state-dependent recruitment function. This function is an R function factory (a funtion that returns another function), that accepts the standard Beverton-Holt parameters – h, R0, and S0 – and returns back a new function to which SSB is provided an input (see the example below).

beverton_holt <- function(h, R0, S0, sigR, seed){
    # note that the set.seed() call needs to happen
    # outside of the returned function, or else there
    # will be no random variability in recruitment draws
    set.seed(seed) 
    function(ssb){
        bh <- (4*R0*h*ssb)/((1-h)*R0*(S0/R0) + (5*h - 1)*ssb)
        return(
            bh + exp(rnorm(1, mean=0, sd=sigR)) # lognormal deviates
        )
    }
}

bevholt <- beverton_holt(h=0.7, R0=25, S0=300, sigR=1, seed=1120)
bevholt(ssb=50) # 16.65
## [1] 17.74222

This function factory can be used in nearly exactly the same way as the previous three recruitment functions:

om$recruitment$func <- beverton_holt
om$recruitment$pars <- list(
    h=0.70,
    R0=25,
    S0=300,
    sigR=1
)

Like with the other recruitment functions, the final “seed” parameter is not provided as input in the recruitmemt$pars list. The MSE will internally handle computing SSB at the beginning of each year and using the defined SRR to generate an annual recruitment level.

Defining Custom Recruitment Functions

Users can, optionally, define their own recruitment functions beyond what comes pre-packaged with the MSE.

There are two types of recruitment functions that can be developed: those which are state-dependent (such as the Beverton-Holt), and those that are not state-dependent (such as the recruitment regime functions). State-independent recruitment functions have the useful property that the entire recruitment timeseries can be defined before the MSE simulation starts (which is helpful for guaranteeing reproducability between model runs), while state-depenedent functions are only realized at the start of each simulation year. Where possible, we recommend defining state-independent recruitment functions.

The R function that defines a custom recruitment function, regardless of type, can take any form it needs too with the important caveat that the final function pararmeter must be called “seed” and represent a random seed (this holds even if the custom recruitment functions is completely deterministic). Below is an example of a recruitment function that random pulls recruitment from a lognormal distribution:

random_lognormal <- function(log_mean_rec, sigR, nyears, seed){
    set.seed(seed)
    return(exp(log_mean_rec + rnorm(nyears, 0, sigR) - 0.5*sigR^2))
}

random_lognormal(log_mean_rec = log(25), sigR = 1.04, nyears = 5, seed = 1007) # 25.022 19.746 55.721 14.737 5.858

This is an example of a “state-independent” recruitment function. The function takes a mean recruitment level (in log space) and a recruitment variation and computes nyears random recruitment levels. Nearly all such state-independent recruitment functions will need to accept an nyears parameter in order to generate the correct number of recruitment events. Similarly, like all recruitment functions, the final parameter defines a random seed.