FIMS  v0.11.0
Loading...
Searching...
No Matches
information.hpp
Go to the documentation of this file.
1
10
11#ifndef FIMS_COMMON_INFORMATION_HPP
12#define FIMS_COMMON_INFORMATION_HPP
13
14#include <algorithm>
15#include <map>
16#include <memory>
17#include <vector>
18
29#include "def.hpp"
30#include "fims_vector.hpp"
31#include "model_object.hpp"
32
33namespace fims_info {
34
39template <typename Type>
40class Information {
41 public:
42 size_t n_years = 0;
43 size_t n_ages = 0;
44
45 static std::shared_ptr<Information<Type>>
47 std::vector<Type*> parameters;
48 std::vector<Type*>
50 std::vector<Type*>
52 std::vector<std::string> parameter_names;
54 std::vector<std::string>
57
58 // data objects
59 std::map<uint32_t, std::shared_ptr<fims_data_object::DataObject<Type>>>
61 typedef typename std::map<
62 uint32_t, std::shared_ptr<fims_data_object::DataObject<Type>>>::iterator
64
65 // life history modules
66 std::map<uint32_t, std::shared_ptr<fims_popdy::RecruitmentBase<Type>>>
69 typedef typename std::map<
70 uint32_t, std::shared_ptr<fims_popdy::RecruitmentBase<Type>>>::iterator
73
74 std::map<uint32_t, std::shared_ptr<fims_popdy::RecruitmentBase<Type>>>
77 typedef typename std::map<
78 uint32_t, std::shared_ptr<fims_popdy::RecruitmentBase<Type>>>::iterator
81
82 std::map<uint32_t, std::shared_ptr<fims_popdy::SelectivityBase<Type>>>
85 typedef typename std::map<
86 uint32_t, std::shared_ptr<fims_popdy::SelectivityBase<Type>>>::iterator
89
90 std::map<uint32_t, std::shared_ptr<fims_popdy::GrowthBase<Type>>>
93 typedef
94 typename std::map<uint32_t,
95 std::shared_ptr<fims_popdy::GrowthBase<Type>>>::iterator
98
99 std::map<uint32_t, std::shared_ptr<fims_popdy::MaturityBase<Type>>>
102 typedef typename std::map<
103 uint32_t, std::shared_ptr<fims_popdy::MaturityBase<Type>>>::iterator
106
107 // fleet modules
108 std::map<uint32_t, std::shared_ptr<fims_popdy::Fleet<Type>>>
111 typedef typename std::map<uint32_t,
112 std::shared_ptr<fims_popdy::Fleet<Type>>>::iterator
115
116 // populations
117 std::map<uint32_t, std::shared_ptr<fims_popdy::Population<Type>>>
120 typedef
121 typename std::map<uint32_t,
122 std::shared_ptr<fims_popdy::Population<Type>>>::iterator
125
126 // distributions
127 std::map<uint32_t,
128 std::shared_ptr<fims_distributions::DensityComponentBase<Type>>>
131 typedef typename std::map<
132 uint32_t,
133 std::shared_ptr<fims_distributions::DensityComponentBase<Type>>>::iterator
136
137 std::unordered_map<uint32_t,
138 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>>
141 typedef typename std::unordered_map<
142 uint32_t, std::shared_ptr<fims_popdy::FisheryModelBase<Type>>>::iterator
144
145 std::unordered_map<uint32_t, fims::Vector<Type>*>
148 typedef typename std::unordered_map<uint32_t, fims::Vector<Type>*>::iterator
150
151 Information() {}
152
153 // Explicit Clear() is not guaranteed before package unload or process exit.
154 // Break recruitment/process ownership cycles while both maps are still alive.
155 virtual ~Information() { ResetRecruitmentLinks(); }
156
157 private:
163 void ResetRecruitmentLinks() noexcept {
164 auto detach = [](auto& models) {
165 for (auto& entry : models) {
166 const auto& recruitment = entry.second;
167 if (recruitment) {
168 recruitment->process.reset();
169 recruitment->recruitment.reset();
170 }
171 }
172 };
173 detach(this->recruitment_models);
174 detach(this->recruitment_process_models);
175 }
176
177 public:
182 void Clear() {
183 this->data_objects.clear();
184 this->populations.clear();
185 this->fixed_effects_parameters.clear();
186 this->fleets.clear();
187 this->growth_models.clear();
188 this->maturity_models.clear();
189 this->parameter_names.clear();
190 this->parameters.clear();
191 this->random_effects_names.clear();
192 this->random_effects_parameters.clear();
193 this->selectivity_models.clear();
194 this->models_map.clear();
195 this->n_years = 0;
196 this->n_ages = 0;
197
198 ResetRecruitmentLinks();
199 this->recruitment_models.clear();
200 this->recruitment_process_models.clear();
201
202 // Density components borrow these vectors from the population, fleet, and
203 // recruitment modules released above, so only drop the links. Reading
204 // through them here would touch freed memory.
206 it != density_components.end(); ++it) {
207 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
208 (*it).second;
209 d->priors.clear();
210 d->data_observed_values.reset();
211 d->data_expected_values = nullptr;
212 d->re = nullptr;
213 d->re_expected_values = nullptr;
214 }
215 this->density_components.clear();
216 }
217
227 std::string State() {
228 std::stringstream ss;
229 ss << "Information object State:\n";
230 ss << "data_objects: " << this->data_objects.clear();
231 ss << "populations: " << this->populations.size() << std::endl;
232 ss << "fixed_effects_parameters: " << this->fixed_effects_parameters.size()
233 << std::endl;
234 ss << "fleets: " << this->fleets.size() << std::endl;
235 ss << "growth_models: " << this->growth_models.size() << std::endl;
236 ss << "maturity_models: " << this->maturity_models.size() << std::endl;
237 ss << "parameter_names: " << this->parameter_names.size() << std::endl;
238 ss << "parameters: " << this->parameters.size() << std::endl;
239 ss << "random_effects_names: " << this->random_effects_names.size()
240 << std::endl;
241 ss << "random_effects_parameters: "
242 << this->random_effects_parameters.size() << std::endl;
243 ss << "recruitment_models: " << this->recruitment_models.size()
244 << std::endl;
245 ss << "recruitment_process_models: "
246 << this->recruitment_process_models.size() << std::endl;
247 ss << "selectivity_models: " << this->selectivity_models.size()
248 << std::endl;
249 ss << "models_map: " << this->models_map.size() << std::endl;
250 ss << "n_years: " << this->n_years << std::endl;
251 ss << "n_ages: " << this->n_ages << std::endl;
252 ss << "density_components: " << this->density_components.size()
253 << std::endl;
254 return ss.str();
255 }
256
262 static std::shared_ptr<Information<Type>> GetInstance() {
265 std::make_shared<fims_info::Information<Type>>();
266 }
268 }
269
275 void RegisterParameter(Type& p) {
276 this->fixed_effects_parameters.push_back(&p);
277 }
278
284 void RegisterRandomEffect(Type& re) {
285 this->random_effects_parameters.push_back(&re);
286 }
287
293 void RegisterParameterName(std::string p_name) {
294 this->parameter_names.push_back(p_name);
295 }
296
302 void RegisterRandomEffectName(std::string re_name) {
303 this->random_effects_names.push_back(re_name);
304 }
305
310 void SetupPriors() {
312 it != density_components.end(); ++it) {
313 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
314 (*it).second;
315 if (d->input_type == "prior") {
316 FIMS_INFO_LOG("Setup prior for distribution " + fims::to_string(d->id));
318 FIMS_INFO_LOG("Link prior from distribution " + fims::to_string(d->id) +
319 " to parameter " + fims::to_string(d->key[0]));
320 d->priors.resize(d->key.size());
321 for (size_t i = 0; i < d->key.size(); i++) {
322 FIMS_INFO_LOG("Link prior from distribution " +
323 fims::to_string(d->id) + " to parameter " +
324 fims::to_string(d->key[0]));
325 vmit = this->variable_map.find(d->key[i]);
326 d->priors[i] = (*vmit).second;
327 }
328 FIMS_INFO_LOG("Prior size for distribution " + fims::to_string(d->id) +
329 "is: " + fims::to_string(d->observed_values.size()));
330 }
331 }
332 }
333
339 for (density_components_iterator it = this->density_components.begin();
340 it != this->density_components.end(); ++it) {
341 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
342 (*it).second;
343 if (d->input_type == "random_effects") {
344 FIMS_INFO_LOG("Setup random effects for distribution " +
345 fims::to_string(d->id));
347 FIMS_INFO_LOG("Link random effects from distribution " +
348 fims::to_string(d->id) + " to derived value " +
349 fims::to_string(d->key[0]));
350 vmit = this->variable_map.find(d->key[0]);
351 d->re = (*vmit).second;
352 if (d->key.size() == 2) {
353 vmit = this->variable_map.find(d->key[1]);
354 d->re_expected_values = (*vmit).second;
355 } else {
356 d->re_expected_values = &d->expected_values;
357 }
358 FIMS_INFO_LOG("Random effect size for distribution " +
359 fims::to_string(d->id) +
360 " is: " + fims::to_string(d->observed_values.size()));
361 }
362 }
363 }
364
369 void SetupData() {
370 for (density_components_iterator it = this->density_components.begin();
371 it != this->density_components.end(); ++it) {
372 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
373 (*it).second;
374 if (d->input_type == "data") {
375 FIMS_INFO_LOG("Setup expected value for data distribution " +
376 fims::to_string(d->id));
378 FIMS_INFO_LOG("Link expected value from distribution " +
379 fims::to_string(d->id) + " to derived value " +
380 fims::to_string(d->key[0]));
381 vmit = this->variable_map.find(d->key[0]);
382 d->data_expected_values = (*vmit).second;
384 "Expected value size for distribution " + fims::to_string(d->id) +
385 " is: " + fims::to_string((*d->data_expected_values).size()));
386 }
387 }
388 }
389
397 void SetFleetCatchData(bool& valid_model,
398 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
399 if (f->fleet_observed_catch_data_id_m != static_cast<Type>(-999)) {
400 uint32_t observed_catch_id =
401 static_cast<uint32_t>(f->fleet_observed_catch_data_id_m);
402 data_iterator it = this->data_objects.find(observed_catch_id);
403 if (it != this->data_objects.end()) {
404 f->observed_catch_data = (*it).second;
405 FIMS_INFO_LOG("Catch data for fleet " + fims::to_string(f->id) +
406 " successfully set to " +
407 fims::to_string(f->observed_catch_data->at(1)));
408 } else {
409 valid_model = false;
410 FIMS_ERROR_LOG("Expected catch data not defined for fleet " +
411 fims::to_string(f->id) + ", index " +
412 fims::to_string(observed_catch_id));
413 }
414 }
415 }
416
424 void SetFleetIndexData(bool& valid_model,
425 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
426 if (f->fleet_observed_index_data_id_m != static_cast<Type>(-999)) {
427 uint32_t observed_index_id =
428 static_cast<uint32_t>(f->fleet_observed_index_data_id_m);
429 data_iterator it = this->data_objects.find(observed_index_id);
430 if (it != this->data_objects.end()) {
431 f->observed_index_data = (*it).second;
432 FIMS_INFO_LOG("Index data for fleet " + fims::to_string(f->id) +
433 " successfully set to " +
434 fims::to_string(f->observed_index_data->at(1)));
435 } else {
436 valid_model = false;
437 FIMS_ERROR_LOG("Expected index data not defined for fleet " +
438 fims::to_string(f->id) + ", index " +
439 fims::to_string(observed_index_id));
440 }
441 }
442 }
443
451 void SetAgeCompositionData(bool& valid_model,
452 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
453 if (f->fleet_observed_agecomp_data_id_m != static_cast<Type>(-999)) {
454 uint32_t observed_agecomp_id =
455 static_cast<uint32_t>(f->fleet_observed_agecomp_data_id_m);
456 data_iterator it = this->data_objects.find(observed_agecomp_id);
457 if (it != this->data_objects.end()) {
458 f->observed_agecomp_data = (*it).second;
459 FIMS_INFO_LOG("Observed input age-composition data for fleet " +
460 fims::to_string(f->id) + " successfully set to " +
461 fims::to_string(f->observed_agecomp_data->at(1)));
462 } else {
463 valid_model = false;
465 "Expected age-composition observations not defined for fleet " +
466 fims::to_string(f->id));
467 }
468 }
469 }
470
478 void SetLengthCompositionData(bool& valid_model,
479 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
480 if (f->fleet_observed_lengthcomp_data_id_m != static_cast<Type>(-999)) {
481 uint32_t observed_lengthcomp_id =
482 static_cast<uint32_t>(f->fleet_observed_lengthcomp_data_id_m);
483 data_iterator it = this->data_objects.find(observed_lengthcomp_id);
484 if (it != this->data_objects.end()) {
485 f->observed_lengthcomp_data = (*it).second;
486 FIMS_INFO_LOG("Observed input length-composition data for fleet " +
487 fims::to_string(f->id) + " successfully set to " +
488 fims::to_string(f->observed_lengthcomp_data->at(1)));
489 } else {
490 valid_model = false;
492 "Expected length-composition observations not defined for fleet " +
493 fims::to_string(f->id));
494 }
495 }
496 }
497
506 void SetFleetSelectivityModel(bool& valid_model,
507 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
508 if (f->fleet_selectivity_id_m != static_cast<Type>(-999)) {
509 uint32_t sel_id = static_cast<uint32_t>(
510 f->fleet_selectivity_id_m); // cast as unsigned integer
512 sel_id); // if find, set it, otherwise invalid
513
514 if (it != this->selectivity_models.end()) {
515 f->selectivity = (*it).second; // elements in container held in pair
516 FIMS_INFO_LOG("Selectivity model " +
517 fims::to_string(f->fleet_selectivity_id_m) +
518 " successfully set to fleet " + fims::to_string(f->id));
519 } else {
520 valid_model = false;
521 FIMS_ERROR_LOG("Expected selectivity pattern not defined for fleet " +
522 fims::to_string(f->id) + ", selectivity pattern " +
523 fims::to_string(sel_id));
524 }
525 } else {
526 FIMS_WARNING_LOG("Warning: No selectivity pattern defined for fleet " +
527 fims::to_string(f->id) +
528 ". FIMS requires selectivity be defined for all fleets "
529 "when running a catch at age model.");
530 }
531 }
532
543 bool& valid_model, std::shared_ptr<fims_popdy::Population<Type>> p,
544 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
545 if (p == nullptr || f == nullptr) {
546 valid_model = false;
548 "Unable to set fleet age-to-length conversion because the population "
549 "or fleet "
550 "pointer was null.");
551 return;
552 }
553
554 f->age_to_length_conversion_model =
556
557 if (f->age_to_length_conversion_model != nullptr &&
558 f->age_to_length_conversion_model->IsActive()) {
559 return;
560 }
561
562 if (!f->requires_age_length_mapping) {
563 return;
564 }
565
566 if (f->n_lengths == 0) {
567 valid_model = false;
568 FIMS_ERROR_LOG("Fleet " + fims::to_string(f->id) +
569 " requires age-to-length conversion but has no fleet "
570 "length observation bins. Provide length_bin rows or "
571 "length_comp rows with length values.");
572 return;
573 }
574
575 valid_model = false;
576 FIMS_ERROR_LOG("Fleet " + fims::to_string(f->id) +
577 " has fleet length observation bins but no usable "
578 "age-to-length conversion path. Provide fixed "
579 "age-to-length conversion of size " +
580 fims::to_string(f->n_ages * f->n_lengths) + " (or " +
581 fims::to_string(f->n_years * f->n_ages * f->n_lengths) +
582 " for 1 table per year) or use a supported growth-derived "
583 "age-to-length conversion path.");
584 }
585
594 void SetRecruitment(bool& valid_model,
595 std::shared_ptr<fims_popdy::Population<Type>> p) {
596 if (p->recruitment_id != static_cast<Type>(-999)) {
597 uint32_t recruitment_uint = static_cast<uint32_t>(p->recruitment_id);
598
600 this->recruitment_models.find(recruitment_uint);
601
602 if (it != this->recruitment_models.end()) {
603 p->recruitment = (*it).second; // recruitment defined in population.hpp
604 FIMS_INFO_LOG("Recruitment model " + fims::to_string(recruitment_uint) +
605 " successfully set to population " +
606 fims::to_string(p->id));
607 } else {
608 valid_model = false;
610 "Expected recruitment function not defined for "
611 "population " +
612 fims::to_string(p->id) + ", recruitment function " +
613 fims::to_string(recruitment_uint));
614 }
615 } else {
617 "No recruitment function defined for population " +
618 fims::to_string(p->id) +
619 ". FIMS requires recruitment functions be defined for all "
620 "populations when running a catch at age model.");
621 }
622 }
623
632 void SetRecruitmentProcess(bool& valid_model,
633 std::shared_ptr<fims_popdy::Population<Type>> p) {
634 std::shared_ptr<fims_popdy::RecruitmentBase<Type>> r = p->recruitment;
635 // if recruitment is defined
636 if (r) {
637 if (r->process_id != static_cast<Type>(-999)) {
638 uint32_t process_uint = static_cast<uint32_t>(r->process_id);
640 this->recruitment_process_models.find(process_uint);
641
642 if (it != this->recruitment_process_models.end()) {
643 r->process = (*it).second; // recruitment process
645 "Recruitment Process model " + fims::to_string(process_uint) +
646 " successfully set to population " + fims::to_string(p->id));
647 (*it).second->recruitment = r;
648 } else {
649 valid_model = false;
651 "Expected recruitment process function not defined for "
652 "population " +
653 fims::to_string(p->id) + ", recruitment process function " +
654 fims::to_string(process_uint));
655 }
656 } else {
658 "No recruitment process function defined for population " +
659 fims::to_string(p->id) +
660 ". FIMS requires recruitment process functions be defined for all "
661 "recruitments when running a catch at age model.");
662 }
663 }
664 }
665
674 const std::shared_ptr<fims_popdy::Population<Type>>& p) {
676
677 for (std::size_t fleet_index = 0; fleet_index < p->fleets.size();
678 ++fleet_index) {
679 const std::shared_ptr<fims_popdy::Fleet<Type>>& fleet =
680 p->fleets[fleet_index];
681
682 if (fleet == nullptr) {
683 continue;
684 }
685
686 if (!fleet->requires_age_length_mapping || fleet->n_lengths == 0) {
687 fleet->length_bin_edges = fims::Vector<double>();
688 continue;
689 }
690
691 if (fleet->lengths.size() != fleet->n_lengths) {
692 throw std::runtime_error(
693 "Fleet length_bin lower edges are not consistent with n_lengths");
694 }
695
696 fleet->length_bin_edges =
698 fleet->lengths);
699
700 fleet_edges.emplace_back(fleet->length_bin_edges);
701 }
702
703 return fleet_edges;
704 }
705
720 const fims_popdy::SizeGrid& size_grid,
721 const fims::Vector<fims::Vector<double>>& fleet_edges) {
722 if (!size_grid.IsConsistent() || size_grid.n_bins == 0 ||
723 fleet_edges.size() == 0) {
724 return;
725 }
726
727 for (std::size_t population_bin_index = 0;
728 population_bin_index < size_grid.n_bins; ++population_bin_index) {
729 const double population_left = size_grid.edges[population_bin_index];
730 const double population_right = size_grid.edges[population_bin_index + 1];
731 const double population_bin_width = population_right - population_left;
732 const double population_tolerance =
733 1e-12 * (population_bin_width > 1.0 ? population_bin_width : 1.0);
734
735 for (std::size_t fleet_index = 0; fleet_index < fleet_edges.size();
736 ++fleet_index) {
737 const fims::Vector<double>& edges = fleet_edges[fleet_index];
738
739 for (std::size_t fleet_bin_index = 1; fleet_bin_index < edges.size();
740 ++fleet_bin_index) {
741 const double fleet_left = edges[fleet_bin_index - 1];
742 const double fleet_right = edges[fleet_bin_index];
743 const double overlap_left = std::max(population_left, fleet_left);
744 const double overlap_right = std::min(population_right, fleet_right);
745
746 if (!(overlap_right > overlap_left)) {
747 continue;
748 }
749
750 const double fleet_bin_width = fleet_right - fleet_left;
751 if (population_bin_width > fleet_bin_width + population_tolerance) {
752 throw std::runtime_error(
753 "Population biological size grid contains at least one bin "
754 "that is coarser than an overlapping active fleet observation "
755 "bin. Provide a finer biological size-grid override or correct "
756 "the fleet bin setup.");
757 }
758 }
759 }
760 }
761 }
762
781 bool& valid_model, std::shared_ptr<fims_popdy::Population<Type>> p) {
783
784 try {
785 fleet_edges = PrepareFleetObservationBinEdges(p);
786 } catch (const std::exception& e) {
787 valid_model = false;
789 "Failed to prepare fleet observation-bin geometry for population " +
790 fims::to_string(p->id) + ": " + e.what());
791 return;
792 }
793
794 if (p->size_grid.IsConsistent() && p->size_grid.n_bins > 0) {
795 try {
796 EnforcePopulationGridNotCoarserThanFleetBins(p->size_grid, fleet_edges);
797 } catch (const std::exception& e) {
798 valid_model = false;
800 "Population " + fims::to_string(p->id) +
801 " has a biological size grid that is incompatible with active "
802 "fleet observation bins: " +
803 e.what());
804 }
805 return;
806 }
807
808 const bool size_grid_missing = p->size_grid.n_bins == 0 &&
809 p->size_grid.edges.size() == 0 &&
810 p->size_grid.centers.size() == 0;
811
812 if (size_grid_missing) {
813 try {
814 if (fleet_edges.size() == 0) {
815 throw std::runtime_error(
816 "No resolvable fleet observation-bin geometry was available "
817 "to build the default biological size grid");
818 }
819
821 fleet_edges);
822 EnforcePopulationGridNotCoarserThanFleetBins(p->size_grid, fleet_edges);
823
824 const std::size_t regular_bin_count =
825 p->size_grid.n_bins > 0 ? p->size_grid.n_bins - 1 : 0;
826
827 if (regular_bin_count > 200) {
829 "Built-in default biological size grid created more than 200 "
830 "regular bins for population " +
831 fims::to_string(p->id) +
832 ". This may slow model evaluation. Consider providing a "
833 "biological size-grid override if needed.");
834 }
835
836 } catch (const std::exception& e) {
837 valid_model = false;
839 "Failed to initialize default population size grid for "
840 "population " +
841 fims::to_string(p->id) + ": " + e.what());
842 }
843 return;
844 }
845
846 valid_model = false;
848 "Population " + fims::to_string(p->id) +
849 " has an invalid biological size grid. Provide a consistent override "
850 "or leave the grid empty so FIMS can build the default.");
851 }
852
861 std::shared_ptr<fims_popdy::Population<Type>> p,
863 growth_observation) {
864 std::shared_ptr<fims_popdy::GrowthDerivedSizeProvider<Type>> size_provider =
865 std::make_shared<fims_popdy::GrowthDerivedSizeProvider<Type>>();
866
867 size_provider->SetGrowth(growth_observation);
868 size_provider->SetPopulationDimensions(p->n_years, p->n_ages);
869 size_provider->SetPopulationSizeGrid(&(p->size_grid));
870
871 p->size_distribution_provider = size_provider;
872 }
873
882 void SetGrowth(bool& valid_model,
883 std::shared_ptr<fims_popdy::Population<Type>> p) {
884 if (p->growth_id != static_cast<Type>(-999)) {
885 uint32_t growth_uint = static_cast<uint32_t>(p->growth_id);
887 growth_uint); // growth_models is specified in information.hpp
888 // and used in rcpp
889 // at the head of information.hpp; are the
890 // dimensions of ages defined in rcpp or where?
891 if (it != this->growth_models.end()) {
892 p->growth =
893 (*it).second; // growth defined in population.hpp (the object
894 // is called p, growth is within p)
896 growth_observation = std::dynamic_pointer_cast<
898 p->growth)) {
899 growth_observation->Initialize(p->n_years, p->n_ages, 1);
900
901 if (p->ages.size() > 0) {
902 double min_age = p->ages[0];
903 for (size_t i = 1; i < p->ages.size(); ++i) {
904 if (p->ages[i] < min_age) {
905 min_age = p->ages[i];
906 }
907 }
908 growth_observation->SetAgeOffset(static_cast<double>(min_age));
909 }
910
911 const bool population_has_size_grid_input =
912 p->size_grid.n_bins > 0 || p->size_grid.edges.size() > 0 ||
913 p->size_grid.centers.size() > 0;
914
915 bool any_length_based_fleet = false;
916 for (std::size_t i = 0; i < p->fleets.size(); ++i) {
917 if (p->fleets[i] != nullptr &&
918 p->fleets[i]->requires_age_length_mapping &&
919 p->fleets[i]->n_lengths > 0) {
920 any_length_based_fleet = true;
921 break;
922 }
923 }
924
925 if (population_has_size_grid_input || any_length_based_fleet) {
926 EnsurePopulationSizeGrid(valid_model, p);
927 if (!valid_model) {
928 return;
929 }
930 ConfigureGrowthDerivedSizeProvider(p, growth_observation);
931 }
932 }
933 FIMS_INFO_LOG("Growth model " + fims::to_string(growth_uint) +
934 " successfully set to population " +
935 fims::to_string(p->id));
936 } else {
937 valid_model = false;
938 FIMS_ERROR_LOG("Expected growth function not defined for population " +
939 fims::to_string(p->id) + ", growth function " +
940 fims::to_string(growth_uint));
941 }
942 } else {
943 FIMS_WARNING_LOG("Growth function undefined for population " +
944 fims::to_string(p->id) +
945 ". FIMS requires growth functions be defined for all "
946 "populations when running a catch at age model.");
947 }
948 }
949
958 void SetMaturity(bool& valid_model,
959 std::shared_ptr<fims_popdy::Population<Type>> p) {
960 if (p->maturity_id != static_cast<Type>(-999)) {
961 uint32_t maturity_uint = static_cast<uint32_t>(p->maturity_id);
963 maturity_uint); // >maturity_models is specified in
964 // information.hpp and used in rcpp
965 if (it != this->maturity_models.end()) {
966 p->maturity = (*it).second; // >maturity defined in population.hpp
967 FIMS_INFO_LOG("Maturity model " + fims::to_string(maturity_uint) +
968 " successfully set to population " +
969 fims::to_string(p->id));
970 } else {
971 valid_model = false;
973 "Expected maturity function not defined for population " +
974 fims::to_string(p->id) + ", maturity function " +
975 fims::to_string(maturity_uint));
976 }
977 } else {
978 FIMS_WARNING_LOG("Maturity function undefined for population " +
979 fims::to_string(p->id) +
980 ". FIMS requires maturity functions be defined for all "
981 "populations when running a catch at age model.");
982 }
983 }
984
991 void CreateFleetObjects(bool& valid_model) {
992 for (fleet_iterator it = this->fleets.begin(); it != this->fleets.end();
993 ++it) {
994 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
995 FIMS_INFO_LOG("Initializing fleet " + fims::to_string(f->id));
996
997 SetFleetCatchData(valid_model, f);
998
999 SetFleetIndexData(valid_model, f);
1000
1001 SetAgeCompositionData(valid_model, f);
1002
1003 SetLengthCompositionData(valid_model, f);
1004
1005 SetFleetSelectivityModel(valid_model, f);
1006 }
1007 }
1008
1015 void SetDataObjects(bool& valid_model) {
1016 for (density_components_iterator it = this->density_components.begin();
1017 it != this->density_components.end(); ++it) {
1018 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
1019 (*it).second;
1020
1021 // set data objects if distribution is a data type
1022 if (d->input_type == "data") {
1023 if (d->observed_data_id_m != static_cast<Type>(-999)) {
1024 uint32_t observed_data_id =
1025 static_cast<uint32_t>(d->observed_data_id_m);
1026 data_iterator it = this->data_objects.find(observed_data_id);
1027
1028 if (it != this->data_objects.end()) {
1029 d->data_observed_values = (*it).second;
1030 FIMS_INFO_LOG("Observed data " + fims::to_string(observed_data_id) +
1031 " successfully set to density component " +
1032 fims::to_string(d->id));
1033 } else {
1034 valid_model = false;
1036 "Expected data observations not defined for density "
1037 "component " +
1038 fims::to_string(d->id) + ", observed data " +
1039 fims::to_string(observed_data_id));
1040 }
1041 } else {
1042 valid_model = false;
1043 FIMS_ERROR_LOG("No data input for density component" +
1044 fims::to_string(d->id));
1045 }
1046 }
1047 }
1048 }
1049
1056 void CreatePopulationObjects(bool& valid_model) {
1057 for (population_iterator it = this->populations.begin();
1058 it != this->populations.end(); ++it) {
1059 std::shared_ptr<fims_popdy::Population<Type>> p = (*it).second;
1060
1061 FIMS_INFO_LOG("Initializing population " + fims::to_string(p->id));
1062 // check if population has fleets
1063 typename std::set<uint32_t>::iterator fleet_ids_it;
1064
1065 for (fleet_ids_it = p->fleet_ids.begin();
1066 fleet_ids_it != p->fleet_ids.end(); ++fleet_ids_it) {
1067 // error check and set population elements
1068 // check me - add another fleet iterator to push information from
1069 // for (fleet_iterator it = this->fleets.begin(); it !=
1070 // this->fleets.end();
1071 // ++it) {
1072
1073 fleet_iterator it = this->fleets.find(*fleet_ids_it);
1074
1075 if (it != this->fleets.end()) {
1076 // Initialize fleet object
1077 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
1078 // population to the individual fleets This is to pass catch at age
1079 // from population to fleets?
1080 // any shared member in p (population is pushed into fleets)
1081 p->fleets.push_back(f);
1082 } else {
1083 valid_model = false;
1084 FIMS_ERROR_LOG("Fleet \"" + fims::to_string(*fleet_ids_it) +
1085 "\" undefined, not found for Population \"" +
1086 fims::to_string(p->id) + "\". ");
1087 }
1088 }
1089
1090 // set information dimensions
1091 this->n_years = std::max(this->n_years, p->n_years);
1092 this->n_ages = std::max(this->n_ages, p->n_ages);
1093
1094 SetRecruitment(valid_model, p);
1095
1096 SetRecruitmentProcess(valid_model, p);
1097
1098 SetGrowth(valid_model, p);
1099 for (size_t i = 0; i < p->fleets.size(); ++i) {
1100 SetFleetAgeToLengthConversionModel(valid_model, p, p->fleets[i]);
1101 }
1102
1103 SetMaturity(valid_model, p);
1104 }
1105 }
1106
1110 void CreateModelingObjects(bool& valid_model) {
1111 for (model_map_iterator it = this->models_map.begin();
1112 it != this->models_map.end(); ++it) {
1113 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>& model = (*it).second;
1114 std::set<uint32_t>::iterator jt;
1115
1116 for (jt = model->population_ids.begin();
1117 jt != model->population_ids.end(); ++jt) {
1118 population_iterator pt = this->populations.find((*jt));
1119
1120 if (pt != this->populations.end()) {
1121 std::shared_ptr<fims_popdy::Population<Type>> p = (*pt).second;
1122 model->populations.push_back(p);
1123 for (size_t i = 0; i < p->fleets.size(); i++) {
1124 uint32_t local_fleet_id = p->fleets[i]->GetId();
1125 model->fleets[local_fleet_id] = p->fleets[i];
1126 FIMS_INFO_LOG(std::string("Linked fleet id ") +
1127 fims::to_string(local_fleet_id) +
1128 std::string(" into model id ") +
1129 fims::to_string(model->GetId()));
1130 }
1131 } else {
1132 valid_model = false;
1133 FIMS_ERROR_LOG("No population object defined for model " +
1134 fims::to_string(model->GetId()));
1135 }
1136 }
1137 model->Initialize();
1138 }
1139 }
1140
1152 FIMS_INFO_LOG("Creating model and checking for required components...");
1153 bool valid_model = true;
1154
1155 CreateFleetObjects(valid_model);
1156
1157 SetDataObjects(valid_model);
1158
1159 CreatePopulationObjects(valid_model);
1160
1161 CreateModelingObjects(valid_model);
1162
1163 // setup priors, random effect, and data density components
1164 SetupPriors();
1166 SetupData();
1167
1168 if (valid_model) {
1169 FIMS_INFO_LOG("Model successfully created.");
1170 } else {
1171 FIMS_ERROR_LOG("Model creation failed.");
1172 }
1173
1174 return valid_model;
1175 }
1176
1182 size_t GetNages() const { return n_ages; }
1183
1189 void SetNages(size_t n_ages) { this->n_ages = n_ages; }
1190
1196 size_t GetNyears() const { return n_years; }
1197
1203 void SetNyears(size_t n_years) { this->n_years = n_years; }
1204
1210 std::vector<Type*>& GetParameters() { return parameters; }
1211
1217 std::vector<Type*>& GetFixedEffectsParameters() {
1219 }
1220
1226 std::vector<Type*>& GetRandomEffectsParameters() {
1228 }
1229
1237 bool CheckModel() {
1238 bool valid_model = true;
1239 for (model_map_iterator it = this->models_map.begin();
1240 it != this->models_map.end(); ++it) {
1241 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>& model = (*it).second;
1242 std::set<uint32_t>::iterator jt;
1243
1244 for (jt = model->population_ids.begin();
1245 jt != model->population_ids.end(); ++jt) {
1246 population_iterator pt = this->populations.find((*jt));
1247
1248 if (pt != this->populations.end()) {
1249 std::shared_ptr<fims_popdy::Population<Type>> p = (*pt).second;
1250
1251 if (model->model_type_m == "caa") {
1252 typename std::set<uint32_t>::iterator fleet_ids_it;
1253 for (fleet_ids_it = p->fleet_ids.begin();
1254 fleet_ids_it != p->fleet_ids.end(); ++fleet_ids_it) {
1255 fleet_iterator it = this->fleets.find(*fleet_ids_it);
1256
1257 if (it != this->fleets.end()) {
1258 // Initialize fleet object
1259 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
1260
1261 if (f->fleet_selectivity_id_m == static_cast<Type>(-999)) {
1262 valid_model = false;
1264 "No selectivity pattern defined for fleet " +
1265 fims::to_string(f->id) +
1266 ". FIMS requires selectivity be defined for all fleets "
1267 "when running a catch at age model.");
1268 }
1269 }
1270 }
1271
1272 if (p->recruitment_id == static_cast<Type>(-999)) {
1273 valid_model = false;
1275 "No recruitment function defined for population " +
1276 fims::to_string(p->id) +
1277 ". FIMS requires recruitment functions be defined for all "
1278 "populations when running a catch at age model.");
1279 }
1280
1281 std::shared_ptr<fims_popdy::RecruitmentBase<Type>> r =
1282 p->recruitment;
1283 r = p->recruitment;
1284 if (r->process_id == static_cast<Type>(-999)) {
1285 valid_model = false;
1287 "No recruitment process function defined for population " +
1288 fims::to_string(p->id) +
1289 ". FIMS requires recruitment process functions be defined "
1290 "for all "
1291 "recruitments when running a catch at age model.");
1292 }
1293
1294 if (p->growth_id == static_cast<Type>(-999)) {
1295 valid_model = false;
1297 "No growth function defined for population " +
1298 fims::to_string(p->id) +
1299 ". FIMS requires growth functions be defined for all "
1300 "populations when running a catch at age model.");
1301 }
1302
1303 if (p->maturity_id == static_cast<Type>(-999)) {
1304 valid_model = false;
1305
1307 "No maturity function defined for population " +
1308 fims::to_string(p->id) +
1309 ". FIMS requires maturity functions be defined for all "
1310 "populations when running a catch at age model.");
1311 }
1312 }
1313 }
1314 }
1315 }
1316 return valid_model;
1317 }
1318};
1319
1320template <typename Type>
1321std::shared_ptr<Information<Type>> Information<Type>::fims_information =
1322 nullptr;
1323
1324} // namespace fims_info
1325
1326#endif /* FIMS_COMMON_INFORMATION_HPP */
Definition fims_vector.hpp:27
void emplace_back(Args &&...args)
Constructs an element in-place at the end.
Definition fims_vector.hpp:389
size_type size() const
Returns the number of elements.
Definition fims_vector.hpp:299
Stores FIMS model information and creates model. Contains all objects and data pre-model construction...
Definition information.hpp:40
fims::Vector< fims::Vector< double > > PrepareFleetObservationBinEdges(const std::shared_ptr< fims_popdy::Population< Type > > &p)
Build canonical fleet observation-bin edge vectors from fleet length_bin lower edges.
Definition information.hpp:673
std::map< uint32_t, std::shared_ptr< fims_popdy::GrowthBase< Type > > >::iterator growth_models_iterator
Definition information.hpp:96
void SetupRandomEffects()
Loop over distributions and set links to distribution x value if distribution is a random effects typ...
Definition information.hpp:338
std::map< uint32_t, std::shared_ptr< fims_popdy::Population< Type > > > populations
Definition information.hpp:118
std::unordered_map< uint32_t, std::shared_ptr< fims_popdy::FisheryModelBase< Type > > > models_map
Definition information.hpp:139
void RegisterRandomEffectName(std::string re_name)
Register a random effects name.
Definition information.hpp:302
std::map< uint32_t, std::shared_ptr< fims_data_object::DataObject< Type > > >::iterator data_iterator
Definition information.hpp:63
std::vector< Type * > & GetFixedEffectsParameters()
Get the Fixed Effects Parameters object.
Definition information.hpp:1217
std::vector< Type * > random_effects_parameters
Definition information.hpp:49
void SetFleetIndexData(bool &valid_model, std::shared_ptr< fims_popdy::Fleet< Type > > f)
Set pointers to index data in the fleet module.
Definition information.hpp:424
void SetGrowth(bool &valid_model, std::shared_ptr< fims_popdy::Population< Type > > p)
Set pointers to the growth module referenced in the population module.
Definition information.hpp:882
std::map< uint32_t, std::shared_ptr< fims_popdy::RecruitmentBase< Type > > > recruitment_process_models
Definition information.hpp:75
void EnforcePopulationGridNotCoarserThanFleetBins(const fims_popdy::SizeGrid &size_grid, const fims::Vector< fims::Vector< double > > &fleet_edges)
Enforce that biological size bins are not coarser than overlapping active fleet observation bins.
Definition information.hpp:719
void SetMaturity(bool &valid_model, std::shared_ptr< fims_popdy::Population< Type > > p)
Set pointers to the maturity module referenced in the population module.
Definition information.hpp:958
std::map< uint32_t, std::shared_ptr< fims_popdy::Fleet< Type > > >::iterator fleet_iterator
Definition information.hpp:113
void EnsurePopulationSizeGrid(bool &valid_model, std::shared_ptr< fims_popdy::Population< Type > > p)
Ensure a population has a usable biological size grid.
Definition information.hpp:780
void SetDataObjects(bool &valid_model)
Loop over all density components and set pointers to data objects.
Definition information.hpp:1015
size_t n_years
Definition information.hpp:42
std::map< uint32_t, std::shared_ptr< fims_popdy::Fleet< Type > > > fleets
Definition information.hpp:109
void CreatePopulationObjects(bool &valid_model)
Loop over all populations and set pointers to population objects.
Definition information.hpp:1056
std::map< uint32_t, std::shared_ptr< fims_popdy::GrowthBase< Type > > > growth_models
Definition information.hpp:91
void SetLengthCompositionData(bool &valid_model, std::shared_ptr< fims_popdy::Fleet< Type > > f)
Set pointers to length composition data in the fleet module.
Definition information.hpp:478
void SetFleetSelectivityModel(bool &valid_model, std::shared_ptr< fims_popdy::Fleet< Type > > f)
Set pointers to the selectivity module referenced in the fleet module.
Definition information.hpp:506
std::map< uint32_t, std::shared_ptr< fims_popdy::Population< Type > > >::iterator population_iterator
Definition information.hpp:123
void RegisterParameter(Type &p)
Register a parameter as estimable.
Definition information.hpp:275
std::map< uint32_t, std::shared_ptr< fims_distributions::DensityComponentBase< Type > > > density_components
Definition information.hpp:129
void RegisterRandomEffect(Type &re)
Register a random effect as estimable.
Definition information.hpp:284
void SetRecruitment(bool &valid_model, std::shared_ptr< fims_popdy::Population< Type > > p)
Set pointers to the recruitment module referenced in the population module.
Definition information.hpp:594
void SetNages(size_t n_ages)
Set the Nages object.
Definition information.hpp:1189
size_t GetNages() const
Get the Nages object.
Definition information.hpp:1182
std::unordered_map< uint32_t, fims::Vector< Type > * > variable_map
Definition information.hpp:146
void SetNyears(size_t n_years)
Set the n_years object.
Definition information.hpp:1203
std::map< uint32_t, std::shared_ptr< fims_popdy::RecruitmentBase< Type > > >::iterator recruitment_models_iterator
Definition information.hpp:71
void SetRecruitmentProcess(bool &valid_model, std::shared_ptr< fims_popdy::Population< Type > > p)
Set pointers to the recruitment process module referenced in the population module.
Definition information.hpp:632
bool CheckModel()
Checks to make sure all required modules are present for specified model.
Definition information.hpp:1237
std::map< uint32_t, std::shared_ptr< fims_popdy::SelectivityBase< Type > > > selectivity_models
Definition information.hpp:83
bool CreateModel()
Create the generalized stock assessment model that will evaluate the objective function....
Definition information.hpp:1151
void Clear()
Clears all containers.
Definition information.hpp:182
size_t n_ages
Definition information.hpp:43
std::unordered_map< uint32_t, std::shared_ptr< fims_popdy::FisheryModelBase< Type > > >::iterator model_map_iterator
Definition information.hpp:143
std::map< uint32_t, std::shared_ptr< fims_distributions::DensityComponentBase< Type > > >::iterator density_components_iterator
Definition information.hpp:134
void SetAgeCompositionData(bool &valid_model, std::shared_ptr< fims_popdy::Fleet< Type > > f)
Set pointers to age composition data in the fleet module.
Definition information.hpp:451
std::vector< Type * > parameters
Definition information.hpp:47
void SetFleetAgeToLengthConversionModel(bool &valid_model, std::shared_ptr< fims_popdy::Population< Type > > p, std::shared_ptr< fims_popdy::Fleet< Type > > f)
Set the age-to-length conversion module referenced by the fleet and population modules.
Definition information.hpp:542
void CreateFleetObjects(bool &valid_model)
Loop over all fleets and set pointers to fleet objects.
Definition information.hpp:991
static std::shared_ptr< Information< Type > > fims_information
Definition information.hpp:46
std::vector< std::string > parameter_names
Definition information.hpp:52
std::map< uint32_t, std::shared_ptr< fims_popdy::MaturityBase< Type > > > maturity_models
Definition information.hpp:100
void SetFleetCatchData(bool &valid_model, std::shared_ptr< fims_popdy::Fleet< Type > > f)
Set pointers to catch data in the fleet module.
Definition information.hpp:397
void ConfigureGrowthDerivedSizeProvider(std::shared_ptr< fims_popdy::Population< Type > > p, std::shared_ptr< fims_popdy::GrowthDerivedObservationBase< Type > > growth_observation)
Configure the growth-derived size provider for a population.
Definition information.hpp:860
std::vector< Type * > & GetRandomEffectsParameters()
Get the Random Effects Parameters object.
Definition information.hpp:1226
std::vector< std::string > random_effects_names
Definition information.hpp:55
std::vector< Type * > & GetParameters()
Get the Parameters object.
Definition information.hpp:1210
std::map< uint32_t, std::shared_ptr< fims_popdy::RecruitmentBase< Type > > >::iterator recruitment_process_iterator
Definition information.hpp:79
void SetupPriors()
Loop over distributions and set links to distribution x value if distribution is a prior type.
Definition information.hpp:310
size_t GetNyears() const
Get the n_years object.
Definition information.hpp:1196
std::unordered_map< uint32_t, fims::Vector< Type > * >::iterator variable_map_iterator
Definition information.hpp:149
std::map< uint32_t, std::shared_ptr< fims_popdy::SelectivityBase< Type > > >::iterator selectivity_models_iterator
Definition information.hpp:87
void RegisterParameterName(std::string p_name)
Register a parameter name.
Definition information.hpp:293
void SetupData()
Loop over distributions and set links to distribution expected value if distribution is a data type.
Definition information.hpp:369
std::map< uint32_t, std::shared_ptr< fims_popdy::MaturityBase< Type > > >::iterator maturity_models_iterator
Definition information.hpp:104
std::string State()
Get a summary string of the Information object state.
Definition information.hpp:227
static std::shared_ptr< Information< Type > > GetInstance()
Returns a singleton Information object for type T.
Definition information.hpp:262
void CreateModelingObjects(bool &valid_model)
Loop over all models and set pointers to population objects.
Definition information.hpp:1110
std::map< uint32_t, std::shared_ptr< fims_popdy::RecruitmentBase< Type > > > recruitment_models
Definition information.hpp:67
std::vector< Type * > fixed_effects_parameters
Definition information.hpp:51
std::map< uint32_t, std::shared_ptr< fims_data_object::DataObject< Type > > > data_objects
Definition information.hpp:60
Generic capability interface for growth models that can feed the growth-derived age-to-length convers...
Definition growth_model_adapter.hpp:26
Platform macros and the core FIMS logging system.
#define FIMS_WARNING_LOG(MESSAGE)
Definition def.hpp:648
#define FIMS_INFO_LOG(MESSAGE)
Record an info-log entry with metadata.
Definition def.hpp:648
std::string to_string(T v)
Definition def.hpp:735
#define FIMS_ERROR_LOG(MESSAGE)
Definition def.hpp:664
This distributions module includes any .hpp files within the subfolders so that only this file needs ...
Establishes the FIMS Vector class.
Defines the base class for all fishery models within the FIMS framework.
Declare the fleet functor class which is the base class for all fleet functors.
Includes any .hpp files within the subfolders so that only this file needs to included in include sta...
Defines a size provider that reads mean growth outputs and prepares population-level size probabiliti...
Definition of the FIMSObject structure.
std::shared_ptr< AgeToLengthConversionBase< Type > > BuildAgeToLengthConversionFleet(const std::shared_ptr< Population< Type > > &population, const std::shared_ptr< Fleet< Type > > &fleet)
Build the active age-to-length conversion for a fleet from the current population and fleet state.
Definition runtime.hpp:44
Defines the Population class and its fields and methods.
Includes any .hpp files within the subfolders so that only this file needs to included in include sta...
Shared runtime helpers for constructing and validating fleet age-to-length conversions.
Includes any .hpp files within the subfolders so that only this file needs to included in include sta...
Defines helpers for constructing population-level biological size grids.
Base class for all fleets.
Definition fleet.hpp:26
Population class. Contains subpopulations that are divided into generic partitions (e....
Definition population.hpp:27
static fims::Vector< double > BuildObservationEdgesFromLowerEdges(const fims::Vector< double > &lower_edges)
Build one fleet observation-bin edge vector from stored bin lower edges.
Definition size_grid_builder.hpp:112
static SizeGrid BuildDefaultFromFleetEdges(const fims::Vector< fims::Vector< double > > &fleet_edges)
Build the default population biological size grid from resolved fleet observation-bin edges.
Definition size_grid_builder.hpp:155
Population-level biological size grid.
Definition size_grid.hpp:26
bool IsConsistent() const
Return whether the grid dimensions and geometry are internally consistent.
Definition size_grid.hpp:80
fims::Vector< double > edges
Definition size_grid.hpp:28
std::size_t n_bins
Definition size_grid.hpp:27