Do Population Projections
Do_Population_Projection.RdProjects population dynamics forward in time under alternative recruitment and fishing mortality scenarios. The model initializes from terminal assessment quantities and advances numbers-at-age through recruitment, seasonal movement, mortality, ageing, and harvest control rules across multiple seasons and years.
Usage
Do_Population_Projection(
n_proj_yrs = 2,
n_pop,
n_regions,
n_ages,
n_sexes,
sexratio,
n_fish_fleets,
do_recruits_move = 0,
recruitment,
terminal_NAA,
terminal_NAA0,
terminal_F,
dmr = array(0, dim = c(n_regions, n_seas, n_fish_fleets)),
natmort,
natal_region = NULL,
WAA,
WAA_fish,
MatAA,
fish_sel,
ret_sel = array(1, dim = c(n_pop, n_regions, n_proj_yrs, n_seas, n_ages, n_sexes,
n_fish_fleets)),
Movement,
sgl_seas_spawning_movement = NULL,
stray_rate = NULL,
f_ref_pt = NULL,
b_ref_pt = NULL,
HCR_function = NULL,
recruitment_opt = "inv_gauss",
fmort_opt = "HCR",
catch_input = NULL,
catch_fallback_opt = if (fmort_opt == "Catch") "HCR" else fmort_opt,
catch_terminal_yr = FALSE,
catch_f_max = 5,
catch_tol = 1e-06,
catch_max_iter = 100,
t_spawn,
srr_opt = NULL,
bh_rec_opt = NULL,
n_seas = 1,
seasdur = rep(1/n_seas, n_seas),
spawn_seas = 1,
rec_seas_prop = {
rec_seas_prop = array(0, dim = c(n_pop, n_seas))
rec_seas_prop[] <- 1/n_seas
rec_seas_prop
},
Mrate = NULL,
move_timing = 0,
expm_nsub = 0,
rec_devs = NULL
)Arguments
- n_proj_yrs
Integer. Number of projection years.
- n_pop
Integer. Number of populations (may exceed regions when natal homing is modeled).
- n_regions
Integer. Number of spatial regions.
- n_ages
Integer. Number of age classes including the plus group.
- n_sexes
Integer. Number of sexes.
- sexratio
Array `[n_pop, n_regions, n_proj_yrs, n_sexes]`. Recruitment sex ratio used to allocate projected recruits by sex.
- n_fish_fleets
Integer. Number of fishing fleets.
- do_recruits_move
Integer (0 or 1). Whether age-1 recruits are subject to movement. Default = 0.
- recruitment
Array `[n_pop, n_regions, n_yrs]`. Historical recruitment used to condition stochastic projection options.
- terminal_NAA
Array `[n_pop, n_regions, n_seas, n_ages, n_sexes]`. Fished numbers-at-age in the terminal assessment year.
- terminal_NAA0
Array `[n_pop, n_regions, n_seas, n_ages, n_sexes]`. Unfished numbers-at-age in the terminal assessment year.
- terminal_F
Array `[n_regions, n_seas, n_fish_fleets]`. Terminal fishing mortality; sets F in projection year 1 and defines the seasonal F ratios applied in subsequent years.
- dmr
Array
[n_regions, n_seas, n_fish_fleets]. Discard mortality rate. Default behavior is no discard mortality (dmr = 0). When combined withret_sel = 1, this implies no discarding within a given fleet (all catch is retained).- natmort
Array of natural mortality, a rate per year in each season. Either `[n_pop, n_regions, n_proj_yrs, n_seas, n_ages, n_sexes]` or the same without the season dim, which is expanded across seasons. Annual natural mortality-at-age, scaled internally by season duration.
- natal_region
Integer vector `[n_pop]`. Natal region for each population. Only read when `n_pop > 1`, so `NULL` (the default) is valid for single-population models.
- WAA
Array `[n_pop, n_regions, n_proj_yrs, n_seas, n_ages, n_sexes]`. Weight-at-age used in spawning biomass calculations.
- WAA_fish
Array `[n_pop, n_regions, n_proj_yrs, n_seas, n_ages, n_sexes, n_fish_fleets]`. Fishery weight-at-age used in catch biomass calculations.
- MatAA
Array `[n_pop, n_regions, n_proj_yrs, n_seas, n_ages, n_sexes]`. Maturity-at-age.
- fish_sel
Array `[n_pop, n_regions, n_proj_yrs, n_seas, n_ages, n_sexes, n_fish_fleets]`. Fishery selectivity-at-age.
- ret_sel
Array
[n_pop, n_regions, n_proj_yrs, n_seas, n_ages, n_sexes, n_fish_fleets]. Retention selectivity-at-age. Default behavior corresponds to full retention (ret_sel = 1), meaning all captured fish are retained unless otherwise specified.- Movement
Array `[n_pop, n_regions, n_regions, n_proj_yrs, n_seas, n_ages, n_sexes]`. Seasonal movement transition matrices.
- sgl_seas_spawning_movement
Array `[n_pop, n_regions, n_regions, n_proj_yrs, n_ages, n_sexes]`. Spawning movement matrix applied when `n_seas = 1` and `n_pop > 1` to redistribute fish to natal grounds prior to SSB calculation. Only read in that case, so `NULL` (the default) is valid otherwise.
- stray_rate
Array `[n_pop, n_proj_yrs]`. Per-population stray rate used when accumulating effective SSB contributions across populations. Only read when `n_pop > 1`, so `NULL` (the default) is valid otherwise.
- f_ref_pt
Array `[n_regions, n_proj_yrs]`. Fishing mortality reference point (e.g., F_MSY) or fixed input F, depending on `fmort_opt`.
- b_ref_pt
Array `[n_pop, n_regions, n_proj_yrs]`. Biomass reference point used in harvest control rules.
- HCR_function
Function. Harvest control rule with arguments `x` (SSB), `frp` (F reference point), and `brp` (B reference point). A rule that also declares a `state` argument (or `...`) is handed this year's population as a named list, so a rule can be written on more than spawning biomass: `y` (projection year), `r` (region the F is being set for), `NAA`, `SSB`, `Total_Biom` and `Catch`. Mean weight, age structure and last year's catch all follow from those. Rules that do not declare it are called exactly as before and the state is not assembled.
- recruitment_opt
Character. Recruitment scenario: `"inv_gauss"`, `"mean_rec"`, `"zero"`, or `"bh_rec"`.
- fmort_opt
Character. Fishing mortality scenario: `"HCR"`, `"HCR_global"`, `"Input"`, or `"Catch"`. `"Catch"` solves each projection year's fishing mortality so that realized catch matches `catch_input`, leaving every other model quantity untouched.
- catch_input
Catch targets in biomass, used when `fmort_opt = "Catch"` and ignored otherwise. Either an array `[n_regions, n_proj_yrs]` of annual targets or `[n_regions, n_proj_yrs, n_seas]` of seasonal ones; which shape is supplied decides what gets solved. `catch_input[r, y]` is the catch removed from region `r` during projection year `y`, indexed the same way `proj_Catch` is in the returned list rather than with the one year lag `f_ref_pt` does. Targets are totals over populations and fleets, and over seasons too in the annual case. A target of 0 sets `F = 0` there without a solve.
With annual targets one annual F per region is solved for and split over seasons at the terminal year seasonal shares, exactly as the other `fmort_opt` settings do. With seasonal targets that constraint is released and a separate F is solved per region and season; the split across fleets within a season still stays at terminal year ratios, so fleet specific targets are not supported either way. A season the terminal year did not fish has no fleet split to inherit and so can take no catch, which is an error rather than a silent zero.
Not every projection year has to have a target. Set a year to `NA` and it falls back to `catch_fallback_opt` instead, which is the usual shape of catch advice: a year or two of agreed catch followed by the harvest control rule. `NA` (no target, use the fallback) and `0` (a target of no fishing) are different things. A year has to be all target or all `NA` across regions and seasons, since splitting one annual fallback F across only some seasons has no defensible reading; a partly specified year is an error.
Column 1 is only used when `catch_terminal_yr = TRUE`; see that argument.
- catch_fallback_opt
Character. Which rule sets F in the projection years `catch_input` leaves `NA`: `"HCR"`, `"HCR_global"`, or `"Input"`. Defaults to `"HCR"` under `fmort_opt = "Catch"` and to `fmort_opt` itself otherwise, where it is unused. Ignored unless `fmort_opt = "Catch"`, and its usual inputs (`f_ref_pt`, `b_ref_pt`, `HCR_function`) are only needed if some year actually falls back. Mind the indexing difference when mixing the two: `catch_input[r, y]` is the catch taken in year `y`, but `f_ref_pt[r, y]` sets F in year `y + 1`, which is the lag the HCR and Input options have always kept.
- catch_terminal_yr
Logical. Whether projection year 1, which replays the terminal assessment year, is also solved against its catch target rather than fished at `terminal_F`. Default `FALSE`. Set it `TRUE` for the common assessment case where the terminal year's catch is itself a projection because the year is not yet complete. Note that this overrides the F the assessment estimated for that year, and so changes the numbers-at-age entering year 2. Note also that with `n_seas > 1` the terminal year takes all its seasons from `terminal_NAA` rather than propagating them, so only the last season's F feeds year 2; the earlier seasons still take their catch, but do not otherwise propagate.
- catch_f_max
Numeric. Upper bound on the F searched when `fmort_opt = "Catch"`. Default 5. A target that cannot be taken even at this F is unreachable, in which case F is capped here, the target is undershot, and a warning names the regions involved.
- catch_tol
Numeric. Relative catch tolerance for the F solver. Default 1e-6.
- catch_max_iter
Integer. Maximum solver iterations per projection year. Default 100.
- t_spawn
Numeric scalar. Fraction of the spawning season elapsed before spawning; used for mid-season SSB calculations.
- srr_opt
Named list of inputs for deterministic stock-recruit recruitment when `recruitment_opt` is `"bh_rec"` or `"ricker_rec"`. The curve itself is taken from `recruitment_opt`, so the same list serves both. Formerly `bh_rec_opt`.
- bh_rec_opt
Deprecated. Former name of `srr_opt`; supplying it warns and forwards. Supplying both is an error. This list is passed directly to
Get_Det_Recruitmentand must contain all required arguments for that function.Required elements and their expected dimensions include:
R0Numeric vector
[n_pop]. Unfished recruitment.hNumeric array
[n_pop, n_regions]. Steepness.rec_region_propNumeric array
[n_pop, n_regions]. Recruitment allocation across regions (sums to 1 across regions).rec_seas_propNumeric array
[n_pop, n_seas]. Seasonal recruitment proportions (sums to 1 across seasons).SSBNumeric array
[n_pop, n_regions, n_yrs]. Historical spawning biomass, to which projected SSB is appended internally.WAAArray
[n_pop, n_regions, n_seas, n_ages]. Weight-at-age.MatAAArray
[n_pop, n_regions, n_seas, n_ages]. Maturity-at-age.natmortArray
[n_pop, n_regions, n_seas, n_ages]. Natural mortality, a rate per year in each season. Also accepted without the season dim.MovementArray
[n_pop, n_regions, n_regions, n_seas, n_ages]. Movement transition matrices.sgl_seas_spawning_movementArray
[n_pop, n_regions, n_regions, n_ages]. Spawning movement (single-season case).stray_rateNumeric vector
[n_pop]. Straying rates.init_FArray
[n_regions, n_seas, n_fish_fleets]. Initial fishing mortality.fish_selArray
[n_pop, n_regions, n_seas, n_ages, n_fish_fleets]. Total selectivity.ret_selArray
[n_pop, n_regions, n_seas, n_ages, n_fish_fleets]. Retention selectivity.dmrArray
[n_regions, n_seas, n_fish_fleets]. Discard mortality rates.sex_ratio_fNumeric array
[n_pop, n_regions]. Female recruitment proportion.
Additional scalar inputs include
rec_dd,rec_lag,n_pop,n_regions,n_ages,n_seas,spawn_seas,seasdur,t_spawn, anddo_recruits_move.Spawning biomass used in recruitment is constructed internally by combining
srr_opt$SSBwith projected SSB values during the simulation.srr_opt$rec_lag = 1is the classic lagged case: each projection year's recruitment is computed up front from the prior year's SSB, exactly asrecruitment_opt = "inv_gauss"/"mean_rec"are.srr_opt$rec_lag = 0is age-0 recruitment: recruitment for yearyis computed from yeary's own SSB oncespawn_seasis reached within that year's season loop, and is inserted no earlier thanspawn_seas(rec_seas_propmust be zero for every season beforespawn_seasin that case). Reference points and the seasonal SBPR calculation used to getsrr_opt$WAA/MatAA/etc. are unaffected by this choice,rec_lagonly changes which year's SSB feeds the Beverton-Holt curve, not the per-recruit math itself.- n_seas
Integer. Number of seasons. Default = 1.
- seasdur
Numeric vector `[n_seas]`. Duration of each season as a fraction of the year.
- spawn_seas
Integer. Spawning season index.
- rec_seas_prop
Array `[n_pop, n_seas]`. Proportion of annual recruitment entering in each season. Must sum to 1 across seasons for each population.
- Mrate
Array dimensioned like `Movement`, holding the instantaneous movement rates (the generator) rather than the realized transition fractions. Only read when `move_timing` is 1 or 2. `NULL` (default) is valid for `move_timing = 0`, where movement is applied as a transition matrix and no generator is needed.
- move_timing
Integer. When movement happens relative to mortality within a season. `0` (default) applies movement first and mortality afterwards; `1` applies mortality first and movement afterwards; `2` runs the two continuously and simultaneously, which also switches catch-at-age to the spatial Baranov form built on season-integrated abundance. Must match the timing used to derive the reference points the projection is run against.
- expm_nsub
Integer controlling how the matrix exponential is evaluated under `move_timing = 2`: `0` uses `Matrix::expm`, `n >= 1` uses `n` implicit backward Euler substeps. See [mat_exp()].
- rec_devs
Optional array
[n_pop, n_regions, n_proj_yrs]of multiplicative deviations applied to whatever recruitmentrecruitment_optproduces, so a deterministic option becomes a stochastic one under deviations the caller draws and owns. Defaults toNULL, which leaves recruitment as the option alone gives it. Projection year 1 replays the terminal assessment year and generates no recruitment, so its slice is never read. Drawing the deviations outside is what makes a set of replicates share the same recruitment across management procedures, and what lets the projection be differentiated with respect to the rule while the deviations are kept fixed.
Value
A named list of projected quantities. Year index 1 is the terminal assessment year replayed, so year 2 is the first projected year and catch advice for terminal year + 1 is read from index 2.
Several arrays have a trailing `n_proj_yrs + 1` year slot, which is used inconsistently and is noted per element below. In short: `proj_NAA`, `proj_NAA0`, `proj_F` and `proj_F_seas` fill it, and `proj_ZAA`, `proj_ret_FAA` and `proj_disc_FAA` leave it at 0.
proj_FArray `[n_regions, n_proj_yrs + 1]`. Annual fishing mortality by region, summed over seasons and fleets. The trailing column holds the F the harvest control rule or input would apply in the year after the projection; it stays 0 under `fmort_opt = "Catch"`, where there is no further year to solve a target for.
proj_F_seasArray `[n_regions, n_proj_yrs + 1, n_seas]`. The same fishing mortality broken out by season, so `rowSums(proj_F_seas[, y, ])` recovers `proj_F[, y]` for every `y`, including the trailing column. This is the only place the answer lives when seasonal catch targets are used, since an annual total cannot represent a seasonal solve.
proj_ret_FAAArray `[n_pop, n_regions, n_proj_yrs + 1, n_seas, n_ages, n_sexes, n_fish_fleets]`. Retained fishing mortality-at-age, i.e. the component that generates landed catch. Only years `1:n_proj_yrs` are filled; the trailing year slot stays 0.
proj_disc_FAAArray dimensioned as `proj_ret_FAA`, and filled over the same years. Discard fishing mortality-at-age, i.e. the component killed but not landed, set by `ret_sel` and `dmr`. Total fishing mortality-at-age is the sum of the two.
proj_CatchArray `[n_pop, n_regions, n_proj_yrs, n_seas, n_fish_fleets]`. Retained catch in biomass. Built from `proj_ret_FAA`, so discard mortality acts on the population but is not counted here, and this is the quantity `catch_input` is matched against.
proj_SSBArray `[n_pop, n_regions, n_proj_yrs]`. Female spawning biomass, accumulated in `spawn_seas` with the `t_spawn` mortality correction. Halved when `n_sexes = 1`.
proj_eff_SSBArray `[n_pop, n_proj_yrs]`. Effective spawning biomass at each population's natal region, aggregating contributions from every population with cross-population terms scaled by `stray_rate`. Equal to spawning biomass summed across regions when `n_pop = 1`.
proj_Total_BiomArray `[n_pop, n_regions, n_proj_yrs]`. Total biomass over all ages and both sexes, accumulated at the same point in the season as `proj_SSB` and using the same definition the estimation model uses for `Total_Biom`, so the projected series continues the estimated one without a discontinuity at the terminal year.
proj_Dynamic_SSB0Array `[n_pop, n_regions, n_proj_yrs]`. Spawning biomass the population would have kept under the same realized recruitment but no fishing, for dynamic depletion.
proj_NAAArray `[n_pop, n_regions, n_proj_yrs + 1, n_seas, n_ages, n_sexes]`. Fished numbers-at-age kept at the start of each season, before that season's mortality and ageing. Under the default `move_timing = 0` movement has already been applied at this point; under `move_timing` 1 and 2 it has not, since movement is deferred into the mortality step. The trailing year slot is filled, and holds the numbers passed into the year after the projection ends.
proj_NAA0Array dimensioned as `proj_NAA`. The unfished counterpart, decremented by natural mortality alone.
proj_ZAAArray `[n_pop, n_regions, n_proj_yrs + 1, n_seas, n_ages, n_sexes]`. Total mortality-at-age for the season: natural mortality scaled by season duration, plus retained and discard fishing mortality summed over fleets. Only years `1:n_proj_yrs` are filled; the trailing year slot stays 0.
proj_catch_residArray shaped like `catch_input`: `[n_regions, n_proj_yrs]` for annual targets, `[n_regions, n_proj_yrs, n_seas]` for seasonal ones. Relative miss on each catch target, `(realized - target) / target`, and `NA` for years with no target (including every year when `fmort_opt != "Catch"`). Should be at or below `catch_tol` wherever the solve converged, and is worth checking directly rather than relying on warnings alone.
Details
Population dynamics are tracked over
[population x region x year x season x age x sex]. Recruitment is
generated annually and then distributed across seasons using
rec_seas_prop, allowing intra-annual timing of recruitment within
the first age class.
Each projection year proceeds as follows when
recruitment_opt != "bh_rec" or srr_opt$rec_lag != 0
(the classic case):
Annual recruitment is generated and allocated across regions and sexes. Seasonal recruitment is then distributed within the first age class using
rec_seas_prop, with additional recruits entering in seasonsseas > 1.Fishing mortality-at-age is constructed from annual F, seasonal F ratios derived from the terminal year, and selectivity.
Movement is applied at each seasonal step via transition matrices. Age-1 movement is optional via
do_recruits_move.Within-season mortality is applied using exponential decay. At the end of the final season, individuals age forward and the plus group accumulates survivors.
Spawning biomass is computed in
spawn_seasusing a mid-season mortality correction. For natal homing models with a single season, spawning movement is applied prior to SSB calculation.Catch is calculated using the Baranov equation and aggregated to biomass using fishery-specific weights.
Fishing mortality for the next year is updated via the specified harvest control rule or fixed input.
When srr_opt$rec_lag == 0 (age-0 recruitment), steps 1 and 5
above are reordered within spawn_seas: movement is applied first,
spawning biomass is computed from the survivor population alone (no new
recruits exist yet), that SSB is used to generate this year's
recruitment, and only then are the recruits inserted (no earlier than
spawn_seas) - immediately before mortality/ageing runs for that
season, so the new cohort is advanced exactly like any other
seasonal recruit pulse. Years y > 1 generate recruitment this way;
year 1 holds the supplied terminal assessment state forward with no new
recruitment event, matching the classic case.
Under fmort_opt = "Catch" step 7 moves to the front of the following
year instead: the F that lands a catch target depends on that year's own
numbers-at-age, not on the previous year's spawning biomass, so it cannot be
set at the end of the previous year the way the HCR and Input options are.
The year is run repeatedly at trial F values until realized catch matches the
target, then run once more at the accepted F and committed. Steps 1 to 6 are
otherwise unchanged, and no demographic input is modified: only F moves.
Regions are solved jointly rather than one at a time, because between-season
movement (and, under move_timing = 2, the season-integrated abundance)
makes each region's catch depend on the F set in every other region. Seasonal
targets are instead swept forward one season at a time, which is exact because
a season's catch depends only on the F in that season and earlier ones.
Note that the catch solved against is retained catch, matching
proj_Catch. Discard mortality still acts on the population through
dmr and ret_sel, so a fleet that discards will exert more total
F than the target alone implies.
Effective spawning biomass at each population's natal region aggregates
contributions from all populations, with cross-population contributions
scaled by stray_rate and normalized by the number of populations
in each natal region.
When n_sexes = 1, spawning biomass is multiplied by 0.5. When
n_regions = 1, movement is skipped.
Differentiating through the projection
The projection uses RTMB's replacement operators, so it can be taped with
MakeTape or MakeADFun and handed to an
optimizer with an exact gradient. That gives an F schedule solved against an
objective rather than scanned over a grid, and the delta method on projected
quantities from a fitted model's parameters.
Two options are refused when the inputs are AD types, because neither has a
derivative and both would otherwise return a gradient that is wrong rather
than an error. recruitment_opt = "inv_gauss" draws recruitment at
random, and fmort_opt = "Catch" inverts the catch target with a
numerical solve, so the F it hands back has no derivative. Tape under
"mean_rec", "bh_rec" or "ricker_rec" with
fmort_opt = "Input".
A control rule stops on its own rather than being refused here. The usual threshold rule branches on stock status, and a comparison against an AD spawning biomass raises an error inside RTMB. Optimizing through a control rule means writing a smooth one.
See also
Other Reference Points and Projections:
Get_Reference_Point_Uncertainty(),
Get_Reference_Points(),
get_key_quants()