```{css, echo=FALSE} .hide { display: none!important; }

/ https://bookdown.org/yihui/rmarkdown-cookbook/html-css.html / .modelScript pre, .modelScript pre.sourceCode code { background-color: #f0f8ff !important; }

```r
library(unittest)
# Redirect ok() output to stderr
options(unittest.output = stderr())

library(gadget3)
set.seed(123)
if (nzchar(Sys.getenv('G3_TEST_TMB'))) options(gadget3.tmb.work_dir = gadget3:::vignette_base_dir('work_dir'))
NB: This vignette is a work in progress

This vignette walks through a script that will generate a gadget3 model, explaining concepts along the way.

Code blocks that make up the gadget3 script are marked in blue, like this:

wzxhzdk:1

We only show the blocks that are relevant to implementing random effects, see the appendix for the entire script.

For an explanation of other parts of the script, see previous vignettes.

wzxhzdk:2
wzxhzdk:3

Spawning

In vignette("introduction-single-stock") we introduced g3a_renewal_normalparam() as a means of adding recruitment into the model.

An alternative action is g3a_spawn(). The main difference here is the existing state of the stock is used to inform the rate of recruitment.

To improve our model fit, we shall define the rate of spawning using a random walk.

Firstly, we define our immature stock. There's no real difference here, apart from g3a_renewal_normalparam() no longer being present:

wzxhzdk:4

Next, we need to define the set of parameters that will constitute our random walk:

wzxhzdk:5

As we saw in vignette('multiple-substocks'), by_year will give us a series of parameters for spawn_mu, one per year. random = TRUE will ensure that these parameters have TRUE in the random column in the parameter template.

The scale parameter adds seasonal variation parameters, spawn_mu_seasonal.1..spawn_mu_seasonal.4, which can be used to control when spawning happens.

We store this as a separate variable as we need to use it in 2 places. First, when we configure our spawning action:

wzxhzdk:6

Mature stocks spawn, their output going into the immature stock. We use suitability functions to define proportion_f, the proportion of stock ready to spawn, by_step meaning this proportion is seasonal. Our random walk is used as the rate of recruitment, mu.

Next we use a likelihood action to constrain the values in the random walk during optimisation:

wzxhzdk:7

For random effects to be useful, they have to be constrained to sensible bounds. There are 2 likelihood actions that help with this, g3l_random_dnorm() & g3l_random_walk(). The former penalises random values that stray outside given normal distribution, the latter constrains along a random walk; the current year's value should not vary significantly from the previous.

wzxhzdk:8
wzxhzdk:9
wzxhzdk:10

Creating model functions and Parameterization

At this point, we are ready to convert our model into code:

wzxhzdk:11
wzxhzdk:12

Finally we are ready for optimisation runs. g3_tmb_adfun() is a wrapper around TMB::MakeADFun() and TMB::compile, producing a TMB objective function. gadgetutils::g3_iterative() then optimises based on iterative reweighting

wzxhzdk:13

Appendix: Full model script

For convenience, here is all the sections of the model script above joined together:

```{js, echo=FALSE} document.write( '

' +
    Array.from(document.querySelectorAll('.modelScript pre')).map((x) => x.innerHTML).join("\n\n") +
    '
');

```r
# TODO:
# gadget3:::vignette_test_output("random-effects", model_code, params.out)


gadget-framework/gadget3 documentation built on June 13, 2025, 5:06 a.m.