Rceattle C++ template
The CEATTLE likelihood: src/TMB/ceattle.cpp and its headers
Loading...
Searching...
No Matches
growth.hpp
Go to the documentation of this file.
1#ifndef GROWTH_HPP
2#define GROWTH_HPP
3
4/**
5 * @brief SD of length-at-age (cm) for one age, year and sex.
6 *
7 * The variability term v is \f$e^{sd_0}\f$ at or below `age_L1`, pinned to
8 * \f$e^{sd_1}\f$ for the plus group under `sd_style == 1` (WHAM; also SS3 with
9 * Growth_Age_for_L2 = 999), and otherwise interpolated linearly in length between
10 * \f$(l_1, e^{sd_0})\f$ and \f$(L_\infty, e^{sd_1})\f$. `sd_form` 1 makes v an SD in cm
11 * (SS3 CV_Growth_Pattern 2), 2 a CV, so SD = v * L (SS3 CV_Growth_Pattern 0).
12 */
13template<class Type>
14Type length_sd_at_age(Type current_age, Type age_L1, bool plus_group,
15 int sd_style, int sd_form, Type l1, Type linf, Type len,
16 Type log_sd0, Type log_sd1) {
17 Type sd0 = exp(log_sd0);
18 Type sd1 = exp(log_sd1);
19 Type v;
20 if(current_age <= age_L1) {
21 v = sd0;
22 } else if(plus_group && sd_style == 1) {
23 v = sd1;
24 } else {
25 v = sd0 + (sd1 - sd0) / (linf - l1) * (len - l1);
26 }
27 if(sd_form == 2) v = v * len;
28 return v;
29}
30
31
32/**
33 * @brief Age-length key, weight-at-age and mature weight-at-age for one cell.
34 *
35 * Length is normal with mean `mu` and SD `sd` (cm) on the population length bins
36 * `lengths_pop` (lower edges): the first bin is a minus group, the last a plus group
37 * (SS3's convention).
38 *
39 * Weight-at-age is \f$\sum_l P(l|a) \alpha L_{mid}^\beta\f$ at population-bin midpoints
40 * (kg). With maturity-at-length, mature weight-at-age is the same sum with the logistic
41 * maturity \f$1/(1+e^{-s(L_{mid} - L_{50})})\f$ inside: SS3's fecundity-at-age when
42 * fecundity equals body weight.
43 */
44template<class Type>
45void fill_age_length_key(int wtind, int sp, int sex, int age, int yr,
46 Type mu, Type sd,
47 const vector<int>& nlengths_pop,
48 matrix<Type>& lengths_pop,
49 matrix<Type>& weight_length_pars,
50 const vector<int>& mat_len_use,
51 matrix<Type>& mat_len_pars,
52 array<Type>& growth_matrix,
53 array<Type>& weight_hat,
54 array<Type>& mat_weight_hat) {
55 int np = nlengths_pop(sp);
56 // Kept on the POPULATION bins: readers multiply by selectivity-at-length there, as SS3
57 // does, and sum into data bins afterwards (ceattle.cpp section 2.3c). Aggregating here
58 // would apply one bin-average selectivity across a data bin.
59 for(int lp = 0; lp < np; lp++) growth_matrix(wtind, sex, age, lp, yr) = Type(0.0);
60
61 Type expected_weight = 0.0;
62 Type expected_mat_weight = 0.0;
63 for(int lp = 0; lp < np; lp++) {
64 Type prob;
65 if(np < 2) {
66 // One bin spans the whole length distribution, so it holds all of it.
67 // Tested before the lp == 0 branch, which would read the second edge.
68 prob = Type(1.0);
69 } else if(lp == 0) {
70 prob = pnorm((lengths_pop(sp, 1) - mu) / sd);
71 } else if(lp == (np - 1)) {
72 prob = 1.0 - pnorm((lengths_pop(sp, np - 1) - mu) / sd);
73 } else {
74 prob = pnorm((lengths_pop(sp, lp + 1) - mu) / sd) - pnorm((lengths_pop(sp, lp) - mu) / sd);
75 }
76 growth_matrix(wtind, sex, age, lp, yr) = prob;
77
78 // Bin midpoint (cm): lower edge plus half its own width, the last bin taking the
79 // previous bin's width. A single-bin grid has no neighbour to take a width from,
80 // so it keeps the edge itself -- as selectivity.hpp does.
81 Type lenmid;
82 if(lp < np - 1) {
83 lenmid = (lengths_pop(sp, lp) + lengths_pop(sp, lp + 1)) / Type(2.0);
84 } else if(np < 2) {
85 lenmid = lengths_pop(sp, np - 1);
86 } else {
87 lenmid = lengths_pop(sp, np - 1) + (lengths_pop(sp, np - 1) - lengths_pop(sp, np - 2)) / Type(2.0);
88 }
89 Type wt_len = weight_length_pars(sp, 0) * pow(lenmid, weight_length_pars(sp, 1));
90 expected_weight += prob * wt_len;
91 if(mat_len_use(sp) == 1) {
92 expected_mat_weight += prob * wt_len / (Type(1.0) + exp(-mat_len_pars(sp, 1) * (lenmid - mat_len_pars(sp, 0))));
93 }
94 }
95 weight_hat(wtind, sex, age, yr) = expected_weight;
96 if(mat_len_use(sp) == 1) mat_weight_hat(wtind, sex, age, yr) = expected_mat_weight;
97}
98
99/**
100 * @brief Jan-1 (month 0) mean length, age-length key and weight-at-age for one species.
101 *
102 * Mean length-at-age (cm) is anchored at \f$L(a_{L1}) = l_1\f$:
103 * - von Bertalanffy (`growth_model` 1):
104 * \f$L_a = L_{\infty} + (l_1 - L_{\infty}) \cdot e^{-K(a - a_{L1})}\f$
105 * - Richards (2):
106 * \f$L_a = [L_{\infty}^m + (l_1^m - L_{\infty}^m) \cdot e^{-K(a - a_{L1})}]^{1/m}\f$
107 * - Below the anchor, a linear ramp from `Lmin_sp` at age 0 to \f$l_1\f$ at `age_L1`.
108 * - After year 0 a cohort recursion advances \f$L_{a, y}\f$ from \f$L_{a-1, y-1}\f$ with
109 * the previous year's parameters; where that predecessor is still on the ramp, or at
110 * slot 0, the closed-form anchor at \f$l_1\f$ is used instead.
111 *
112 * Weight-at-age (kg) is integrated across the length distribution rather than taken at
113 * mean length, which Jensen's inequality would bias:
114 * \f$W_a = \sum_{ln} P(ln | a) \cdot \alpha \cdot L_{mid}^{\beta}\f$.
115 *
116 * @param wtind Weight index slot to write into.
117 * @param sp Species index.
118 * @param minage Minimum modelled age per species; 0 is supported.
119 * @param growth_model Per species, 1 = von Bertalanffy, 2 = Richards.
120 * @param growth_parameters Time-varying growth parameters by species, sex, year and
121 * parameter: K (per year), L1 and Linf (cm), Richards m.
122 * @param growth_log_sd Log-scale variability endpoints: index 0 at L1, index 1 at Linf.
123 * @param weight_length_pars Allometric \f$\alpha\f$ and \f$\beta\f$, kg from cm.
124 * @param length_hat [Output] mean length-at-age (cm).
125 * @param growth_matrix [Output] age-length key on the population length bins.
126 * @param weight_hat [Output] integrated weight-at-age (kg).
127 */
128template<class Type>
130 int wtind,
131 int sp,
132 int nspp,
133 int nyrs,
134 const vector<int>& nsex,
135 const vector<int>& nages,
136 const vector<int>& nlengths,
137 const vector<int>& minage,
138 const vector<Type>& growth_age_L1,
139 const vector<int>& growth_model,
140 const vector<int>& growth_sd_style, // Plus-group SD-at-age: 1 = WHAM pin, 2 = SS3 by length
141 const vector<int>& growth_sd_form, // 1 = SD endpoints in cm, 2 = CV endpoints (SD = CV * L)
142 const vector<int>& growth_plus_length,// Plus-group mean length: 1 = M1-weighted,
143 // 2 = no adjustment, 3/4 = SS3 Linf_decay
144 const vector<Type>& plus_group_decay, // Decay rate (per year) for growth_plus_length == 4
145 matrix<Type>& lengths,
146 const vector<int>& nlengths_pop,
147 matrix<Type>& lengths_pop, // Population length bins, lower edges (cm)
148 array<Type>& growth_parameters,
149 array<Type>& growth_log_sd,
150 matrix<Type>& weight_length_pars,
151 const vector<int>& mat_len_use, // 1 = maturity-at-length for this species
152 matrix<Type>& mat_len_pars, // [sp, 0] = L50 (cm), [sp, 1] = logistic slope (per cm)
153 array<Type>& log_M1, // Base natural mortality at age [nspp, nsex, nages], log scale
154 array<Type> &length_hat, // Modified by reference
155 array<Type> &growth_matrix, // Modified by reference
156 array<Type> &weight_hat, // Modified by reference
157 array<Type> &mat_weight_hat // Modified by reference (maturity-at-length species only)
158) {
159
160 Type b_len, last_linear, current_age;
161
162 // The linear ramp below age_L1 starts from the lowest population length edge (cm) at
163 // age 0 (SS3's len_bins(1)); with no population grid that is the lowest data bin.
164 Type Lmin_sp = lengths_pop(sp, 0);
165 // Anchor age, where mean length is `l1` (SS3's Growth_Age_for_L1). fit_mod() resolves
166 // an unset value to max(0.5, minage[sp]): an SS3-style half-year anchor at minage = 0.
167 Type age_L1 = growth_age_L1(sp);
168
169 // An anchor at age 0 would divide by zero in the ramp slope b_len, so the slope and the
170 // cohort-boundary test below both floor it at 1 year.
171 Type age_L1_safe = age_L1;
172 if (age_L1 <= Type(0)) age_L1_safe = Type(1);
173
174 for(int sex = 0; sex < nsex(sp); sex++) {
175 for(int yr = 0; yr < nyrs; yr++) {
176 for(int age = 0; age < nages(sp); age++) {
177
178 // This sex and year: K (per year), L1 and Linf (cm), Richards m.
179 Type kappa = growth_parameters(sp, sex, yr, 0);
180 Type l1 = growth_parameters(sp, sex, yr, 1);
181 Type linf = growth_parameters(sp, sex, yr, 2);
182 Type m = growth_parameters(sp, sex, yr, 3);
183 // Age (years) at the start of the year: 0-based slot `age` holds the
184 // (age + minage) cohort. This is the SLOT age, not the anchor age_L1 above, and
185 // adding 1 rather than minage reads the wrong age at any minage != 1.
186 current_age = Type(age) + Type(minage(sp));
187
188 // 1. Calculate Mean Length at Age ---
189 switch(growth_model(sp)) {
190 case 1: // Von Bertalanffy
191
192 // Slope from Lmin to L1
193 b_len = (l1 - Lmin_sp) / age_L1_safe; // age_L1_safe == age_L1 unless the anchor is <= 0
194
195 // Linear ramp below the anchor age
196 if((current_age) <= age_L1){
197 length_hat(wtind, sex, age, yr) = Lmin_sp + b_len * (current_age);
198 } else {
199 if(yr == 0) {
200 length_hat(wtind, sex, age, yr) = linf + (l1 - linf) * exp(-kappa * (current_age - age_L1));
201 } else { // Yr > 0
202 // The recursion below reads the same cohort one year younger, so it is
203 // valid only once that slot is on the curve. Where it is still on the ramp
204 // -- or at slot 0, which has no predecessor -- read off the anchor instead.
205 if(current_age - Type(1) < age_L1_safe || age == 0) {
206 last_linear = Lmin_sp + b_len * age_L1_safe;
207 length_hat(wtind, sex, age, yr) = last_linear + (last_linear - linf) * (exp(-kappa * (current_age - age_L1)) - 1.0);
208 } else {
209 // Lag 1-year parameters
210 Type lagkappa = growth_parameters(sp, sex, yr - 1, 0);
211 Type laglinf = growth_parameters(sp, sex, yr - 1, 2);
212 length_hat(wtind, sex, age, yr) = length_hat(wtind, sex, age - 1, yr - 1) + (length_hat(wtind, sex, age - 1, yr - 1) - laglinf) * (exp(-lagkappa) - 1.0);
213 }
214 }
215 }
216 break;
217
218 case 2: // Richards
219
220 // Slope from Lmin to L1
221 b_len = (l1 - Lmin_sp) / age_L1_safe;
222
223 // Linear ramp below the anchor age
224 if((current_age) <= age_L1) {
225 length_hat(wtind, sex, age, yr) = Lmin_sp + b_len * (current_age);
226 } else {
227 if(yr == 0) {
228 length_hat(wtind, sex, age, yr) = pow(pow(linf, m) + (pow(l1, m) - pow(linf, m)) * exp(-kappa * (current_age - age_L1)), 1 / m);
229 } else { // Yr > 0
230 // Same cohort-boundary test as the VBGF branch above.
231 if(current_age - Type(1) < age_L1_safe || age == 0) {
232 last_linear = Lmin_sp + b_len * age_L1_safe;
233 length_hat(wtind, sex, age, yr) = pow(pow(last_linear, m) + (pow(last_linear, m) - pow(linf, m)) * (exp(-kappa * (current_age - age_L1)) - 1.0), 1 / m);
234 } else {
235 // Lag 1-year parameters
236 Type lagkappa = growth_parameters(sp, sex, yr - 1, 0);
237 Type laglinf = growth_parameters(sp, sex, yr - 1, 2);
238 Type lagm = growth_parameters(sp, sex, yr - 1, 3);
239 length_hat(wtind, sex, age, yr) = pow(pow(length_hat(wtind, sex, age - 1, yr - 1), lagm) + (pow(length_hat(wtind, sex, age - 1, yr - 1), lagm) - pow(laglinf, lagm)) * (exp(-lagkappa) - 1.0), 1 / lagm);
240 }
241 }
242 }
243 break;
244
245 case 3: // Non-parametric (Free parameters)
246 error("Non-parametric growth not yet implemented");
247 break;
248
249 default:
250 error("Invalid 'growth_model");
251 } // Growth_model switch
252
253
254 // 2. Plus-Group Mean Length (Oldest Age Only) ---
255 // The plus group holds fish past the oldest age, so its mean length (cm) lies
256 // between L(oldest age) and Linf. growth_plus_length: 1 = weighted by survival at
257 // the oldest age's M1, 2/3/4 = SS3's Linf_decay -998/-999/d (?build_growth).
258 if(growth_model(sp) < 3 && age == (nages(sp) - 1)) {
259 Type current_size = length_hat(wtind, sex, age, yr);
260 Type diff = linf - current_size;
261 int oldest_age = minage(sp) + nages(sp) - 1;
262 if(growth_plus_length(sp) == 1) {
263 Type temp_n = 0, temp_sum = 0, weight_a = 1.0;
264 Type surv = exp(-exp(log_M1(sp, sex, nages(sp) - 1)));
265 for(int a = 0; a <= nages(sp); a++) {
266 temp_sum += weight_a * (current_size + (Type(a) / Type(nages(sp))) * diff);
267 temp_n += weight_a;
268 weight_a *= surv;
269 }
270 length_hat(wtind, sex, age, yr) = temp_sum / temp_n;
271 } else if(growth_plus_length(sp) == 3) {
272 Type temp_n = 0, temp_sum = 0;
273 // Survival weights at a fixed 0.2/yr, the nominal mortality SS3 uses for
274 // Linf_decay = -999 -- not this species' M1, which is what form 1 above uses.
275 for(int a = 0; a <= oldest_age; a++) {
276 Type weight_a = exp(Type(-0.2) * Type(a));
277 temp_sum += weight_a * (current_size + (Type(a) / Type(oldest_age)) * diff);
278 temp_n += weight_a;
279 }
280 length_hat(wtind, sex, age, yr) = temp_sum / temp_n;
281 } else if(growth_plus_length(sp) == 4) {
282 Type size = current_size, temp_sum = current_size, temp_n = 1.0, weight_a = 1.0;
283 // Each further age is one more year along the von Bertalanffy curve, for
284 // either growth family, weighted by exp(-plus_group_decay) per year. Averaged
285 // over 2 x the oldest age, SS3's span, by when the weights are negligible.
286 for(int a = 1; a <= 2 * oldest_age; a++) {
287 weight_a *= exp(-plus_group_decay(sp));
288 size += (linf - size) * (Type(1.0) - exp(-kappa));
289 temp_sum += weight_a * size;
290 temp_n += weight_a;
291 }
292 length_hat(wtind, sex, age, yr) = temp_sum / temp_n;
293 }
294 }
295
296 // 3. SD of length-at-age, then age-length key and weight-at-age ---
297 if(growth_model(sp) < 3) {
298 Type len = length_hat(wtind, sex, age, yr);
299 Type sd = length_sd_at_age(current_age, age_L1, age == (nages(sp) - 1),
300 growth_sd_style(sp), growth_sd_form(sp), l1, linf, len,
301 growth_log_sd(sp, sex, 0), growth_log_sd(sp, sex, 1));
302 fill_age_length_key(wtind, sp, sex, age, yr, len, sd, nlengths_pop,
303 lengths_pop, weight_length_pars,
304 mat_len_use, mat_len_pars, growth_matrix, weight_hat, mat_weight_hat);
305 }
306 } // age
307 } // yr
308 } // sex
309}
310
311
312
313/**
314 * @brief Mean length-at-age, age-length key and weight-at-age `fracyr` into the year.
315 *
316 * Advances the Jan-1 mean length stored at `id_pop` by `fracyr` of growth, for SSB
317 * weight-at-age at the spawning month and each fleet's weight-at-age at its own month:
318 * - von Bertalanffy (`growth_model` 1):
319 * \f$L_a = L_{\infty} + (L_{a, jan1} - L_{\infty}) \cdot e^{-K \cdot fracyr}\f$
320 * - Richards (2):
321 * \f$L_a = [L_{\infty}^m + (L_{a, jan1}^m - L_{\infty}^m) \cdot e^{-K \cdot fracyr}]^{1/m}\f$
322 * - Below the anchor age (`current_age <= age_L1`) the linear ramp applies, as at Jan-1.
323 *
324 * Under `growth_plus_length == 1` the plus group keeps the Jan-1 mean length
325 * `estimate_growth()` set for it; under the SS3 forms (2-4) it grows within the year like
326 * every other age, as SS3 does.
327 *
328 * Weight-at-age (kg) is integrated over the length distribution as in estimate_growth().
329 *
330 * @param wtind Weight index slot to write into.
331 * @param id_pop Weight index holding the Jan-1 lengths the advance starts from.
332 * @param sp Species index.
333 * @param fracyr Fraction of the year (0.0 - 1.0) to advance growth by.
334 * @param growth_parameters,growth_log_sd,weight_length_pars As in estimate_growth().
335 * @param length_hat,growth_matrix,weight_hat [Output] As in estimate_growth().
336 */
337template<class Type>
339 int wtind,
340 int id_pop,
341 int sp,
342 Type fracyr,
343 int nspp,
344 int nyrs,
345 const vector<int>& nsex,
346 const vector<int>& nages,
347 const vector<int>& nlengths,
348 const vector<int>& minage,
349 const vector<Type>& growth_age_L1,
350 const vector<int>& growth_model,
351 const vector<int>& growth_sd_style, // Plus-group SD-at-age: 1 = WHAM pin, 2 = SS3 by length
352 const vector<int>& growth_sd_form, // 1 = SD endpoints in cm, 2 = CV endpoints (SD = CV * L)
353 const vector<int>& growth_plus_length,// 1 = plus group held at Jan-1 length; 2-4 = it grows
354 matrix<Type>& lengths,
355 const vector<int>& nlengths_pop,
356 matrix<Type>& lengths_pop, // Population length bins, lower edges (cm)
357 array<Type>& growth_parameters,
358 array<Type>& growth_log_sd,
359 matrix<Type>& weight_length_pars,
360 const vector<int>& mat_len_use, // 1 = maturity-at-length for this species
361 matrix<Type>& mat_len_pars, // [sp, 0] = L50 (cm), [sp, 1] = logistic slope (per cm)
362 array<Type> &length_hat, // Modified by reference
363 array<Type> &growth_matrix, // Modified by reference
364 array<Type> &weight_hat, // Modified by reference
365 array<Type> &mat_weight_hat // Modified by reference (maturity-at-length species only)
366) {
367
368 Type b_len, current_age, last_linear;
369
370 // Ramp origin (lowest population length edge, cm, SS3's len_bins(1)) and anchor age
371 // (SS3's Growth_Age_for_L1), both as in estimate_growth().
372 Type Lmin_sp = lengths_pop(sp, 0);
373 Type age_L1 = growth_age_L1(sp);
374
375 // Floors the ramp slope's denominator at 1 year when the anchor is at age 0. This
376 // routine advances each slot from its own Jan-1 length, so unlike estimate_growth() it
377 // has no cohort-boundary test to floor.
378 Type age_L1_safe = age_L1;
379 if (age_L1 <= Type(0)) age_L1_safe = Type(1);
380
381 for(int sex = 0; sex < nsex(sp); sex++) {
382 for(int yr = 0; yr < nyrs; yr++) {
383 for(int age = 0; age < nages(sp); age++) {
384
385 // This sex and year: K (per year), L1 and Linf (cm), Richards m.
386 Type kappa = growth_parameters(sp, sex, yr, 0);
387 Type l1 = growth_parameters(sp, sex, yr, 1);
388 Type linf = growth_parameters(sp, sex, yr, 2);
389 Type m = growth_parameters(sp, sex, yr, 3);
390 // As in estimate_growth(): the slot age, not the anchor age_L1, offset by fracyr.
391 // Adding 1 rather than minage reads the wrong age at any minage != 1.
392 current_age = Type(age) + Type(minage(sp)) + fracyr;
393
394 // 1. Calculate Mean Length at Age ---
395 switch(growth_model(sp)) {
396 case 1: // Von Bertalanffy
397
398 // Slope from Lmin to L1
399 b_len = (l1 - Lmin_sp) / age_L1_safe; // age_L1_safe == age_L1 unless the anchor is <= 0
400
401 // Linear ramp below the anchor age
402 if((current_age) <= age_L1){
403 length_hat(wtind, sex, age, yr) = Lmin_sp + b_len * (current_age);
404 // Plus group PINNED at the Jan-1 length estimate_growth() wrote for it, so this
405 // override comes BEFORE the anchor test below, which also matches it when the
406 // whole age range sits under the anchor and would discard that pinned length.
407 // `age + 1.0 == nages(sp)` is a slot ordinal (0-based `age`, `nages` a count).
408 }else if(age + 1.0 == nages(sp) && growth_plus_length(sp) == 1) { // Pinned at Jan-1
409 length_hat(wtind, sex, age, yr) = length_hat(id_pop, sex, age, yr);
410 // The cohort that CROSSED the anchor during the year -- Jan-1 age below age_L1,
411 // mid-year age above it -- is read off the growth curve from the anchor, not
412 // advanced from its ramp length. `last_linear` is identically `l1` here, so the
413 // body is linf + (l1 - linf) * exp(-kappa * (current_age - age_L1)). The test
414 // is the JAN-1 age: `current_age` carries fracyr and the first branch took it.
415 }else if(age + Type(minage(sp)) < age_L1){ // Linear + growth curve mixed
416 last_linear = Lmin_sp + b_len * age_L1;
417 length_hat(wtind, sex, age, yr) = last_linear + (last_linear - linf) * (exp(-kappa * (current_age - age_L1)) - 1.0);
418 }else { // Growth curve
419 length_hat(wtind, sex, age, yr) = length_hat(id_pop, sex, age, yr) + (length_hat(id_pop, sex, age, yr) - linf) * (exp(-kappa * fracyr) - 1.0); // Add fracyr growth
420 }
421 break;
422
423 case 2: // Richards
424
425 // Slope from Lmin to L1
426 b_len = (l1 - Lmin_sp) / age_L1_safe;
427
428 // Same branch order as the VBGF case above, with the Richards curve, so the
429 // plus group is treated identically whichever growth family a species uses.
430 // Linear ramp below the anchor age
431 if((current_age) <= age_L1){
432 length_hat(wtind, sex, age, yr) = Lmin_sp + b_len * (current_age);
433 // Plus group PINNED at its Jan-1 length, ordered before the anchor test for the
434 // reason given in the VBGF branch above.
435 }else if(age + 1.0 == nages(sp) && growth_plus_length(sp) == 1) { // Pinned at Jan-1
436 length_hat(wtind, sex, age, yr) = length_hat(id_pop, sex, age, yr);
437 // As in the VBGF branch, but read off the Richards curve: `last_linear` is
438 // identically `l1` here, so the body is
439 // [linf^m + (l1^m - linf^m) * exp(-kappa * (current_age - age_L1))]^(1/m).
440 }else if(age + Type(minage(sp)) < age_L1){ // Linear + growth curve mixed
441 last_linear = Lmin_sp + b_len * age_L1;
442 length_hat(wtind, sex, age, yr) = pow(pow(last_linear, m) + (pow(last_linear, m) - pow(linf, m)) * (exp(-kappa * (current_age - age_L1)) - 1.0), 1 / m);
443 } else {
444 length_hat(wtind, sex, age, yr) = pow(pow(length_hat(id_pop, sex, age, yr), m) + (pow(length_hat(id_pop, sex, age, yr), m) - pow(linf, m)) * (exp(-kappa * fracyr) - 1.0), 1 / m); // Add fracyr growth
445 }
446 break;
447
448 case 3: // Non-parametric (Free parameters)
449 error("Non-parametric growth not yet implemented");
450 break;
451
452 default:
453 error("Invalid 'growth_model");
454 } // Growth_model switch
455
456 // 2. SD of length-at-age, then age-length key and weight-at-age ---
457 if(growth_model(sp) < 3) {
458 Type len = length_hat(wtind, sex, age, yr);
459 Type sd = length_sd_at_age(current_age, age_L1, age == (nages(sp) - 1),
460 growth_sd_style(sp), growth_sd_form(sp), l1, linf, len,
461 growth_log_sd(sp, sex, 0), growth_log_sd(sp, sex, 1));
462 fill_age_length_key(wtind, sp, sex, age, yr, len, sd, nlengths_pop,
463 lengths_pop, weight_length_pars,
464 mat_len_use, mat_len_pars, growth_matrix, weight_hat, mat_weight_hat);
465 }
466 } // age
467 } // yr
468 } // sex
469}
470
471
472/**
473 * @brief Population, SSB and fleet weight-at-age (kg) for every species and fleet.
474 *
475 * Empirical weight-at-age (`growth_model == 0`) is read straight from `weight_obs`, each
476 * projection year carrying the last hindcast year forward. Under estimated growth
477 * (`growth_model > 0`) population weight comes from estimate_growth() at Jan-1, and SSB
478 * and fleet weight from estimate_growth_within_yr() at the spawning month and at each
479 * fleet's own month. Arguments not listed below pass through to those two, except n_flt,
480 * which this function's own fleet loop consumes.
481 *
482 * @param weight_hat [ref] weight-at-age (wt_index, sex, age, year), kg
483 * @param length_hat [ref] mean length-at-age (cm)
484 * @param growth_matrix [ref] age-length key on the population length bins
485 * @param mat_weight_hat [ref] mature weight-at-age (kg), maturity-at-length species only
486 * @param weight_obs Empirical weight-at-age input (wt_index, sex, age, year), kg
487 * @param growth_model Per species, 0 = empirical, 1 = von Bertalanffy, 2 = Richards
488 * @param nyrs Years, hindcast plus projection.
489 * @param nyrs_hind Years in the hindcast.
490 * @param flt_spp Species index of each fleet
491 * @param flt_month Fleet observation month (0 = not specified); flt_month/12 of a year
492 * @param pop_wt_index Weight-at-age input index for population biomass
493 * @param ssb_wt_index Weight-at-age input index for spawning-stock biomass
494 * @param flt_wt_index Weight-at-age input index per fleet
495 * @param spawn_month Spawning month per species; spawn_month/12 of a year (0 = Jan-1)
496 */
497template <class Type>
499 array<Type> &weight_hat, // Modified by reference
500 array<Type> &length_hat, // Modified by reference
501 array<Type> &growth_matrix,// Modified by reference
502 array<Type> &mat_weight_hat,// Modified by reference; maturity-at-length species only
503 array<Type>& weight_obs,
504 const vector<int>& growth_model,
505 const vector<int>& growth_sd_style,
506 const vector<int>& growth_sd_form,
507 const vector<int>& growth_plus_length,
508 const vector<Type>& plus_group_decay,
509 const int& nspp,
510 const int& nyrs,
511 const int& nyrs_hind,
512 const int& n_flt,
513 const vector<int>& flt_spp,
514 vector<Type> flt_month,
515 const vector<int>& nsex,
516 const vector<int>& minage,
517 const vector<Type>& growth_age_L1,
518 const vector<int>& nages,
519 const vector<int>& nlengths,
520 const vector<int>& pop_wt_index,
521 const vector<int>& ssb_wt_index,
522 const vector<int>& flt_wt_index,
523 vector<Type> spawn_month,
524 matrix<Type>& lengths,
525 const vector<int>& nlengths_pop,
526 matrix<Type>& lengths_pop,
527 array<Type>& growth_parameters,
528 array<Type>& growth_log_sd,
529 matrix<Type> weight_length_pars,
530 const vector<int>& mat_len_use,
531 matrix<Type>& mat_len_pars,
532 array<Type>& log_M1
533) {
534 int yr_ind;
535 int wt_idx_pop;
536 int wt_idx_ssb;
537 int wt_idx_flt;
538
539 // 1. POPULATION WEIGHT-AT-AGE
540 for (int sp = 0; sp < nspp; sp++) {
541
542 wt_idx_pop = 2 * sp;
543 wt_idx_ssb = 2 * sp + 1;
544
545 // -- 1.1. Empirical weight-at-age
546 if (growth_model(sp) == 0) {
547 for (int sex = 0; sex < nsex(sp); sex++) {
548 for (int age = 0; age < nages(sp); age++) {
549 for (int yr = 0; yr < nyrs; yr++) {
550
551 // Projection years reuse the last hindcast year's empirical weight-at-age.
552 yr_ind = (yr < nyrs_hind) ? yr : (nyrs_hind - 1);
553
554 // Biomass weight
555 weight_hat(wt_idx_pop, sex, age, yr) = weight_obs(pop_wt_index(sp), sex, age, yr_ind);
556
557 // SSB weight
558 weight_hat(wt_idx_ssb, sex, age, yr) = weight_obs(ssb_wt_index(sp), sex, age, yr_ind);
559 }
560 }
561 }
562 }
563
564 // -- 1.2. Estimated growth
565 if (growth_model(sp) > 0) {
566 // Biomass weight (beginning of year / month 0)
568 wt_idx_pop,
569 sp,
570 nspp,
571 nyrs,
572 nsex,
573 nages,
574 nlengths,
575 minage,
576 growth_age_L1,
577 growth_model,
578 growth_sd_style,
579 growth_sd_form,
580 growth_plus_length,
581 plus_group_decay,
582 lengths,
583 nlengths_pop,
584 lengths_pop,
585 growth_parameters,
586 growth_log_sd,
587 weight_length_pars,
588 mat_len_use,
589 mat_len_pars,
590 log_M1,
591 length_hat,
592 growth_matrix,
593 weight_hat,
594 mat_weight_hat
595 );
596
597 // SSB weight (at month of spawning)
599 wt_idx_ssb,
600 wt_idx_pop,
601 sp,
602 spawn_month(sp) / Type(12.0),
603 nspp,
604 nyrs,
605 nsex,
606 nages,
607 nlengths,
608 minage,
609 growth_age_L1,
610 growth_model,
611 growth_sd_style,
612 growth_sd_form,
613 growth_plus_length,
614 lengths,
615 nlengths_pop,
616 lengths_pop,
617 growth_parameters,
618 growth_log_sd,
619 weight_length_pars,
620 mat_len_use,
621 mat_len_pars,
622 length_hat,
623 growth_matrix,
624 weight_hat,
625 mat_weight_hat
626 );
627 }
628 }
629
630 // 2. FLEET WEIGHT-AT-AGE
631 for (int flt = 0; flt < n_flt; flt++) {
632 int sp = flt_spp(flt);
633 Type mo = flt_month(flt);
634 wt_idx_pop = 2 * sp;
635 wt_idx_flt = nspp * 2 + flt;
636
637 // -- 2.1. Empirical weight-at-age
638 if (growth_model(sp) == 0) {
639 for (int sex = 0; sex < nsex(sp); sex++) {
640 for (int age = 0; age < nages(sp); age++) {
641 for (int yr = 0; yr < nyrs; yr++) {
642
643 yr_ind = (yr < nyrs_hind) ? yr : (nyrs_hind - 1);
644 weight_hat(wt_idx_flt, sex, age, yr) = weight_obs(flt_wt_index(flt), sex, age, yr_ind);
645 }
646 }
647 }
648 }
649
650 // -- 2.2. Estimated growth
651 if (growth_model(sp) > 0) {
652
654 wt_idx_flt,
655 wt_idx_pop,
656 sp,
657 mo / Type(12.0),
658 nspp,
659 nyrs,
660 nsex,
661 nages,
662 nlengths,
663 minage,
664 growth_age_L1,
665 growth_model,
666 growth_sd_style,
667 growth_sd_form,
668 growth_plus_length,
669 lengths,
670 nlengths_pop,
671 lengths_pop,
672 growth_parameters,
673 growth_log_sd,
674 weight_length_pars,
675 mat_len_use,
676 mat_len_pars,
677 length_hat,
678 growth_matrix,
679 weight_hat,
680 mat_weight_hat
681 );
682 }
683 }
684}
685
686
687
688#endif
689
Type length_sd_at_age(Type current_age, Type age_L1, bool plus_group, int sd_style, int sd_form, Type l1, Type linf, Type len, Type log_sd0, Type log_sd1)
SD of length-at-age (cm) for one age, year and sex.
Definition growth.hpp:14
void calculate_weight(array< Type > &weight_hat, array< Type > &length_hat, array< Type > &growth_matrix, array< Type > &mat_weight_hat, array< Type > &weight_obs, const vector< int > &growth_model, const vector< int > &growth_sd_style, const vector< int > &growth_sd_form, const vector< int > &growth_plus_length, const vector< Type > &plus_group_decay, const int &nspp, const int &nyrs, const int &nyrs_hind, const int &n_flt, const vector< int > &flt_spp, vector< Type > flt_month, const vector< int > &nsex, const vector< int > &minage, const vector< Type > &growth_age_L1, const vector< int > &nages, const vector< int > &nlengths, const vector< int > &pop_wt_index, const vector< int > &ssb_wt_index, const vector< int > &flt_wt_index, vector< Type > spawn_month, matrix< Type > &lengths, const vector< int > &nlengths_pop, matrix< Type > &lengths_pop, array< Type > &growth_parameters, array< Type > &growth_log_sd, matrix< Type > weight_length_pars, const vector< int > &mat_len_use, matrix< Type > &mat_len_pars, array< Type > &log_M1)
Population, SSB and fleet weight-at-age (kg) for every species and fleet.
Definition growth.hpp:498
void estimate_growth(int wtind, int sp, int nspp, int nyrs, const vector< int > &nsex, const vector< int > &nages, const vector< int > &nlengths, const vector< int > &minage, const vector< Type > &growth_age_L1, const vector< int > &growth_model, const vector< int > &growth_sd_style, const vector< int > &growth_sd_form, const vector< int > &growth_plus_length, const vector< Type > &plus_group_decay, matrix< Type > &lengths, const vector< int > &nlengths_pop, matrix< Type > &lengths_pop, array< Type > &growth_parameters, array< Type > &growth_log_sd, matrix< Type > &weight_length_pars, const vector< int > &mat_len_use, matrix< Type > &mat_len_pars, array< Type > &log_M1, array< Type > &length_hat, array< Type > &growth_matrix, array< Type > &weight_hat, array< Type > &mat_weight_hat)
Jan-1 (month 0) mean length, age-length key and weight-at-age for one species.
Definition growth.hpp:129
void fill_age_length_key(int wtind, int sp, int sex, int age, int yr, Type mu, Type sd, const vector< int > &nlengths_pop, matrix< Type > &lengths_pop, matrix< Type > &weight_length_pars, const vector< int > &mat_len_use, matrix< Type > &mat_len_pars, array< Type > &growth_matrix, array< Type > &weight_hat, array< Type > &mat_weight_hat)
Age-length key, weight-at-age and mature weight-at-age for one cell.
Definition growth.hpp:45
void estimate_growth_within_yr(int wtind, int id_pop, int sp, Type fracyr, int nspp, int nyrs, const vector< int > &nsex, const vector< int > &nages, const vector< int > &nlengths, const vector< int > &minage, const vector< Type > &growth_age_L1, const vector< int > &growth_model, const vector< int > &growth_sd_style, const vector< int > &growth_sd_form, const vector< int > &growth_plus_length, matrix< Type > &lengths, const vector< int > &nlengths_pop, matrix< Type > &lengths_pop, array< Type > &growth_parameters, array< Type > &growth_log_sd, matrix< Type > &weight_length_pars, const vector< int > &mat_len_use, matrix< Type > &mat_len_pars, array< Type > &length_hat, array< Type > &growth_matrix, array< Type > &weight_hat, array< Type > &mat_weight_hat)
Mean length-at-age, age-length key and weight-at-age fracyr into the year.
Definition growth.hpp:338