78class VonBertalanffySchnuteGrowthModelAdapter
79 :
public GrowthDerivedObservationBase<Type> {
81 VonBertalanffySchnuteGrowthModelAdapter()
82 : GrowthDerivedObservationBase<Type>() {}
88 kEstimatedReferenceLengths = 0,
89 kConstantLengthYoungEstimatedLengthOld,
90 kEstimatedLengthYoungBelowConstantLengthOld,
98 length_reference_parameterization_ =
99 LengthReferenceParameterization::kEstimatedReferenceLengths;
100 growth_products_prepared_ =
false;
110 Type constant_mean_length_young) {
111 length_reference_parameterization_ =
112 LengthReferenceParameterization::kConstantLengthYoungEstimatedLengthOld;
113 constant_mean_length_young_ = constant_mean_length_young;
114 growth_products_prepared_ =
false;
124 Type constant_mean_length_old) {
125 length_reference_parameterization_ = LengthReferenceParameterization::
126 kEstimatedLengthYoungBelowConstantLengthOld;
127 constant_mean_length_old_ = constant_mean_length_old;
128 growth_products_prepared_ =
false;
140 Type constant_mean_length_old) {
141 length_reference_parameterization_ =
142 LengthReferenceParameterization::kBothConstant;
143 constant_mean_length_young_ = constant_mean_length_young;
144 constant_mean_length_old_ = constant_mean_length_old;
145 growth_products_prepared_ =
false;
154 use_param_vectors_ =
true;
155 vb_params_set_ =
true;
156 growth_products_prepared_ =
false;
157 return mean_length_young_vector_;
165 use_param_vectors_ =
true;
166 vb_params_set_ =
true;
167 growth_products_prepared_ =
false;
168 return mean_length_old_vector_;
177 use_param_vectors_ =
true;
178 vb_params_set_ =
true;
179 growth_products_prepared_ =
false;
180 return growth_coefficient_vector_;
188 use_param_vectors_ =
true;
189 vb_params_set_ =
true;
190 growth_products_prepared_ =
false;
191 return reference_age_for_length_young_vector_;
199 use_param_vectors_ =
true;
200 vb_params_set_ =
true;
201 growth_products_prepared_ =
false;
202 return reference_age_for_length_old_vector_;
210 use_param_vectors_ =
true;
211 lw_params_set_ =
true;
212 growth_products_prepared_ =
false;
213 return length_weight_a_vector_;
221 use_param_vectors_ =
true;
222 lw_params_set_ =
true;
223 growth_products_prepared_ =
false;
224 return length_weight_b_vector_;
232 use_param_vectors_ =
true;
233 growth_products_prepared_ =
false;
234 return length_at_age_sd_young_vector_;
242 use_param_vectors_ =
true;
243 growth_products_prepared_ =
false;
244 return length_at_age_sd_old_vector_;
252 use_param_vectors_ =
true;
253 growth_products_prepared_ =
false;
254 return log_sd_mean_length_young_vector_;
262 use_param_vectors_ =
true;
263 growth_products_prepared_ =
false;
264 return log_sd_mean_length_old_vector_;
272 use_param_vectors_ =
true;
273 growth_products_prepared_ =
false;
274 return log_sd_growth_coefficient_vector_;
283 use_param_vectors_ =
true;
284 growth_products_prepared_ =
false;
285 return mean_length_young_mean_length_old_logit_corr_vector_;
294 use_param_vectors_ =
true;
295 growth_products_prepared_ =
false;
296 return mean_length_young_growth_coefficient_logit_corr_vector_;
305 use_param_vectors_ =
true;
306 growth_products_prepared_ =
false;
307 return mean_length_old_growth_coefficient_logit_corr_vector_;
315 age_offset_ = min_age;
316 age_offset_set_ =
true;
317 growth_products_prepared_ =
false;
319 model_->SetAgeOffset(
static_cast<Type
>(age_offset_));
330 std::size_t n_sexes = 1)
override {
333 throw std::runtime_error(
334 "VonBertalanffySchnuteGrowthModelAdapter currently supports n_sexes "
340 growth_products_prepared_ =
false;
341 model_ = std::make_shared<GrowthModel<Type>>(n_years, n_ages, n_sexes);
343 if (age_offset_set_) {
344 model_->SetAgeOffset(
static_cast<Type
>(age_offset_));
355 virtual const Type
evaluate(
int year,
const double& a)
override {
357 throw std::runtime_error(
"Negative age not supported");
359 const double a_round = std::round(a);
360 const double tol = 1e-8;
361 if (std::fabs(a - a_round) > tol) {
362 throw std::runtime_error(
"Non-integer age not supported yet");
365 const Type ref_age_young = CurrentReferenceAgeForLengthYoung();
366 const Type ref_age_old = CurrentReferenceAgeForLengthOld();
367 if (ref_age_old <= ref_age_young) {
368 throw std::runtime_error(
369 "VonBertalanffySchnuteGrowth reference_age_for_length_old must be > "
370 "reference_age_for_length_young");
374 return EvaluateWithFunctor(year, a);
379 const auto& p = model_->GetProducts();
380 const double offset = age_offset_set_ ? age_offset_ : 0.0;
381 const double age_index_raw = a_round - offset;
382 const double age_index_round = std::round(age_index_raw);
383 if (std::fabs(age_index_raw - age_index_round) <= tol &&
384 age_index_round >= 0.0) {
385 const std::size_t age_index =
static_cast<std::size_t
>(age_index_round);
386 if (age_index < p.n_ages) {
387 const std::size_t year_index =
388 (year >= 0 &&
static_cast<std::size_t
>(year) < p.n_years)
389 ?
static_cast<std::size_t
>(year)
390 :
static_cast<std::size_t
>(0);
391 return p.MeanWAA(year_index, age_index, 0);
396 return EvaluateWithFunctor(year, a);
403 growth_products_prepared_ =
false;
406 throw std::runtime_error(
"Growth model not initialized; n_ages is 0");
408 Initialize(n_years_ == 0 ? 1 : n_years_, n_ages_,
409 n_sexes_ == 0 ? 1 : n_sexes_);
413 growth_products_prepared_ =
true;
421 if (!model_ || !growth_products_prepared_) {
424 return &(model_->GetProducts());
440 return CurrentLengthWeightA() *
441 fims_math::pow(length_safe, CurrentLengthWeightB());
463 bool use_param_vectors_ =
false;
465 LengthReferenceParameterization::kEstimatedReferenceLengths;
466 Type constant_mean_length_young_ = Type(0.0);
467 Type constant_mean_length_old_ = Type(0.0);
468 std::size_t n_years_ = 0;
469 std::size_t n_ages_ = 0;
470 std::size_t n_sexes_ = 1;
471 double age_offset_ = 0.0;
472 bool age_offset_set_ =
false;
473 bool vb_params_set_ =
false;
474 bool lw_params_set_ =
false;
475 bool growth_products_prepared_ =
false;
477 mutable std::shared_ptr<GrowthModel<Type>> model_;
479 Type EvaluateWithFunctor(
int year,
const double& a)
const {
492 void SyncParamsToModel()
const {
496 model_->SetVonBertalanffySchnuteParameters(
497 CurrentMeanLengthYoung(), CurrentMeanLengthOld(),
498 CurrentGrowthCoefficient(), CurrentReferenceAgeForLengthYoung(),
499 CurrentReferenceAgeForLengthOld());
500 model_->SetLengthWeightParameters(CurrentLengthWeightA(),
501 CurrentLengthWeightB());
503 if (HasInterpolationSdInputs()) {
504 model_->SetLengthSdParams(CurrentLengthAtAgeSdAtReferenceAge1(),
505 CurrentLengthAtAgeSdAtReferenceAge2());
508 if (HasStructuredDeltaMethodInputs()) {
509 model_->SetGrowthParameterCovariance(
510 CurrentMeanLengthYoungVariance(),
511 CurrentMeanLengthYoungLengthAtRefAgeOldCovariance(),
512 CurrentMeanLengthYoungKCovariance(), CurrentMeanLengthOldVariance(),
513 CurrentMeanLengthOldKCovariance(),
514 CurrentGrowthCoefficientVariance());
516 model_->ClearGrowthParameterCovariance();
520 Type CurrentMeanLengthYoungStorage()
const {
521 return fims_math::exp(mean_length_young_vector_[0]);
524 Type CurrentMeanLengthOldStorage()
const {
525 return fims_math::exp(mean_length_old_vector_[0]);
528 Type CurrentMeanLengthYoung()
const {
529 switch (length_reference_parameterization_) {
530 case LengthReferenceParameterization::kEstimatedReferenceLengths:
531 return CurrentMeanLengthYoungStorage();
533 case LengthReferenceParameterization::
534 kConstantLengthYoungEstimatedLengthOld:
535 return constant_mean_length_young_;
537 case LengthReferenceParameterization::
538 kEstimatedLengthYoungBelowConstantLengthOld:
540 constant_mean_length_old_,
541 mean_length_young_vector_[0]);
543 case LengthReferenceParameterization::kBothConstant:
544 return constant_mean_length_young_;
547 return CurrentMeanLengthYoungStorage();
550 Type CurrentMeanLengthOld()
const {
551 switch (length_reference_parameterization_) {
552 case LengthReferenceParameterization::kEstimatedReferenceLengths:
553 case LengthReferenceParameterization::
554 kConstantLengthYoungEstimatedLengthOld:
555 return CurrentMeanLengthOldStorage();
557 case LengthReferenceParameterization::
558 kEstimatedLengthYoungBelowConstantLengthOld:
559 return constant_mean_length_old_;
561 case LengthReferenceParameterization::kBothConstant:
562 return constant_mean_length_old_;
565 return CurrentMeanLengthOldStorage();
568 Type CurrentGrowthCoefficient()
const {
569 return fims_math::exp(growth_coefficient_vector_[0]);
571 Type CurrentReferenceAgeForLengthYoung()
const {
572 return reference_age_for_length_young_vector_[0];
574 Type CurrentReferenceAgeForLengthOld()
const {
575 return reference_age_for_length_old_vector_[0];
577 Type CurrentLengthWeightA()
const {
578 return fims_math::exp(length_weight_a_vector_[0]);
580 Type CurrentLengthWeightB()
const {
581 return fims_math::exp(length_weight_b_vector_[0]);
583 Type CurrentLengthAtAgeSdAtReferenceAge1()
const {
584 return fims_math::exp(length_at_age_sd_young_vector_[0]);
586 Type CurrentLengthAtAgeSdAtReferenceAge2()
const {
587 return fims_math::exp(length_at_age_sd_old_vector_[0]);
589 Type CurrentSdLengthAtRefAgeYoung()
const {
590 return fims_math::exp(log_sd_mean_length_young_vector_[0]);
593 Type CurrentSdLengthAtRefAgeOld()
const {
594 return fims_math::exp(log_sd_mean_length_old_vector_[0]);
597 Type CurrentSdGrowthCoefficient()
const {
598 return fims_math::exp(log_sd_growth_coefficient_vector_[0]);
601 Type CurrentCorrLengthAtRefAgeYoungLengthAtRefAgeOld()
const {
603 static_cast<Type
>(-1.0),
static_cast<Type
>(1.0),
604 mean_length_young_mean_length_old_logit_corr_vector_[0]);
607 Type CurrentCorrLengthAtRefAgeYoungK()
const {
609 static_cast<Type
>(-1.0),
static_cast<Type
>(1.0),
610 mean_length_young_growth_coefficient_logit_corr_vector_[0]);
613 Type CurrentCorrLengthAtRefAgeOldK()
const {
615 static_cast<Type
>(-1.0),
static_cast<Type
>(1.0),
616 mean_length_old_growth_coefficient_logit_corr_vector_[0]);
619 Type CurrentMeanLengthYoungVariance()
const {
620 const Type sd = CurrentSdLengthAtRefAgeYoung();
624 Type CurrentMeanLengthOldVariance()
const {
625 const Type sd = CurrentSdLengthAtRefAgeOld();
629 Type CurrentGrowthCoefficientVariance()
const {
630 const Type sd = CurrentSdGrowthCoefficient();
634 Type CurrentMeanLengthYoungLengthAtRefAgeOldCovariance()
const {
635 return CurrentCorrLengthAtRefAgeYoungLengthAtRefAgeOld() *
636 CurrentSdLengthAtRefAgeYoung() * CurrentSdLengthAtRefAgeOld();
639 Type CurrentMeanLengthYoungKCovariance()
const {
640 return CurrentCorrLengthAtRefAgeYoungK() * CurrentSdLengthAtRefAgeYoung() *
641 CurrentSdGrowthCoefficient();
644 Type CurrentMeanLengthOldKCovariance()
const {
645 return CurrentCorrLengthAtRefAgeOldK() * CurrentSdLengthAtRefAgeOld() *
646 CurrentSdGrowthCoefficient();
649 bool HasInterpolationSdInputs()
const {
650 return length_at_age_sd_young_vector_.size() > 0 ||
651 length_at_age_sd_old_vector_.size() > 0;
654 bool HasAnyStructuredDeltaMethodInput()
const {
655 return log_sd_mean_length_young_vector_.size() > 0 ||
656 log_sd_mean_length_old_vector_.size() > 0 ||
657 log_sd_growth_coefficient_vector_.size() > 0 ||
658 mean_length_young_mean_length_old_logit_corr_vector_.size() > 0 ||
659 mean_length_young_growth_coefficient_logit_corr_vector_.size() > 0 ||
660 mean_length_old_growth_coefficient_logit_corr_vector_.size() > 0;
663 bool HasStructuredDeltaMethodInputs()
const {
664 return log_sd_mean_length_young_vector_.size() > 0 &&
665 log_sd_mean_length_old_vector_.size() > 0 &&
666 log_sd_growth_coefficient_vector_.size() > 0 &&
667 mean_length_young_mean_length_old_logit_corr_vector_.size() > 0 &&
668 mean_length_young_growth_coefficient_logit_corr_vector_.size() > 0 &&
669 mean_length_old_growth_coefficient_logit_corr_vector_.size() > 0;
672 void EnsureParamsSet()
const {
673 if (!use_param_vectors_ || mean_length_young_vector_.size() < 1 ||
674 mean_length_old_vector_.size() < 1 ||
675 growth_coefficient_vector_.size() < 1 ||
676 reference_age_for_length_young_vector_.size() < 1 ||
677 reference_age_for_length_old_vector_.size() < 1 ||
678 length_weight_a_vector_.size() < 1 ||
679 length_weight_b_vector_.size() < 1) {
680 throw std::runtime_error(
681 "VonBertalanffySchnuteGrowth parameters not set");
684 if (mean_length_young_vector_.size() != 1 ||
685 mean_length_old_vector_.size() != 1 ||
686 growth_coefficient_vector_.size() != 1 ||
687 reference_age_for_length_young_vector_.size() != 1 ||
688 reference_age_for_length_old_vector_.size() != 1 ||
689 length_weight_a_vector_.size() != 1 ||
690 length_weight_b_vector_.size() != 1) {
691 throw std::runtime_error(
692 "VonBertalanffySchnuteGrowthModelAdapter currently supports a single "
693 "growth pattern; expected size 1 for von Bertalanffy--Schnute and "
694 "length-weight parameter vectors");
697 const bool has_sd = HasInterpolationSdInputs();
698 const bool has_any_structured_delta = HasAnyStructuredDeltaMethodInput();
699 const bool has_structured_delta = HasStructuredDeltaMethodInputs();
701 if (!has_sd && !has_any_structured_delta) {
702 throw std::runtime_error(
703 "VonBertalanffySchnuteGrowthModelAdapter requires either "
704 "both length_at_age_sd_young and length_at_age_sd_old, "
705 "or the structured delta-method growth variability inputs");
708 if (has_any_structured_delta && !has_structured_delta) {
709 throw std::runtime_error(
710 "VonBertalanffySchnuteGrowthModelAdapter requires all six structured "
711 "delta-method variability inputs when using that path");
714 if (has_sd && has_structured_delta) {
715 throw std::runtime_error(
716 "von Bertalanffy--Schnute growth adapter requires variability inputs "
717 "for exactly one supported path. Supply either the interpolation "
718 "inputs length_at_age_sd_young and length_at_age_sd_old or the full "
719 "delta-method variability inputs, but not both");
722 if (has_sd && (length_at_age_sd_young_vector_.size() != 1 ||
723 length_at_age_sd_old_vector_.size() != 1)) {
724 throw std::runtime_error(
725 "VonBertalanffySchnuteGrowthModelAdapter requires exactly one "
726 "length_at_age_sd_young value and one length_at_age_sd_old value");
729 if (has_structured_delta &&
730 (log_sd_mean_length_young_vector_.size() != 1 ||
731 log_sd_mean_length_old_vector_.size() != 1 ||
732 log_sd_growth_coefficient_vector_.size() != 1 ||
733 mean_length_young_mean_length_old_logit_corr_vector_.size() != 1 ||
734 mean_length_young_growth_coefficient_logit_corr_vector_.size() != 1 ||
735 mean_length_old_growth_coefficient_logit_corr_vector_.size() != 1)) {
736 throw std::runtime_error(
737 "VonBertalanffySchnuteGrowthModelAdapter currently supports a single "
738 "structured delta-method variability parameter set; expected "
739 "size 1 for each structured uncertainty input");