FIMS  v0.11.0
Loading...
Searching...
No Matches
growth_model.hpp
Go to the documentation of this file.
1
8#ifndef POPULATION_DYNAMICS_GROWTH_MODEL_HPP
9#define POPULATION_DYNAMICS_GROWTH_MODEL_HPP
10
11#include <cstddef>
12#include <stdexcept>
13
14#include "growth_model_base.hpp"
15#include "growth_products.hpp"
17#include "../../common/def.hpp"
18
19namespace fims_popdy {
20
30template <typename Type>
31class GrowthModel : public GrowthModelBase<Type> {
32 public:
39 GrowthModel(std::size_t n_years, std::size_t n_ages, std::size_t n_sexes = 1)
40 : n_years_(n_years),
41 n_ages_(n_ages),
42 n_sexes_(n_sexes),
43 products_(n_years, n_ages, n_sexes) {}
44
46 void SetVonBertalanffySchnuteParameters(Type mean_length_young,
47 Type mean_length_old,
48 Type growth_coefficient,
49 Type reference_age_for_length_young,
50 Type reference_age_for_length_old) {
51 vb_.mean_length_young = mean_length_young;
52 vb_.mean_length_old = mean_length_old;
53 vb_.growth_coefficient = growth_coefficient;
54 vb_.reference_age_for_length_young = reference_age_for_length_young;
55 vb_.reference_age_for_length_old = reference_age_for_length_old;
56 needs_update_ = true;
57 }
58
60 void SetLengthWeightParameters(Type length_weight_a, Type length_weight_b) {
61 vb_.length_weight_a = length_weight_a;
62 vb_.length_weight_b = length_weight_b;
63 needs_update_ = true;
64 }
65
68 void SetLengthSdParams(Type length_at_age_sd_at_reference_age_young,
69 Type length_at_age_sd_at_reference_age_old) {
70 length_at_age_sd_at_reference_age_young_ =
71 length_at_age_sd_at_reference_age_young;
72 length_at_age_sd_at_reference_age_old_ =
73 length_at_age_sd_at_reference_age_old;
74 needs_update_ = true;
75 }
76
86 Type mean_length_young_variance,
87 Type mean_length_young_mean_length_old_covariance,
88 Type mean_length_young_growth_coefficient_covariance,
89 Type mean_length_old_variance,
90 Type mean_length_old_growth_coefficient_covariance,
91 Type growth_coefficient_variance) {
92 ValidateGrowthParameterCovariance(
93 mean_length_young_variance,
94 mean_length_young_mean_length_old_covariance,
95 mean_length_young_growth_coefficient_covariance,
96 mean_length_old_variance, mean_length_old_growth_coefficient_covariance,
97 growth_coefficient_variance);
98
99 mean_length_young_variance_ = mean_length_young_variance;
100 mean_length_young_mean_length_old_covariance_ =
101 mean_length_young_mean_length_old_covariance;
102 mean_length_young_growth_coefficient_covariance_ =
103 mean_length_young_growth_coefficient_covariance;
104 mean_length_old_variance_ = mean_length_old_variance;
105 mean_length_old_growth_coefficient_covariance_ =
106 mean_length_old_growth_coefficient_covariance;
107 growth_coefficient_variance_ = growth_coefficient_variance;
108 use_delta_method_variability_ = true;
109 needs_update_ = true;
110 }
111
115 mean_length_young_variance_ = static_cast<Type>(0.0);
116 mean_length_young_mean_length_old_covariance_ = static_cast<Type>(0.0);
117 mean_length_young_growth_coefficient_covariance_ = static_cast<Type>(0.0);
118 mean_length_old_variance_ = static_cast<Type>(0.0);
119 mean_length_old_growth_coefficient_covariance_ = static_cast<Type>(0.0);
120 growth_coefficient_variance_ = static_cast<Type>(0.0);
121 use_delta_method_variability_ = false;
122 needs_update_ = true;
123 }
124
126 void Prepare() override {
127 if (!needs_update_) return;
128
129 if (n_ages_ == 0) {
130 throw std::runtime_error(
131 "VonBertalanffySchnuteGrowth requires n_ages > 0");
132 }
133 if (vb_.reference_age_for_length_old <=
134 vb_.reference_age_for_length_young) {
135 throw std::runtime_error(
136 "VonBertalanffySchnuteGrowth reference_age_for_length_old must be > "
137 "reference_age_for_length_young");
138 }
139
140 Type laa_min = Type(0.0);
141 Type slope = Type(0.0);
142
143 if (!use_delta_method_variability_) {
144 laa_min = vb_.length_at_age(vb_.reference_age_for_length_young);
145 const Type laa_max = vb_.length_at_age(vb_.reference_age_for_length_old);
146 const Type laa_delta_safe = fims_math::ad_max(
147 fims_math::ad_fabs(laa_max - laa_min), static_cast<Type>(1e-8));
148 slope = (n_ages_ > 1) ? (length_at_age_sd_at_reference_age_old_ -
149 length_at_age_sd_at_reference_age_young_) /
150 laa_delta_safe
151 : Type(0.0);
152 }
153
154 // Fill mean length-at-age, sd, and mean weight-at-age.
155 for (std::size_t y = 0; y < n_years_; ++y) {
156 for (std::size_t a = 0; a < n_ages_; ++a) {
157 for (std::size_t s = 0; s < n_sexes_; ++s) {
158 const Type age = static_cast<Type>(a) + age_offset_;
159
160 // log-scale params live upstream; laa here is natural scale
161 const Type laa = vb_.length_at_age(age);
162 const Type sd_laa = ComputeLengthSdAtAge(age, laa, laa_min, slope);
163 const Type waa = vb_.weight_at_age(age);
164
165 products_.MeanLAA(y, a, s) = laa;
166 products_.SdLAA(y, a, s) = sd_laa;
167 products_.MeanWAA(y, a, s) = waa;
168 }
169 }
170 }
171
172 needs_update_ = false;
173 }
174
175 const GrowthProducts<Type>& GetProducts() const override { return products_; }
176
177 private:
181 void ValidateGrowthParameterCovariance(
182 Type mean_length_young_variance,
183 Type mean_length_young_mean_length_old_covariance,
184 Type mean_length_young_growth_coefficient_covariance,
185 Type mean_length_old_variance,
186 Type mean_length_old_growth_coefficient_covariance,
187 Type growth_coefficient_variance) const {
188 if (mean_length_young_variance < Type(0.0) ||
189 mean_length_old_variance < Type(0.0) ||
190 growth_coefficient_variance < Type(0.0)) {
191 throw std::runtime_error("Growth parameter variances must be >= 0");
192 }
193
194 if (mean_length_young_mean_length_old_covariance *
195 mean_length_young_mean_length_old_covariance >
196 mean_length_young_variance * mean_length_old_variance) {
197 throw std::runtime_error(
198 "Growth covariance between mean_length_young and "
199 "mean_length_old is inconsistent with the supplied variances");
200 }
201
202 if (mean_length_young_growth_coefficient_covariance *
203 mean_length_young_growth_coefficient_covariance >
204 mean_length_young_variance * growth_coefficient_variance) {
205 throw std::runtime_error(
206 "Growth covariance between mean_length_young and "
207 "growth_coefficient is inconsistent with the supplied variances");
208 }
209
210 if (mean_length_old_growth_coefficient_covariance *
211 mean_length_old_growth_coefficient_covariance >
212 mean_length_old_variance * growth_coefficient_variance) {
213 throw std::runtime_error(
214 "Growth covariance between mean_length_old and "
215 "growth_coefficient is inconsistent with the supplied variances");
216 }
217
218 const Type determinant =
219 mean_length_young_variance *
220 (mean_length_old_variance * growth_coefficient_variance -
221 mean_length_old_growth_coefficient_covariance *
222 mean_length_old_growth_coefficient_covariance) -
223 mean_length_young_mean_length_old_covariance *
224 (mean_length_young_mean_length_old_covariance *
225 growth_coefficient_variance -
226 mean_length_young_growth_coefficient_covariance *
227 mean_length_old_growth_coefficient_covariance) +
228 mean_length_young_growth_coefficient_covariance *
229 (mean_length_young_mean_length_old_covariance *
230 mean_length_old_growth_coefficient_covariance -
231 mean_length_young_growth_coefficient_covariance *
232 mean_length_old_variance);
233
234 if (determinant < Type(0.0)) {
235 throw std::runtime_error(
236 "Growth parameter covariance matrix must be positive "
237 "semi-definite");
238 }
239 }
240
243 Type ComputeLengthSdAtAge(const Type& age, const Type& laa,
244 const Type& laa_min, const Type& slope) const {
245 if (use_delta_method_variability_) {
246 const Type log_var = ComputeLogLengthVarianceAtAge(age);
247 const Type log_var_safe =
248 fims_math::ad_max(log_var, static_cast<Type>(0.0));
249 const Type sd_laa = laa * fims_math::sqrt(log_var_safe);
250 return fims_math::ad_max(sd_laa, static_cast<Type>(1e-8));
251 }
252
253 const Type sd_laa =
254 (n_ages_ > 1)
255 ? length_at_age_sd_at_reference_age_young_ + slope * (laa - laa_min)
256 : length_at_age_sd_at_reference_age_young_;
257
258 return fims_math::ad_max(sd_laa, static_cast<Type>(1e-8));
259 }
260
263 Type ComputeLogLengthVarianceAtAge(const Type& age) const {
264 Type d_log_laa_d_log_length_young = Type(0.0);
265 Type d_log_laa_d_log_length_old = Type(0.0);
266 Type d_log_laa_d_log_k = Type(0.0);
267
268 vb_.log_length_at_age_logscale_gradient(age, d_log_laa_d_log_length_young,
269 d_log_laa_d_log_length_old,
270 d_log_laa_d_log_k);
271
272 return d_log_laa_d_log_length_young * d_log_laa_d_log_length_young *
273 mean_length_young_variance_ +
274 Type(2.0) * d_log_laa_d_log_length_young *
275 d_log_laa_d_log_length_old *
276 mean_length_young_mean_length_old_covariance_ +
277 Type(2.0) * d_log_laa_d_log_length_young * d_log_laa_d_log_k *
278 mean_length_young_growth_coefficient_covariance_ +
279 d_log_laa_d_log_length_old * d_log_laa_d_log_length_old *
280 mean_length_old_variance_ +
281 Type(2.0) * d_log_laa_d_log_length_old * d_log_laa_d_log_k *
282 mean_length_old_growth_coefficient_covariance_ +
283 d_log_laa_d_log_k * d_log_laa_d_log_k * growth_coefficient_variance_;
284 }
285
286 std::size_t n_years_;
287 std::size_t n_ages_;
288 std::size_t n_sexes_;
289
290 GrowthProducts<Type> products_;
291
292 // Phase 1 functor
293 VonBertalanffySchnuteGrowth<Type> vb_;
294
295 // Caching state
296 bool needs_update_ = true;
297 Type length_at_age_sd_at_reference_age_young_ = static_cast<Type>(3.0);
298 Type length_at_age_sd_at_reference_age_old_ = static_cast<Type>(7.0);
299 bool use_delta_method_variability_ = false;
300 Type mean_length_young_variance_ = static_cast<Type>(0.0);
301 Type mean_length_young_mean_length_old_covariance_ = static_cast<Type>(0.0);
302 Type mean_length_young_growth_coefficient_covariance_ =
303 static_cast<Type>(0.0);
304 Type mean_length_old_variance_ = static_cast<Type>(0.0);
305 Type mean_length_old_growth_coefficient_covariance_ = static_cast<Type>(0.0);
306 Type growth_coefficient_variance_ = static_cast<Type>(0.0);
307 Type age_offset_ = static_cast<Type>(0.0);
308
309 public:
311 void SetAgeOffset(Type offset) {
312 age_offset_ = offset;
313 needs_update_ = true;
314 }
315};
316
317} // namespace fims_popdy
318
319#endif /* POPULATION_DYNAMICS_GROWTH_MODEL_HPP */
Growth module boundary (product-oriented).
Definition growth_model_base.hpp:24
void SetLengthSdParams(Type length_at_age_sd_at_reference_age_young, Type length_at_age_sd_at_reference_age_old)
Definition growth_model.hpp:68
GrowthModel(std::size_t n_years, std::size_t n_ages, std::size_t n_sexes=1)
Construct a growth model with fixed dimensions.
Definition growth_model.hpp:39
void Prepare() override
Compute and cache growth products.
Definition growth_model.hpp:126
void ClearGrowthParameterCovariance()
Definition growth_model.hpp:114
void SetLengthWeightParameters(Type length_weight_a, Type length_weight_b)
fixed length-weight params (phase 1)
Definition growth_model.hpp:60
const GrowthProducts< Type > & GetProducts() const override
Read-only access to cached growth products.
Definition growth_model.hpp:175
void SetGrowthParameterCovariance(Type mean_length_young_variance, Type mean_length_young_mean_length_old_covariance, Type mean_length_young_growth_coefficient_covariance, Type mean_length_old_variance, Type mean_length_old_growth_coefficient_covariance, Type growth_coefficient_variance)
Definition growth_model.hpp:85
void SetVonBertalanffySchnuteParameters(Type mean_length_young, Type mean_length_old, Type growth_coefficient, Type reference_age_for_length_young, Type reference_age_for_length_old)
Set fixed VonBertalanffySchnute parameters (explicit reference ages).
Definition growth_model.hpp:46
void SetAgeOffset(Type offset)
Set an age offset if population ages do not start at zero.
Definition growth_model.hpp:311
Platform macros and the core FIMS logging system.
const Type ad_max(const Type &a, const Type &b, Type C=1e-5)
Definition fims_math.hpp:380
const Type ad_fabs(const Type &x, Type C=1e-5)
Definition fims_math.hpp:333
Declares the GrowthModelBase interface. This is the growth module boundary that downstream code consu...
Declares the GrowthProducts struct holding growth "products" that downstream population dynamics code...
The population dynamics of FIMS.
Definition catch_at_age.hpp:45
Growth "products" in a consistent (year, age, sex) space.
Definition growth_products.hpp:26
Defines the VonBertalanffySchnuteGrowth class, which inherits from the GrowthBase class.