FIMS  v0.11.0
Loading...
Searching...
No Matches
rcpp_growth.hpp
Go to the documentation of this file.
1
9#ifndef FIMS_INTERFACE_RCPP_RCPP_OBJECTS_RCPP_GROWTH_HPP
10#define FIMS_INTERFACE_RCPP_RCPP_OBJECTS_RCPP_GROWTH_HPP
11
12#include <algorithm>
13#include <cmath>
14
15#include "common/fims_math.hpp"
19
25 public:
29 static uint32_t id_g;
33 uint32_t id;
39 static std::map<uint32_t, std::shared_ptr<GrowthInterfaceBase>> live_objects;
40
45 this->id = GrowthInterfaceBase::id_g++;
46 /* Create instance of map: key is id and value is pointer to
47 GrowthInterfaceBase */
48 // GrowthInterfaceBase::live_objects[this->id] =
49 // std::make_shared<GrowthInterfaceBase>(*this);
50 }
51
57 GrowthInterfaceBase(const GrowthInterfaceBase& other) : id(other.id) {}
58
63
67 virtual uint32_t get_id() = 0;
68
73 virtual double evaluate(double age) = 0;
74};
75
84class GrowthDerivedObservationInterfaceBase : public GrowthInterfaceBase {
85 public:
86 GrowthDerivedObservationInterfaceBase() : GrowthInterfaceBase() {}
87
93 const GrowthDerivedObservationInterfaceBase& other)
94 : GrowthInterfaceBase(other) {}
95
97
98 protected:
99 template <typename Type>
104 std::shared_ptr<fims_popdy::GrowthDerivedObservationBase<Type>>
106 std::shared_ptr<fims_info::Information<Type>> info =
108
110 info->growth_models.find(this->id);
111 if (it == info->growth_models.end()) {
112 FIMS_WARNING_LOG("Growth-derived observation model " +
113 fims::to_string(this->id) +
114 " not found in Information.");
115 return nullptr;
116 }
117
118 std::shared_ptr<fims_popdy::GrowthDerivedObservationBase<Type>>
119 growth_observation = std::dynamic_pointer_cast<
121 if (!growth_observation) {
122 FIMS_WARNING_LOG("Growth-derived observation type mismatch for id " +
123 fims::to_string(this->id));
124 return nullptr;
125 }
126
127 return growth_observation;
128 }
129
130 template <typename Type>
137 growth_observation) const {
138 std::shared_ptr<fims_info::Information<Type>> info =
140 info->growth_models[growth_observation->id] = growth_observation;
141 }
142};
143
150 public:
168 std::shared_ptr<std::map<int, std::map<double, double>>> ewaa;
172 bool initialized = false;
173
178 this->ewaa = std::make_shared<std::map<int, std::map<double, double>>>();
180 std::make_shared<EWAAGrowthInterface>(*this);
182 std::make_shared<EWAAGrowthInterface>(*this));
183 }
184
191 : GrowthInterfaceBase(other),
192 weights(other.weights),
193 ages(other.ages),
194 n_years(other.n_years),
195 ewaa(other.ewaa),
196 initialized(other.initialized) {}
197
202
207 virtual uint32_t get_id() { return this->id; }
208
216 inline std::map<int, std::map<double, double>> make_map(RealVector ages,
219 std::map<int, std::map<double, double>> mymap;
220 const size_t n_years_plus_one = static_cast<size_t>(n_years.get() + 1);
221
222 // Reject invalid year counts because map keys are expected to include
223 // at least one model year.
224 if (n_years.get() < 1) {
225 Rcpp::stop("EWAA Error:: n_years must be at least 1");
226 }
227
228 // Reject empty vectors because we need at least one age-weight pair.
229 if (weights.size() == 0 || ages.size() == 0) {
230 Rcpp::stop("EWAA Error:: ages and weights must have at least one value");
231 }
232
233 // Accept either:
234 // 1) one weight vector by age (shared across years), or
235 // 2) a full year-by-age matrix flattened as (n_years + 1) * n_ages.
236 if ((weights.size() != ages.size() * n_years_plus_one) &&
237 (weights.size() != ages.size())) {
238 Rcpp::stop(
239 "weights size does not match ages size or ages size times "
240 "(n_years + 1), where the plus one is for the beginning "
241 "of the year after the terminal year spawning-biomass "
242 "calculations. weights size: " +
243 std::to_string(weights.size()) +
244 " ages size: " + std::to_string(ages.size()) +
245 " n_years: " + std::to_string(n_years.get()));
246 } else if (weights.size() == ages.size()) {
247 // One age-specific vector was provided, so replicate the same
248 // weight-at-age values for every year key (0 through n_years).
249 for (size_t y = 0; y < n_years_plus_one; y++) {
250 for (size_t i = 0; i < ages.size(); i++) {
251 mymap[y][ages[i]] = weights[i];
252 }
253 }
254 } else if (weights.size() == ages.size() * n_years_plus_one) {
255 // A flattened year-by-age matrix was provided, so map each block of
256 // n_ages values to the corresponding year key (0 through n_years).
257 for (size_t y = 0; y < n_years_plus_one; y++) {
258 for (size_t i = 0; i < ages.size(); i++) {
259 mymap[y][ages[i]] = weights[y * ages.size() + i];
260 }
261 }
262 }
263 return mymap;
264 }
265
271 virtual double evaluate(double age) {
273
274 // Build the EWAA map once from R inputs the first time evaluate() is
275 // called.
276 if (initialized == false) {
277 EWAAGrowth.ewaa = make_map(this->ages, this->weights, this->n_years);
278 initialized = true;
279 } else {
280 // Prevent re-initializing this object with a second evaluate() call.
281 Rcpp::stop("this empirical weight at age object is already initialized");
282 }
283 return EWAAGrowth.evaluate(0, age);
284 }
285
293 virtual std::string to_json() {
294 std::stringstream ss;
295 ss << "{\n";
296 ss << " \"module_name\": \"Growth\",\n";
297 ss << " \"module_type\": \"EWAA\",\n";
298 ss << " \"module_id\":" << this->id << ",\n";
299 ss << " \"parameters\": [\n{\n";
300 ss << " \"name\": \"weight_at_age\",\n";
301 ss << " \"id\": null,\n";
302 ss << " \"type\": \"vector\",\n";
303 ss << " \"dimensionality\": {\n";
304 ss << " \"header\": [\"n_years+1\",\"n_ages\"],\n";
305 ss << " \"dimensions\": [" << this->n_years.get() + 1 << ","
306 << this->ages.size() << "]\n},\n";
307
308 ss << " \"values\": [\n";
309 for (size_t i = 0; i < weights.size() - 1; i++) {
310 ss << "{\n";
311 ss << "\"id\": null,\n";
312 ss << "\"value\": " << weights[i] << ",\n";
313 ss << "\"estimated_value\": " << weights[i] << ",\n";
314 ss << "\"estimation_type\": \"constant\"\n";
315 ss << "},\n";
316 }
317 ss << "{\n";
318 ss << "\"id\": null,\n";
319 ss << "\"value\": " << weights[weights.size() - 1] << ",\n";
320 ss << "\"estimated_value\": " << weights[weights.size() - 1] << ",\n";
321 ss << "\"estimation_type\": \"constant\"\n";
322 ss << "}\n]\n";
323 ss << "}\n]\n}\n";
324 return ss.str();
325 }
326
327#ifdef TMB_MODEL
328
329 template <typename Type>
330 bool add_to_fims_tmb_internal() {
331 std::shared_ptr<fims_info::Information<Type>> info =
333
334 std::shared_ptr<fims_popdy::EWAAGrowth<Type>> ewaa_growth =
335 std::make_shared<fims_popdy::EWAAGrowth<Type>>();
336
337 // set relative info
338 ewaa_growth->id = this->id;
339 ewaa_growth->ewaa =
340 make_map(this->ages, this->weights, this->n_years); // this->ewaa;
341 // add to Information
342 info->growth_models[ewaa_growth->id] = ewaa_growth;
343
344 return true;
345 }
346
351 virtual bool add_to_fims_tmb() {
352 this->add_to_fims_tmb_internal<TMB_FIMS_REAL_TYPE>();
353 this->add_to_fims_tmb_internal<TMBAD_FIMS_TYPE>();
354
355 return true;
356 }
357
358#endif
359};
360
368 : public GrowthDerivedObservationInterfaceBase {
369 public:
376 // clang-format off
381 // clang-format on
426
431 : GrowthDerivedObservationInterfaceBase() {
432 // Variability inputs are optional and mutually exclusive by path, so
433 // leave them absent until a caller explicitly supplies one path.
434 this->length_at_age_sd_young.resize(0);
435 this->length_at_age_sd_old.resize(0);
436 this->log_sd_mean_length_young.resize(0);
437 this->log_sd_mean_length_old.resize(0);
438 this->log_sd_growth_coefficient.resize(0);
439 this->mean_length_young_mean_length_old_logit_corr.resize(0);
440 this->mean_length_young_growth_coefficient_logit_corr.resize(0);
441 this->mean_length_old_growth_coefficient_logit_corr.resize(0);
442
443 // Register this interface instance in global registries so it can be
444 // discovered and linked by ID during model initialization.
446 std::make_shared<VonBertalanffySchnuteGrowthInterface>(*this);
448 std::make_shared<VonBertalanffySchnuteGrowthInterface>(*this));
449 }
450
477
479
480 // Return stable module ID used for linking this growth object to populations.
481 virtual uint32_t get_id() { return this->id; }
482
487 virtual void finalize() {
488 if (this->finalized) {
489 FIMS_WARNING_LOG("VonBertalanffySchnute Growth " +
490 fims::to_string(this->id) +
491 " has been finalized already.");
492 }
493
494 this->finalized = true;
495
496 std::shared_ptr<fims_popdy::GrowthDerivedObservationBase<double>>
497 growth_observation = this->GetGrowthObservationFromInfo<double>();
498 if (!growth_observation) {
499 return;
500 }
501
502 std::shared_ptr<fims_popdy::VonBertalanffySchnuteGrowthModelAdapter<double>>
503 vb = std::dynamic_pointer_cast<
505 growth_observation);
506 if (!vb) {
507 FIMS_WARNING_LOG("Growth model type mismatch for id " +
508 fims::to_string(this->id));
509 return;
510 }
511
512 auto set_final = [](VariableVector& pv, const fims::Vector<double>& src,
513 bool log_scale) {
514 for (size_t i = 0; i < pv.size(); i++) {
515 if (pv[i].estimation_type_m.get() == "constant") {
516 pv[i].final_value_m = pv[i].initial_value_m;
517 } else {
518 double v = src[i];
519 if (log_scale) {
520 v = fims_math::exp(v);
521 }
522 pv[i].final_value_m = v;
523 }
524 }
525 };
526
527 SetFinalLengthParameter(
528 this->mean_length_young,
529 FinalMeanLengthYoungFromWorkingScale(vb->MeanLengthYoungVector()));
530 SetFinalLengthParameter(
531 this->mean_length_old,
532 FinalMeanLengthOldFromWorkingScale(vb->MeanLengthYoungVector(),
533 vb->MeanLengthOldVector()));
534 set_final(this->growth_coefficient, vb->GrowthCoefficientVector(), true);
535 set_final(this->reference_age_for_length_young,
536 vb->ReferenceAgeForLengthYoungVector(), false);
537 set_final(this->reference_age_for_length_old,
538 vb->ReferenceAgeForLengthOldVector(), false);
539 set_final(this->length_weight_a, vb->LengthWeightAVector(), true);
540 set_final(this->length_weight_b, vb->LengthWeightBVector(), true);
541 set_final(this->length_at_age_sd_young, vb->LengthAtAgeSdYoungVector(),
542 true);
543 set_final(this->length_at_age_sd_old, vb->LengthAtAgeSdOldVector(), true);
544 set_final(this->log_sd_mean_length_young,
545 vb->LogSdLengthAtRefAgeYoungVector(), false);
546 set_final(this->log_sd_mean_length_old, vb->LogSdLengthAtRefAgeOldVector(),
547 false);
548 set_final(this->log_sd_growth_coefficient,
549 vb->LogSdGrowthCoefficientVector(), false);
550 set_final(this->mean_length_young_mean_length_old_logit_corr,
551 vb->LogitCorrLengthAtRefAgeYoungLengthAtRefAgeOldVector(), false);
552 set_final(this->mean_length_young_growth_coefficient_logit_corr,
553 vb->LogitCorrLengthAtRefAgeYoungKVector(), false);
554 set_final(this->mean_length_old_growth_coefficient_logit_corr,
555 vb->LogitCorrLengthAtRefAgeOldKVector(), false);
556 }
557
558 virtual double evaluate(double age) {
559 if (age < 0.0) {
560 Rcpp::stop("Negative age not supported");
561 }
562 if (this->n_ages.get() <= 0) {
563 Rcpp::stop("n_ages not set");
564 }
565 const double age_round = std::round(age);
566 const double tol = 1e-8;
567 if (std::fabs(age - age_round) > tol) {
568 Rcpp::stop("Non-integer age not supported yet");
569 }
570 ValidateVonBertalanffySchnuteGrowthInputs(false);
571
573
574 vb.mean_length_young = this->mean_length_young[0].initial_value_m;
575 vb.mean_length_old = this->mean_length_old[0].initial_value_m;
576 vb.growth_coefficient = this->growth_coefficient[0].initial_value_m;
578 this->reference_age_for_length_young[0].initial_value_m;
580 this->reference_age_for_length_old[0].initial_value_m;
581
582 vb.length_weight_a = this->length_weight_a[0].initial_value_m;
583 vb.length_weight_b = this->length_weight_b[0].initial_value_m;
584
585 return vb.evaluate(0, age);
586 }
587
588 private:
589 enum class LengthReferenceParameterization {
590 kEstimatedReferenceLengths = 0,
591 kConstantLengthYoungEstimatedLengthOld,
592 kEstimatedLengthYoungBelowConstantLengthOld,
593 kBothConstant
594 };
595
596 bool IsEstimated(VariableVector& pv) {
597 return pv.size() > 0 && pv[0].estimation_type_m.get() != "constant";
598 }
599
600 double InitialLengthAtRefAgeYoung() {
601 return this->mean_length_young[0].initial_value_m;
602 }
603
604 double InitialLengthAtRefAgeOld() {
605 return this->mean_length_old[0].initial_value_m;
606 }
607
608 LengthReferenceParameterization GetLengthReferenceParameterization() {
609 const bool estimate_length_young = IsEstimated(this->mean_length_young);
610 const bool estimate_length_old = IsEstimated(this->mean_length_old);
611
612 if (estimate_length_young && estimate_length_old) {
613 return LengthReferenceParameterization::kEstimatedReferenceLengths;
614 }
615 if (!estimate_length_young && estimate_length_old) {
616 return LengthReferenceParameterization::
617 kConstantLengthYoungEstimatedLengthOld;
618 }
619 if (estimate_length_young && !estimate_length_old) {
620 return LengthReferenceParameterization::
621 kEstimatedLengthYoungBelowConstantLengthOld;
622 }
623 return LengthReferenceParameterization::kBothConstant;
624 }
625
626 double FinalMeanLengthYoungFromWorkingScale(
627 const fims::Vector<double>& mean_length_young_src) {
628 switch (GetLengthReferenceParameterization()) {
629 case LengthReferenceParameterization::kEstimatedReferenceLengths:
630 return fims_math::exp(mean_length_young_src[0]);
631
632 case LengthReferenceParameterization::
633 kConstantLengthYoungEstimatedLengthOld:
634 return InitialLengthAtRefAgeYoung();
635
636 case LengthReferenceParameterization::
637 kEstimatedLengthYoungBelowConstantLengthOld:
638 return fims_math::inv_logit(0.0, InitialLengthAtRefAgeOld(),
639 mean_length_young_src[0]);
640
641 case LengthReferenceParameterization::kBothConstant:
642 return InitialLengthAtRefAgeYoung();
643 }
644
645 return InitialLengthAtRefAgeYoung();
646 }
647
648 double FinalMeanLengthOldFromWorkingScale(
649 const fims::Vector<double>& mean_length_young_src,
650 const fims::Vector<double>& mean_length_old_src) {
651 switch (GetLengthReferenceParameterization()) {
652 case LengthReferenceParameterization::kEstimatedReferenceLengths:
653 case LengthReferenceParameterization::
654 kConstantLengthYoungEstimatedLengthOld:
655 return fims_math::exp(mean_length_old_src[0]);
656
657 case LengthReferenceParameterization::
658 kEstimatedLengthYoungBelowConstantLengthOld:
659 return InitialLengthAtRefAgeOld();
660
661 case LengthReferenceParameterization::kBothConstant:
662 return InitialLengthAtRefAgeOld();
663 }
664
665 return InitialLengthAtRefAgeOld();
666 }
667
668 void SetFinalLengthParameter(VariableVector& pv, double final_value) const {
669 for (size_t i = 0; i < pv.size(); i++) {
670 if (pv[i].estimation_type_m.get() == "constant") {
671 pv[i].final_value_m = pv[i].initial_value_m;
672 } else {
673 pv[i].final_value_m = final_value;
674 }
675 }
676 }
677
678 template <typename Type>
679 void ConfigureLengthReferenceParameterization(
680 const std::shared_ptr<
681 fims_popdy::VonBertalanffySchnuteGrowthModelAdapter<Type>>& vb) {
682 switch (GetLengthReferenceParameterization()) {
683 case LengthReferenceParameterization::kEstimatedReferenceLengths:
684 vb->UseEstimatedReferenceMeanLengths();
685 break;
686
687 case LengthReferenceParameterization::
688 kConstantLengthYoungEstimatedLengthOld:
689 vb->UseConstantMeanLengthYoungWithEstimatedMeanLengthOld(
690 static_cast<Type>(InitialLengthAtRefAgeYoung()));
691 break;
692
693 case LengthReferenceParameterization::
694 kEstimatedLengthYoungBelowConstantLengthOld:
695 vb->UseEstimatedMeanLengthYoungBelowConstantMeanLengthOld(
696 static_cast<Type>(InitialLengthAtRefAgeOld()));
697 break;
698
699 case LengthReferenceParameterization::kBothConstant:
700 vb->UseConstantReferenceMeanLengths(
701 static_cast<Type>(InitialLengthAtRefAgeYoung()),
702 static_cast<Type>(InitialLengthAtRefAgeOld()));
703 break;
704 }
705 }
706
707 void ValidateVonBertalanffySchnuteGrowthInputs(bool require_variability) {
708 if (this->mean_length_young.size() < 1 ||
709 this->mean_length_old.size() < 1 ||
710 this->growth_coefficient.size() < 1 ||
711 this->reference_age_for_length_young.size() < 1 ||
712 this->reference_age_for_length_old.size() < 1 ||
713 this->length_weight_a.size() < 1 || this->length_weight_b.size() < 1) {
714 Rcpp::stop("VonBertalanffySchnuteGrowth parameters not set");
715 }
716
717 const bool has_sd = this->length_at_age_sd_young.size() > 0 ||
718 this->length_at_age_sd_old.size() > 0;
719 const bool has_any_structured_delta =
720 this->log_sd_mean_length_young.size() > 0 ||
721 this->log_sd_mean_length_old.size() > 0 ||
722 this->log_sd_growth_coefficient.size() > 0 ||
726 const bool has_structured_delta =
727 this->log_sd_mean_length_young.size() > 0 &&
728 this->log_sd_mean_length_old.size() > 0 &&
729 this->log_sd_growth_coefficient.size() > 0 &&
733
734 if (require_variability && !has_sd && !has_any_structured_delta) {
735 Rcpp::stop(
736 "VonBertalanffySchnuteGrowth requires either "
737 "both length_at_age_sd_young and length_at_age_sd_old, "
738 "or the structured delta-method growth variability inputs");
739 }
740
741 if (has_any_structured_delta && !has_structured_delta) {
742 Rcpp::stop(
743 "von Bertalanffy--Schnute growth requires all six structured "
744 "delta-method "
745 "variability inputs when using that path");
746 }
747
748 if (has_sd && has_structured_delta) {
749 Rcpp::stop(
750 "von Bertalanffy--Schnute growth requires variability inputs for "
751 "one supported path. Supply either the interpolation inputs "
752
753 "length_at_age_sd_young and length_at_age_sd_old or the full "
754 "delta-method variability inputs, but not both");
755 }
756
757 if (has_sd && (this->length_at_age_sd_young.size() != 1 ||
758 this->length_at_age_sd_old.size() != 1)) {
759 Rcpp::stop(
760 "Interpolation requires exactly one length_at_age_sd_young value "
761 "and one length_at_age_sd_old value");
762 }
763
764 if (has_structured_delta &&
765 (this->log_sd_mean_length_young.size() != 1 ||
766 this->log_sd_mean_length_old.size() != 1 ||
767 this->log_sd_growth_coefficient.size() != 1 ||
768 this->mean_length_young_mean_length_old_logit_corr.size() != 1 ||
769 this->mean_length_young_growth_coefficient_logit_corr.size() != 1 ||
770 this->mean_length_old_growth_coefficient_logit_corr.size() != 1)) {
771 Rcpp::stop(
772 "VonBertalanffySchnuteGrowth currently supports a single structured "
773 "delta-method variability parameter set; expected size 1 for "
774 "each structured uncertainty input");
775 }
776
777 const double a1 = this->reference_age_for_length_young[0].initial_value_m;
778 const double a2 = this->reference_age_for_length_old[0].initial_value_m;
779 if (!std::isfinite(a1)) {
780 Rcpp::stop("reference_age_for_length_young must be finite");
781 }
782 if (!std::isfinite(a2)) {
783 Rcpp::stop("reference_age_for_length_old must be finite");
784 }
785 if (a2 <= a1) {
786 Rcpp::stop(
787 "VonBertalanffySchnuteGrowth reference_age_for_length_old must be > "
788 "reference_age_for_length_young");
789 }
790
791 auto check_finite = [](VariableVector& pv, const std::string& base_name) {
792 for (size_t i = 0; i < pv.size(); i++) {
793 if (!std::isfinite(pv[i].initial_value_m)) {
794 Rcpp::stop((base_name + " must be finite").c_str());
795 }
796 }
797 };
798
799 auto check_positive = [&check_finite](VariableVector& pv,
800 const std::string& base_name) {
801 check_finite(pv, base_name);
802 for (size_t i = 0; i < pv.size(); i++) {
803 if (pv[i].initial_value_m <= 0.0) {
804 Rcpp::stop((base_name + " must be > 0").c_str());
805 }
806 }
807 };
808
809 check_positive(this->mean_length_young, "mean_length_young");
810 check_positive(this->mean_length_old, "mean_length_old");
811 check_positive(this->growth_coefficient, "growth_coefficient");
812 check_positive(this->length_weight_a, "length_weight_a");
813 check_positive(this->length_weight_b, "length_weight_b");
814
815 if (this->mean_length_old[0].initial_value_m <=
816 this->mean_length_young[0].initial_value_m) {
817 Rcpp::stop(
818 "VonBertalanffySchnuteGrowth mean_length_old must be > "
819 "mean_length_young");
820 }
821
822 if (has_sd) {
823 check_positive(this->length_at_age_sd_young, "length_at_age_sd_young");
824 check_positive(this->length_at_age_sd_old, "length_at_age_sd_old");
825 }
826 if (has_structured_delta) {
827 check_finite(this->log_sd_mean_length_young, "log_sd_mean_length_young");
828 check_finite(this->log_sd_mean_length_old, "log_sd_mean_length_old");
829 check_finite(this->log_sd_growth_coefficient,
830 "log_sd_growth_coefficient");
832 "mean_length_young_mean_length_old_logit_corr");
834 "mean_length_young_growth_coefficient_logit_corr");
836 "mean_length_old_growth_coefficient_logit_corr");
837 }
838 }
839
840 public:
841 virtual std::string to_json() {
842 std::stringstream ss;
843
844 ss << "{\n";
845 ss << " \"module_name\":\"Growth\",\n";
846 ss << " \"module_type\": \"VonBertalanffySchnute\",\n";
847 ss << " \"module_id\": " << this->id << ",\n";
848
849 ss << " \"parameters\": [\n";
850
851 // mean_length_young
852 ss << "{\n";
853 ss << " \"name\": \"mean_length_young\",\n";
854 ss << " \"id\":" << this->mean_length_young.id_m << ",\n";
855 ss << " \"type\": \"vector\",\n";
856 ss << " \"dimensionality\": {\n";
857 ss << " \"header\": [null],\n";
858 ss << " \"dimensions\": [" << this->mean_length_young.size() << "]\n";
859 ss << " },\n";
860 ss << " \"values\":" << this->mean_length_young << "\n";
861 ss << "},\n";
862
863 // growth_coefficient
864 ss << "{\n";
865 ss << " \"name\": \"growth_coefficient\",\n";
866 ss << " \"id\":" << this->growth_coefficient.id_m << ",\n";
867 ss << " \"type\": \"vector\",\n";
868 ss << " \"dimensionality\": {\n";
869 ss << " \"header\": [null],\n";
870 ss << " \"dimensions\": [" << this->growth_coefficient.size() << "]\n";
871 ss << " },\n";
872 ss << " \"values\":" << this->growth_coefficient << "\n";
873 ss << "},\n";
874
875 // mean_length_old
876 ss << "{\n";
877 ss << " \"name\": \"mean_length_old\",\n";
878 ss << " \"id\":" << this->mean_length_old.id_m << ",\n";
879 ss << " \"type\": \"vector\",\n";
880 ss << " \"dimensionality\": {\n";
881 ss << " \"header\": [null],\n";
882 ss << " \"dimensions\": [" << this->mean_length_old.size() << "]\n";
883 ss << " },\n";
884 ss << " \"values\":" << this->mean_length_old << "\n";
885 ss << "},\n";
886
887 // reference_age_for_length_young
888 ss << "{\n";
889 ss << " \"name\": \"reference_age_for_length_young\",\n";
890 ss << " \"id\":" << this->reference_age_for_length_young.id_m << ",\n";
891 ss << " \"type\": \"vector\",\n";
892 ss << " \"dimensionality\": {\n";
893 ss << " \"header\": [null],\n";
894 ss << " \"dimensions\": [" << this->reference_age_for_length_young.size()
895 << "]\n";
896 ss << " },\n";
897 ss << " \"values\":" << this->reference_age_for_length_young << "\n";
898 ss << "},\n";
899
900 // reference_age_for_length_old
901 ss << "{\n";
902 ss << " \"name\": \"reference_age_for_length_old\",\n";
903 ss << " \"id\":" << this->reference_age_for_length_old.id_m << ",\n";
904 ss << " \"type\": \"vector\",\n";
905 ss << " \"dimensionality\": {\n";
906 ss << " \"header\": [null],\n";
907 ss << " \"dimensions\": [" << this->reference_age_for_length_old.size()
908 << "]\n";
909 ss << " },\n";
910 ss << " \"values\":" << this->reference_age_for_length_old << "\n";
911 ss << "},\n";
912
913 // length_weight_a
914 ss << "{\n";
915 ss << " \"name\": \"length_weight_a\",\n";
916 ss << " \"id\":" << this->length_weight_a.id_m << ",\n";
917 ss << " \"type\": \"vector\",\n";
918 ss << " \"dimensionality\": {\n";
919 ss << " \"header\": [null],\n";
920 ss << " \"dimensions\": [" << this->length_weight_a.size() << "]\n";
921 ss << " },\n";
922 ss << " \"values\":" << this->length_weight_a << "\n";
923 ss << "},\n";
924
925 // length_weight_b (last)
926 ss << "{\n";
927 ss << " \"name\": \"length_weight_b\",\n";
928 ss << " \"id\":" << this->length_weight_b.id_m << ",\n";
929 ss << " \"type\": \"vector\",\n";
930 ss << " \"dimensionality\": {\n";
931 ss << " \"header\": [null],\n";
932 ss << " \"dimensions\": [" << this->length_weight_b.size() << "]\n";
933 ss << " },\n";
934 ss << " \"values\":" << this->length_weight_b << "\n";
935 ss << "}";
936
937 // Optional variability parameters
938 auto append_optional_parameter = [&](const std::string& name,
939 VariableVector& pv) {
940 if (pv.size() == 0) {
941 return;
942 }
943
944 ss << ",\n";
945 ss << "{\n";
946 ss << " \"name\": \"" << name << "\",\n";
947 ss << " \"id\":" << pv.id_m << ",\n";
948 ss << " \"type\": \"vector\",\n";
949 ss << " \"dimensionality\": {\n";
950 ss << " \"header\": [null],\n";
951 ss << " \"dimensions\": [" << pv.size() << "]\n";
952 ss << " },\n";
953 ss << " \"values\":" << pv << "\n";
954 ss << "}";
955 };
956
957 append_optional_parameter("length_at_age_sd_young",
958 this->length_at_age_sd_young);
959 append_optional_parameter("length_at_age_sd_old",
960 this->length_at_age_sd_old);
961 append_optional_parameter("log_sd_mean_length_young",
962 this->log_sd_mean_length_young);
963 append_optional_parameter("log_sd_mean_length_old",
964 this->log_sd_mean_length_old);
965 append_optional_parameter("log_sd_growth_coefficient",
966 this->log_sd_growth_coefficient);
967 append_optional_parameter(
968 "mean_length_young_mean_length_old_logit_corr",
969 this->mean_length_young_mean_length_old_logit_corr);
970 append_optional_parameter(
971 "mean_length_young_growth_coefficient_logit_corr",
972 this->mean_length_young_growth_coefficient_logit_corr);
973 append_optional_parameter(
974 "mean_length_old_growth_coefficient_logit_corr",
975 this->mean_length_old_growth_coefficient_logit_corr);
976
977 ss << "\n]\n";
978 ss << "}";
979
980 return ss.str();
981 }
982#ifdef TMB_MODEL
983 template <typename Type>
984 bool add_to_fims_tmb_internal() {
985 std::shared_ptr<fims_info::Information<Type>> info =
987
988 std::shared_ptr<fims_popdy::GrowthDerivedObservationBase<Type>>
989 growth_observation = std::make_shared<
991 std::shared_ptr<fims_popdy::VonBertalanffySchnuteGrowthModelAdapter<Type>>
992 vb = std::dynamic_pointer_cast<
994 growth_observation);
995 if (!vb) {
996 Rcpp::stop(
997 "Failed to create VonBertalanffySchnute growth-derived observation "
998 "model");
999 }
1000
1001 vb->id = this->id;
1002
1003 // Build parameter vectors and register if estimable. Growth variability
1004 // must be supplied through either the legacy interpolation SD anchors or
1005 // the transformed delta-method variability inputs.
1006 ValidateVonBertalanffySchnuteGrowthInputs(true);
1007
1008 std::stringstream ss;
1009 auto load_and_register = [&](VariableVector& pv, fims::Vector<Type>& target,
1010 const std::string& base_name, bool log_scale) {
1011 target.resize(pv.size());
1012 for (size_t i = 0; i < pv.size(); i++) {
1013 double v = pv[i].initial_value_m;
1014 if (log_scale) {
1015 if (v <= 0.0) {
1016 Rcpp::stop((base_name + " must be > 0").c_str());
1017 }
1018
1019 if (&pv == &this->mean_length_young &&
1020 GetLengthReferenceParameterization() ==
1021 LengthReferenceParameterization::
1022 kEstimatedLengthYoungBelowConstantLengthOld) {
1023 // Match the bounded inverse logit used in evaluation and reporting.
1024 v = fims_math::logit(0.0, InitialLengthAtRefAgeOld(), v);
1025 } else {
1026 v = fims_math::log(v);
1027 }
1028 }
1029 target[i] = static_cast<Type>(v);
1030 if (pv[i].estimation_type_m.get() == "fixed_effects") {
1031 ss.str("");
1032 ss << "Growth." << this->id << "." << base_name << "." << pv[i].id_m;
1033 info->RegisterParameterName(ss.str());
1034 info->RegisterParameter(target[i]);
1035 }
1036 if (pv[i].estimation_type_m.get() == "random_effects") {
1037 ss.str("");
1038 ss << "Growth." << this->id << "." << base_name << "." << pv[i].id_m;
1039 info->RegisterRandomEffectName(ss.str());
1040 info->RegisterRandomEffect(target[i]);
1041 }
1042 }
1043 info->variable_map[pv.id_m] = &target;
1044 };
1045
1046 auto load_optional_and_register =
1047 [&](VariableVector& pv, fims::Vector<Type>& target,
1048 const std::string& base_name, bool log_scale) {
1049 if (pv.size() == 0) {
1050 target.resize(0);
1051 return;
1052 }
1053 load_and_register(pv, target, base_name, log_scale);
1054 };
1055
1056 ConfigureLengthReferenceParameterization<Type>(vb);
1057
1058 load_and_register(this->mean_length_young, vb->MeanLengthYoungVector(),
1059 "mean_length_young", true);
1060 load_and_register(this->mean_length_old, vb->MeanLengthOldVector(),
1061 "mean_length_old", true);
1062 load_and_register(this->growth_coefficient, vb->GrowthCoefficientVector(),
1063 "growth_coefficient", true);
1064 load_and_register(this->reference_age_for_length_young,
1065 vb->ReferenceAgeForLengthYoungVector(),
1066 "reference_age_for_length_young", false);
1067 load_and_register(this->reference_age_for_length_old,
1068 vb->ReferenceAgeForLengthOldVector(),
1069 "reference_age_for_length_old", false);
1070 load_and_register(this->length_weight_a, vb->LengthWeightAVector(),
1071 "length_weight_a", true);
1072 load_and_register(this->length_weight_b, vb->LengthWeightBVector(),
1073 "length_weight_b", true);
1074 load_optional_and_register(this->length_at_age_sd_young,
1075 vb->LengthAtAgeSdYoungVector(),
1076 "length_at_age_sd_young", true);
1077 load_optional_and_register(this->length_at_age_sd_old,
1078 vb->LengthAtAgeSdOldVector(),
1079 "length_at_age_sd_old", true);
1080 load_optional_and_register(this->log_sd_mean_length_young,
1081 vb->LogSdLengthAtRefAgeYoungVector(),
1082 "log_sd_mean_length_young", false);
1083 load_optional_and_register(this->log_sd_mean_length_old,
1084 vb->LogSdLengthAtRefAgeOldVector(),
1085 "log_sd_mean_length_old", false);
1086 load_optional_and_register(this->log_sd_growth_coefficient,
1087 vb->LogSdGrowthCoefficientVector(),
1088 "log_sd_growth_coefficient", false);
1089 load_optional_and_register(
1091 vb->LogitCorrLengthAtRefAgeYoungLengthAtRefAgeOldVector(),
1092 "mean_length_young_mean_length_old_logit_corr", false);
1093 load_optional_and_register(
1095 vb->LogitCorrLengthAtRefAgeYoungKVector(),
1096 "mean_length_young_growth_coefficient_logit_corr", false);
1097 load_optional_and_register(
1099 vb->LogitCorrLengthAtRefAgeOldKVector(),
1100 "mean_length_old_growth_coefficient_logit_corr", false);
1101
1102 this->RegisterGrowthObservationInInfo<Type>(growth_observation);
1103 return true;
1104 }
1105
1106 virtual bool add_to_fims_tmb() {
1107 this->add_to_fims_tmb_internal<TMB_FIMS_REAL_TYPE>();
1108 this->add_to_fims_tmb_internal<TMBAD_FIMS_TYPE>();
1109 return true;
1110 }
1111#endif
1112
1113}; // end class
1114
1115#endif
virtual ~EWAAGrowthInterface()
The destructor.
Definition rcpp_growth.hpp:201
SharedInt n_years
An integer specifying the number of years.
Definition rcpp_growth.hpp:163
std::shared_ptr< std::map< int, std::map< double, double > > > ewaa
A map of empirical weight-at-age values allowing multiple modules to access and modify the weights wi...
Definition rcpp_growth.hpp:168
virtual uint32_t get_id()
Gets the ID of the interface base object.
Definition rcpp_growth.hpp:207
RealVector ages
Ages (years) for each age class.
Definition rcpp_growth.hpp:158
virtual double evaluate(double age)
Evaluate the growth using empirical weight at age.
Definition rcpp_growth.hpp:271
EWAAGrowthInterface(const EWAAGrowthInterface &other)
Construct a new EWAAGrowthInterface object.
Definition rcpp_growth.hpp:190
std::map< int, std::map< double, double > > make_map(RealVector ages, RealVector weights, SharedInt n_years)
Create a map of input numeric vectors.
Definition rcpp_growth.hpp:216
bool initialized
Have weight and age vectors been set? The default is false.
Definition rcpp_growth.hpp:172
RealVector weights
Weights (mt) for each age class.
Definition rcpp_growth.hpp:154
EWAAGrowthInterface()
The constructor.
Definition rcpp_growth.hpp:177
virtual std::string to_json()
Converts the data to json representation for the output.
Definition rcpp_growth.hpp:293
Base class for all interface objects.
Definition rcpp_interface_base.hpp:655
bool finalized
Is the object already finalized? The default is false.
Definition rcpp_interface_base.hpp:660
static std::vector< std::shared_ptr< FIMSRcppInterfaceBase > > fims_interface_objects
FIMS interface object vectors.
Definition rcpp_interface_base.hpp:665
virtual bool add_to_fims_tmb()
A virtual method to inherit to add objects to the TMB model.
Definition rcpp_interface_base.hpp:670
Rcpp interface base for growth models that can register a growth-derived observation capability with ...
Definition rcpp_growth.hpp:84
void RegisterGrowthObservationInInfo(const std::shared_ptr< fims_popdy::GrowthDerivedObservationBase< Type > > &growth_observation) const
Register a runtime growth-derived observation in Information.
Definition rcpp_growth.hpp:135
GrowthDerivedObservationInterfaceBase(const GrowthDerivedObservationInterfaceBase &other)
Copy constructor.
Definition rcpp_growth.hpp:92
std::shared_ptr< fims_popdy::GrowthDerivedObservationBase< Type > > GetGrowthObservationFromInfo() const
Look up the registered growth-derived observation object.
Definition rcpp_growth.hpp:105
static std::map< uint32_t, std::shared_ptr< GrowthInterfaceBase > > live_objects
The map associating the IDs of GrowthInterfaceBase to the objects. This is a live object,...
Definition rcpp_growth.hpp:39
virtual double evaluate(double age)=0
A method for each child growth interface object to inherit so each growth option can have an evaluate...
GrowthInterfaceBase(const GrowthInterfaceBase &other)
Construct a new Growth Interface Base object.
Definition rcpp_growth.hpp:57
virtual ~GrowthInterfaceBase()
The destructor.
Definition rcpp_growth.hpp:62
GrowthInterfaceBase()
The constructor.
Definition rcpp_growth.hpp:44
uint32_t id
The local id of the GrowthInterfaceBase object.
Definition rcpp_growth.hpp:33
virtual uint32_t get_id()=0
Get the ID for the child growth interface objects to inherit.
An Rcpp interface class that defines the RealVector class.
Definition rcpp_interface_base.hpp:431
size_t size()
Returns the size of a RealVector.
Definition rcpp_interface_base.hpp:602
A class that provides shared ownership of an integer value.
Definition rcpp_shared_primitive.hpp:29
int get() const
Retrieve the value of the integer.
Definition rcpp_shared_primitive.hpp:127
An Rcpp interface class that defines the VariableVector class.
Definition rcpp_interface_base.hpp:143
Variable & get(size_t pos)
An internal accessor for calling a position of a VariableVector from R.
Definition rcpp_interface_base.hpp:266
uint32_t id_m
The local ID of the Variable object.
Definition rcpp_interface_base.hpp:156
void resize(size_t size)
Resizes a VariableVector to the desired length.
Definition rcpp_interface_base.hpp:294
size_t size()
Returns the size of a VariableVector.
Definition rcpp_interface_base.hpp:287
Rcpp-facing VonBertalanffySchnute growth module. Inherits "derived observation" capability so this gr...
Definition rcpp_growth.hpp:368
VonBertalanffySchnuteGrowthInterface(const VonBertalanffySchnuteGrowthInterface &other)
Copy constructor.
Definition rcpp_growth.hpp:455
VariableVector log_sd_growth_coefficient
Working-scale von Bertalanffy–Schnute variability parameter for sd(log(growth_coefficient)).
Definition rcpp_growth.hpp:408
virtual void finalize()
Extracts derived quantities back to the Rcpp interface object from the Information object.
Definition rcpp_growth.hpp:487
VariableVector mean_length_young
Expected length at the first reference age.
Definition rcpp_growth.hpp:371
virtual uint32_t get_id()
Get the ID for the child growth interface objects to inherit.
Definition rcpp_growth.hpp:481
VariableVector log_sd_mean_length_young
Working-scale von Bertalanffy–Schnute variability parameter for sd(log(mean_length_young)).
Definition rcpp_growth.hpp:398
VariableVector reference_age_for_length_young
First reference age for the length parameterization.
Definition rcpp_growth.hpp:378
VariableVector mean_length_young_growth_coefficient_logit_corr
Working-scale von Bertalanffy–Schnute variability parameter for corr(log(mean_length_young),...
Definition rcpp_growth.hpp:418
VariableVector growth_coefficient
Growth coefficient.
Definition rcpp_growth.hpp:375
virtual double evaluate(double age)
A method for each child growth interface object to inherit so each growth option can have an evaluate...
Definition rcpp_growth.hpp:558
VonBertalanffySchnuteGrowthInterface()
Construct a new VonBertalanffySchnute growth interface.
Definition rcpp_growth.hpp:430
VariableVector length_at_age_sd_old
Natural-scale length-at-age SD at the older reference age.
Definition rcpp_growth.hpp:393
SharedInt n_ages
Modeled number of ages used for validation.
Definition rcpp_growth.hpp:425
VariableVector reference_age_for_length_old
Second reference age for the length parameterization.
Definition rcpp_growth.hpp:380
VariableVector length_weight_a
Coefficient in the length-weight relationship, W = a * L^b.
Definition rcpp_growth.hpp:383
VariableVector log_sd_mean_length_old
Working-scale von Bertalanffy–Schnute variability parameter for sd(log(mean_length_old)).
Definition rcpp_growth.hpp:403
VariableVector mean_length_old_growth_coefficient_logit_corr
Working-scale von Bertalanffy–Schnute variability parameter for corr(log(mean_length_old),...
Definition rcpp_growth.hpp:423
VariableVector mean_length_young_mean_length_old_logit_corr
Working-scale von Bertalanffy–Schnute variability parameter for corr(log(mean_length_young),...
Definition rcpp_growth.hpp:413
VariableVector mean_length_old
Expected length at the second reference age.
Definition rcpp_growth.hpp:373
virtual std::string to_json()
Convert the data to json representation for the output.
Definition rcpp_growth.hpp:841
VariableVector length_weight_b
Exponent in the length-weight relationship, W = a * L^b.
Definition rcpp_growth.hpp:385
VariableVector length_at_age_sd_young
Natural-scale length-at-age SD at the younger reference age.
Definition rcpp_growth.hpp:389
Definition fims_vector.hpp:27
std::map< uint32_t, std::shared_ptr< fims_popdy::GrowthBase< Type > > >::iterator growth_models_iterator
Definition information.hpp:96
std::map< uint32_t, std::shared_ptr< fims_popdy::GrowthBase< Type > > > growth_models
Definition information.hpp:91
static std::shared_ptr< Information< Type > > GetInstance()
Returns a singleton Information object for type T.
Definition information.hpp:262
Generic capability interface for growth models that can feed the growth-derived age-to-length convers...
Definition growth_model_adapter.hpp:26
von Bertalanffy–Schnute growth model adapter implementing the generic growth-derived observation capa...
Definition growth_model_adapter.hpp:79
#define FIMS_WARNING_LOG(MESSAGE)
Definition def.hpp:648
std::string to_string(T v)
Definition def.hpp:735
A collection of mathematical functions used in FIMS.
const Type logit(const Type &a, const Type &b, const Type &x)
A logit function for bounding of parameters.
Definition fims_math.hpp:261
const Type inv_logit(const Type &a, const Type &b, const Type &logit_x)
An inverse logit function for bounding of parameters.
Definition fims_math.hpp:276
Establishes the FIMS Vector class.
Includes any .hpp files within the subfolders so that only this file needs to included in include sta...
The Rcpp interface to declare objects that are used ubiquitously throughout the Rcpp interface,...
uint32_t id
Definition model_object.hpp:56
EWAAGrowth class that returns the EWAA function value.
Definition ewaa.hpp:23
std::map< int, std::map< double, double > > ewaa
Definition ewaa.hpp:29
virtual const Type evaluate(int year, const double &a)
Returns the weight at age a (in kg) from the input vector.
Definition ewaa.hpp:44
VonBertalanffySchnute growth functor for length-at-age and weight-at-age.
Definition vonb_schnute.hpp:32
Type mean_length_young
Expected length at the first reference age.
Definition vonb_schnute.hpp:34
Type reference_age_for_length_old
Second reference age for the length parameterization.
Definition vonb_schnute.hpp:42
Type growth_coefficient
Growth coefficient.
Definition vonb_schnute.hpp:38
Type length_weight_b
Exponent in the length-weight relationship, W = a * L^b.
Definition vonb_schnute.hpp:47
Type reference_age_for_length_young
First reference age for the length parameterization.
Definition vonb_schnute.hpp:40
Type length_weight_a
Coefficient in the length-weight relationship, W = a * L^b.
Definition vonb_schnute.hpp:45
virtual const Type evaluate(int year, const double &a) override
Calculates the growth at the independent variable value.
Definition vonb_schnute.hpp:194
Type mean_length_old
Expected length at the second reference age.
Definition vonb_schnute.hpp:36