FIMS  v0.11.0
Loading...
Searching...
No Matches
information.hpp
Go to the documentation of this file.
1
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>
41 public:
42 size_t n_years = 0;
43 size_t n_ages = 0;
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>
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
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
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
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
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
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
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
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
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
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
145 std::unordered_map<uint32_t, fims::Vector<Type>*>
148 typedef typename std::unordered_map<uint32_t, fims::Vector<Type>*>::iterator
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;
577 "Fleet " + fims::to_string(f->id) +
578 " has fleet length observation bins but no usable "
579 "age-to-length conversion path. Provide fixed "
580 "age-to-length conversion of size " +
581 fims::to_string(f->n_ages * f->n_lengths) +
582 " or use a supported growth-derived age-to-length conversion path.");
583 }
584
593 void SetRecruitment(bool& valid_model,
594 std::shared_ptr<fims_popdy::Population<Type>> p) {
595 if (p->recruitment_id != static_cast<Type>(-999)) {
596 uint32_t recruitment_uint = static_cast<uint32_t>(p->recruitment_id);
597
599 this->recruitment_models.find(recruitment_uint);
600
601 if (it != this->recruitment_models.end()) {
602 p->recruitment = (*it).second; // recruitment defined in population.hpp
603 FIMS_INFO_LOG("Recruitment model " + fims::to_string(recruitment_uint) +
604 " successfully set to population " +
605 fims::to_string(p->id));
606 } else {
607 valid_model = false;
609 "Expected recruitment function not defined for "
610 "population " +
611 fims::to_string(p->id) + ", recruitment function " +
612 fims::to_string(recruitment_uint));
613 }
614 } else {
616 "No recruitment function defined for population " +
617 fims::to_string(p->id) +
618 ". FIMS requires recruitment functions be defined for all "
619 "populations when running a catch at age model.");
620 }
621 }
622
631 void SetRecruitmentProcess(bool& valid_model,
632 std::shared_ptr<fims_popdy::Population<Type>> p) {
633 std::shared_ptr<fims_popdy::RecruitmentBase<Type>> r = p->recruitment;
634 // if recruitment is defined
635 if (r) {
636 if (r->process_id != static_cast<Type>(-999)) {
637 uint32_t process_uint = static_cast<uint32_t>(r->process_id);
639 this->recruitment_process_models.find(process_uint);
640
641 if (it != this->recruitment_process_models.end()) {
642 r->process = (*it).second; // recruitment process
644 "Recruitment Process model " + fims::to_string(process_uint) +
645 " successfully set to population " + fims::to_string(p->id));
646 (*it).second->recruitment = r;
647 } else {
648 valid_model = false;
650 "Expected recruitment process function not defined for "
651 "population " +
652 fims::to_string(p->id) + ", recruitment process function " +
653 fims::to_string(process_uint));
654 }
655 } else {
657 "No recruitment process function defined for population " +
658 fims::to_string(p->id) +
659 ". FIMS requires recruitment process functions be defined for all "
660 "recruitments when running a catch at age model.");
661 }
662 }
663 }
664
673 const std::shared_ptr<fims_popdy::Population<Type>>& p) {
675
676 for (std::size_t fleet_index = 0; fleet_index < p->fleets.size();
677 ++fleet_index) {
678 const std::shared_ptr<fims_popdy::Fleet<Type>>& fleet =
679 p->fleets[fleet_index];
680
681 if (fleet == nullptr) {
682 continue;
683 }
684
685 if (!fleet->requires_age_length_mapping || fleet->n_lengths == 0) {
686 fleet->length_bin_edges = fims::Vector<double>();
687 continue;
688 }
689
690 if (fleet->lengths.size() != fleet->n_lengths) {
691 throw std::runtime_error(
692 "Fleet length_bin centers are not consistent with n_lengths");
693 }
694
695 fleet->length_bin_edges =
697 fleet->lengths);
698
699 fleet_edges.emplace_back(fleet->length_bin_edges);
700 }
701
702 return fleet_edges;
703 }
704
719 const fims_popdy::SizeGrid& size_grid,
720 const fims::Vector<fims::Vector<double>>& fleet_edges) {
721 if (!size_grid.IsConsistent() || size_grid.n_bins == 0 ||
722 fleet_edges.size() == 0) {
723 return;
724 }
725
726 for (std::size_t population_bin_index = 0;
727 population_bin_index < size_grid.n_bins; ++population_bin_index) {
728 const double population_left = size_grid.edges[population_bin_index];
729 const double population_right = size_grid.edges[population_bin_index + 1];
730 const double population_bin_width = population_right - population_left;
731 const double population_tolerance =
732 1e-12 * (population_bin_width > 1.0 ? population_bin_width : 1.0);
733
734 for (std::size_t fleet_index = 0; fleet_index < fleet_edges.size();
735 ++fleet_index) {
736 const fims::Vector<double>& edges = fleet_edges[fleet_index];
737
738 for (std::size_t fleet_bin_index = 1; fleet_bin_index < edges.size();
739 ++fleet_bin_index) {
740 const double fleet_left = edges[fleet_bin_index - 1];
741 const double fleet_right = edges[fleet_bin_index];
742 const double overlap_left = std::max(population_left, fleet_left);
743 const double overlap_right = std::min(population_right, fleet_right);
744
745 if (!(overlap_right > overlap_left)) {
746 continue;
747 }
748
749 const double fleet_bin_width = fleet_right - fleet_left;
750 if (population_bin_width > fleet_bin_width + population_tolerance) {
751 throw std::runtime_error(
752 "Population biological size grid contains at least one bin "
753 "that is coarser than an overlapping active fleet observation "
754 "bin. Provide a finer biological size-grid override or correct "
755 "the fleet bin setup.");
756 }
757 }
758 }
759 }
760 }
761
780 bool& valid_model, std::shared_ptr<fims_popdy::Population<Type>> p) {
782
783 try {
784 fleet_edges = PrepareFleetObservationBinEdges(p);
785 } catch (const std::exception& e) {
786 valid_model = false;
788 "Failed to prepare fleet observation-bin geometry for population " +
789 fims::to_string(p->id) + ": " + e.what());
790 return;
791 }
792
793 if (p->size_grid.IsConsistent() && p->size_grid.n_bins > 0) {
794 try {
795 EnforcePopulationGridNotCoarserThanFleetBins(p->size_grid, fleet_edges);
796 } catch (const std::exception& e) {
797 valid_model = false;
799 "Population " + fims::to_string(p->id) +
800 " has a biological size grid that is incompatible with active "
801 "fleet observation bins: " +
802 e.what());
803 }
804 return;
805 }
806
807 const bool size_grid_missing = p->size_grid.n_bins == 0 &&
808 p->size_grid.edges.size() == 0 &&
809 p->size_grid.centers.size() == 0;
810
811 if (size_grid_missing) {
812 try {
813 if (fleet_edges.size() == 0) {
814 throw std::runtime_error(
815 "No resolvable fleet observation-bin geometry was available "
816 "to build the default biological size grid");
817 }
818
820 fleet_edges);
821 EnforcePopulationGridNotCoarserThanFleetBins(p->size_grid, fleet_edges);
822
823 const std::size_t regular_bin_count =
824 p->size_grid.n_bins > 0 ? p->size_grid.n_bins - 1 : 0;
825
826 if (regular_bin_count > 200) {
828 "Built-in default biological size grid created more than 200 "
829 "regular bins for population " +
830 fims::to_string(p->id) +
831 ". This may slow model evaluation. Consider providing a "
832 "biological size-grid override if needed.");
833 }
834
835 } catch (const std::exception& e) {
836 valid_model = false;
838 "Failed to initialize default population size grid for "
839 "population " +
840 fims::to_string(p->id) + ": " + e.what());
841 }
842 return;
843 }
844
845 valid_model = false;
847 "Population " + fims::to_string(p->id) +
848 " has an invalid biological size grid. Provide a consistent override "
849 "or leave the grid empty so FIMS can build the default.");
850 }
851
860 std::shared_ptr<fims_popdy::Population<Type>> p,
862 growth_observation) {
863 std::shared_ptr<fims_popdy::GrowthDerivedSizeProvider<Type>> size_provider =
864 std::make_shared<fims_popdy::GrowthDerivedSizeProvider<Type>>();
865
866 size_provider->SetGrowth(growth_observation);
867 size_provider->SetPopulationDimensions(p->n_years, p->n_ages);
868 size_provider->SetPopulationSizeGrid(&(p->size_grid));
869
870 p->size_distribution_provider = size_provider;
871 }
872
881 void SetGrowth(bool& valid_model,
882 std::shared_ptr<fims_popdy::Population<Type>> p) {
883 if (p->growth_id != static_cast<Type>(-999)) {
884 uint32_t growth_uint = static_cast<uint32_t>(p->growth_id);
886 growth_uint); // growth_models is specified in information.hpp
887 // and used in rcpp
888 // at the head of information.hpp; are the
889 // dimensions of ages defined in rcpp or where?
890 if (it != this->growth_models.end()) {
891 p->growth =
892 (*it).second; // growth defined in population.hpp (the object
893 // is called p, growth is within p)
895 growth_observation = std::dynamic_pointer_cast<
897 p->growth)) {
898 growth_observation->Initialize(p->n_years, p->n_ages, 1);
899
900 if (p->ages.size() > 0) {
901 double min_age = p->ages[0];
902 for (size_t i = 1; i < p->ages.size(); ++i) {
903 if (p->ages[i] < min_age) {
904 min_age = p->ages[i];
905 }
906 }
907 growth_observation->SetAgeOffset(static_cast<double>(min_age));
908 }
909
910 const bool population_has_size_grid_input =
911 p->size_grid.n_bins > 0 || p->size_grid.edges.size() > 0 ||
912 p->size_grid.centers.size() > 0;
913
914 bool any_length_based_fleet = false;
915 for (std::size_t i = 0; i < p->fleets.size(); ++i) {
916 if (p->fleets[i] != nullptr &&
917 p->fleets[i]->requires_age_length_mapping &&
918 p->fleets[i]->n_lengths > 0) {
919 any_length_based_fleet = true;
920 break;
921 }
922 }
923
924 if (population_has_size_grid_input || any_length_based_fleet) {
925 EnsurePopulationSizeGrid(valid_model, p);
926 if (!valid_model) {
927 return;
928 }
929 ConfigureGrowthDerivedSizeProvider(p, growth_observation);
930 }
931 }
932 FIMS_INFO_LOG("Growth model " + fims::to_string(growth_uint) +
933 " successfully set to population " +
934 fims::to_string(p->id));
935 } else {
936 valid_model = false;
937 FIMS_ERROR_LOG("Expected growth function not defined for population " +
938 fims::to_string(p->id) + ", growth function " +
939 fims::to_string(growth_uint));
940 }
941 } else {
942 FIMS_WARNING_LOG("Growth function undefined for population " +
943 fims::to_string(p->id) +
944 ". FIMS requires growth functions be defined for all "
945 "populations when running a catch at age model.");
946 }
947 }
948
957 void SetMaturity(bool& valid_model,
958 std::shared_ptr<fims_popdy::Population<Type>> p) {
959 if (p->maturity_id != static_cast<Type>(-999)) {
960 uint32_t maturity_uint = static_cast<uint32_t>(p->maturity_id);
962 maturity_uint); // >maturity_models is specified in
963 // information.hpp and used in rcpp
964 if (it != this->maturity_models.end()) {
965 p->maturity = (*it).second; // >maturity defined in population.hpp
966 FIMS_INFO_LOG("Maturity model " + fims::to_string(maturity_uint) +
967 " successfully set to population " +
968 fims::to_string(p->id));
969 } else {
970 valid_model = false;
972 "Expected maturity function not defined for population " +
973 fims::to_string(p->id) + ", maturity function " +
974 fims::to_string(maturity_uint));
975 }
976 } else {
977 FIMS_WARNING_LOG("Maturity function undefined for population " +
978 fims::to_string(p->id) +
979 ". FIMS requires maturity functions be defined for all "
980 "populations when running a catch at age model.");
981 }
982 }
983
990 void CreateFleetObjects(bool& valid_model) {
991 for (fleet_iterator it = this->fleets.begin(); it != this->fleets.end();
992 ++it) {
993 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
994 FIMS_INFO_LOG("Initializing fleet " + fims::to_string(f->id));
995
996 SetFleetCatchData(valid_model, f);
997
998 SetFleetIndexData(valid_model, f);
999
1000 SetAgeCompositionData(valid_model, f);
1001
1002 SetLengthCompositionData(valid_model, f);
1003
1004 SetFleetSelectivityModel(valid_model, f);
1005 }
1006 }
1007
1014 void SetDataObjects(bool& valid_model) {
1015 for (density_components_iterator it = this->density_components.begin();
1016 it != this->density_components.end(); ++it) {
1017 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
1018 (*it).second;
1019
1020 // set data objects if distribution is a data type
1021 if (d->input_type == "data") {
1022 if (d->observed_data_id_m != static_cast<Type>(-999)) {
1023 uint32_t observed_data_id =
1024 static_cast<uint32_t>(d->observed_data_id_m);
1025 data_iterator it = this->data_objects.find(observed_data_id);
1026
1027 if (it != this->data_objects.end()) {
1028 d->data_observed_values = (*it).second;
1029 FIMS_INFO_LOG("Observed data " + fims::to_string(observed_data_id) +
1030 " successfully set to density component " +
1031 fims::to_string(d->id));
1032 } else {
1033 valid_model = false;
1035 "Expected data observations not defined for density "
1036 "component " +
1037 fims::to_string(d->id) + ", observed data " +
1038 fims::to_string(observed_data_id));
1039 }
1040 } else {
1041 valid_model = false;
1042 FIMS_ERROR_LOG("No data input for density component" +
1043 fims::to_string(d->id));
1044 }
1045 }
1046 }
1047 }
1048
1055 void CreatePopulationObjects(bool& valid_model) {
1056 for (population_iterator it = this->populations.begin();
1057 it != this->populations.end(); ++it) {
1058 std::shared_ptr<fims_popdy::Population<Type>> p = (*it).second;
1059
1060 FIMS_INFO_LOG("Initializing population " + fims::to_string(p->id));
1061 // check if population has fleets
1062 typename std::set<uint32_t>::iterator fleet_ids_it;
1063
1064 for (fleet_ids_it = p->fleet_ids.begin();
1065 fleet_ids_it != p->fleet_ids.end(); ++fleet_ids_it) {
1066 // error check and set population elements
1067 // check me - add another fleet iterator to push information from
1068 // for (fleet_iterator it = this->fleets.begin(); it !=
1069 // this->fleets.end();
1070 // ++it) {
1071
1072 fleet_iterator it = this->fleets.find(*fleet_ids_it);
1073
1074 if (it != this->fleets.end()) {
1075 // Initialize fleet object
1076 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
1077 // population to the individual fleets This is to pass catch at age
1078 // from population to fleets?
1079 // any shared member in p (population is pushed into fleets)
1080 p->fleets.push_back(f);
1081 } else {
1082 valid_model = false;
1083 FIMS_ERROR_LOG("Fleet \"" + fims::to_string(*fleet_ids_it) +
1084 "\" undefined, not found for Population \"" +
1085 fims::to_string(p->id) + "\". ");
1086 }
1087 }
1088
1089 // set information dimensions
1090 this->n_years = std::max(this->n_years, p->n_years);
1091 this->n_ages = std::max(this->n_ages, p->n_ages);
1092
1093 SetRecruitment(valid_model, p);
1094
1095 SetRecruitmentProcess(valid_model, p);
1096
1097 SetGrowth(valid_model, p);
1098 for (size_t i = 0; i < p->fleets.size(); ++i) {
1099 SetFleetAgeToLengthConversionModel(valid_model, p, p->fleets[i]);
1100 }
1101
1102 SetMaturity(valid_model, p);
1103 }
1104 }
1105
1109 void CreateModelingObjects(bool& valid_model) {
1110 for (model_map_iterator it = this->models_map.begin();
1111 it != this->models_map.end(); ++it) {
1112 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>& model = (*it).second;
1113 std::set<uint32_t>::iterator jt;
1114
1115 for (jt = model->population_ids.begin();
1116 jt != model->population_ids.end(); ++jt) {
1117 population_iterator pt = this->populations.find((*jt));
1118
1119 if (pt != this->populations.end()) {
1120 std::shared_ptr<fims_popdy::Population<Type>> p = (*pt).second;
1121 model->populations.push_back(p);
1122 for (size_t i = 0; i < p->fleets.size(); i++) {
1123 uint32_t local_fleet_id = p->fleets[i]->GetId();
1124 model->fleets[local_fleet_id] = p->fleets[i];
1125 FIMS_INFO_LOG(std::string("Linked fleet id ") +
1126 fims::to_string(local_fleet_id) +
1127 std::string(" into model id ") +
1128 fims::to_string(model->GetId()));
1129 }
1130 } else {
1131 valid_model = false;
1132 FIMS_ERROR_LOG("No population object defined for model " +
1133 fims::to_string(model->GetId()));
1134 }
1135 }
1136 model->Initialize();
1137 }
1138 }
1139
1151 FIMS_INFO_LOG("Creating model and checking for required components...");
1152 bool valid_model = true;
1153
1154 CreateFleetObjects(valid_model);
1155
1156 SetDataObjects(valid_model);
1157
1158 CreatePopulationObjects(valid_model);
1159
1160 CreateModelingObjects(valid_model);
1161
1162 // setup priors, random effect, and data density components
1163 SetupPriors();
1165 SetupData();
1166
1167 if (valid_model) {
1168 FIMS_INFO_LOG("Model successfully created.");
1169 } else {
1170 FIMS_ERROR_LOG("Model creation failed.");
1171 }
1172
1173 return valid_model;
1174 }
1175
1181 size_t GetNages() const { return n_ages; }
1182
1188 void SetNages(size_t n_ages) { this->n_ages = n_ages; }
1189
1195 size_t GetNyears() const { return n_years; }
1196
1202 void SetNyears(size_t n_years) { this->n_years = n_years; }
1203
1209 std::vector<Type*>& GetParameters() { return parameters; }
1210
1216 std::vector<Type*>& GetFixedEffectsParameters() {
1218 }
1219
1225 std::vector<Type*>& GetRandomEffectsParameters() {
1227 }
1228
1236 bool CheckModel() {
1237 bool valid_model = true;
1238 for (model_map_iterator it = this->models_map.begin();
1239 it != this->models_map.end(); ++it) {
1240 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>& model = (*it).second;
1241 std::set<uint32_t>::iterator jt;
1242
1243 for (jt = model->population_ids.begin();
1244 jt != model->population_ids.end(); ++jt) {
1245 population_iterator pt = this->populations.find((*jt));
1246
1247 if (pt != this->populations.end()) {
1248 std::shared_ptr<fims_popdy::Population<Type>> p = (*pt).second;
1249
1250 if (model->model_type_m == "caa") {
1251 typename std::set<uint32_t>::iterator fleet_ids_it;
1252 for (fleet_ids_it = p->fleet_ids.begin();
1253 fleet_ids_it != p->fleet_ids.end(); ++fleet_ids_it) {
1254 fleet_iterator it = this->fleets.find(*fleet_ids_it);
1255
1256 if (it != this->fleets.end()) {
1257 // Initialize fleet object
1258 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
1259
1260 if (f->fleet_selectivity_id_m == static_cast<Type>(-999)) {
1261 valid_model = false;
1263 "No selectivity pattern defined for fleet " +
1264 fims::to_string(f->id) +
1265 ". FIMS requires selectivity be defined for all fleets "
1266 "when running a catch at age model.");
1267 }
1268 }
1269 }
1270
1271 if (p->recruitment_id == static_cast<Type>(-999)) {
1272 valid_model = false;
1274 "No recruitment function defined for population " +
1275 fims::to_string(p->id) +
1276 ". FIMS requires recruitment functions be defined for all "
1277 "populations when running a catch at age model.");
1278 }
1279
1280 std::shared_ptr<fims_popdy::RecruitmentBase<Type>> r =
1281 p->recruitment;
1282 r = p->recruitment;
1283 if (r->process_id == static_cast<Type>(-999)) {
1284 valid_model = false;
1286 "No recruitment process function defined for population " +
1287 fims::to_string(p->id) +
1288 ". FIMS requires recruitment process functions be defined "
1289 "for all "
1290 "recruitments when running a catch at age model.");
1291 }
1292
1293 if (p->growth_id == static_cast<Type>(-999)) {
1294 valid_model = false;
1296 "No growth function defined for population " +
1297 fims::to_string(p->id) +
1298 ". FIMS requires growth functions be defined for all "
1299 "populations when running a catch at age model.");
1300 }
1301
1302 if (p->maturity_id == static_cast<Type>(-999)) {
1303 valid_model = false;
1304
1306 "No maturity function defined for population " +
1307 fims::to_string(p->id) +
1308 ". FIMS requires maturity functions be defined for all "
1309 "populations when running a catch at age model.");
1310 }
1311 }
1312 }
1313 }
1314 }
1315 return valid_model;
1316 }
1317};
1318
1319template <typename Type>
1320std::shared_ptr<Information<Type>> Information<Type>::fims_information =
1321 nullptr;
1323} // namespace fims_info
1324
1325#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 centers.
Definition information.hpp:672
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:1216
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:881
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:718
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:957
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:779
void SetDataObjects(bool &valid_model)
Loop over all density components and set pointers to data objects.
Definition information.hpp:1014
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:1055
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:593
void SetNages(size_t n_ages)
Set the Nages object.
Definition information.hpp:1188
size_t GetNages() const
Get the Nages object.
Definition information.hpp:1181
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:1202
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:631
bool CheckModel()
Checks to make sure all required modules are present for specified model.
Definition information.hpp:1236
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:1150
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:990
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:859
std::vector< Type * > & GetRandomEffectsParameters()
Get the Random Effects Parameters object.
Definition information.hpp:1225
std::vector< std::string > random_effects_names
Definition information.hpp:55
std::vector< Type * > & GetParameters()
Get the Parameters object.
Definition information.hpp:1209
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:1195
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:1109
static std::shared_ptr< Information< Type > > fims_information
Definition information.hpp:46
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:636
#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 > BuildObservationEdgesFromCenters(const fims::Vector< double > &centers)
Build one fleet observation-bin edge vector from stored bin centers.
Definition size_grid_builder.hpp:107
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:160
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