FIMS  v0.10.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
203 it != density_components.end(); ++it) {
204 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
205 (*it).second;
206 if ((d->priors)[0]) {
207 d->priors.clear();
208 }
209 if (d->data_observed_values) {
210 d->data_observed_values.reset();
211 }
212 if (d->data_expected_values) {
213 d->data_expected_values->clear();
214 }
215 if (d->re) {
216 d->re->clear();
217 }
218 if (d->re_expected_values) {
219 d->re_expected_values->clear();
220 }
221 }
222 this->density_components.clear();
223 }
224
234 std::string State() {
235 std::stringstream ss;
236 ss << "Information object State:\n";
237 ss << "data_objects: " << this->data_objects.clear();
238 ss << "populations: " << this->populations.size() << std::endl;
239 ss << "fixed_effects_parameters: " << this->fixed_effects_parameters.size()
240 << std::endl;
241 ss << "fleets: " << this->fleets.size() << std::endl;
242 ss << "growth_models: " << this->growth_models.size() << std::endl;
243 ss << "maturity_models: " << this->maturity_models.size() << std::endl;
244 ss << "parameter_names: " << this->parameter_names.size() << std::endl;
245 ss << "parameters: " << this->parameters.size() << std::endl;
246 ss << "random_effects_names: " << this->random_effects_names.size()
247 << std::endl;
248 ss << "random_effects_parameters: "
249 << this->random_effects_parameters.size() << std::endl;
250 ss << "recruitment_models: " << this->recruitment_models.size()
251 << std::endl;
252 ss << "recruitment_process_models: "
253 << this->recruitment_process_models.size() << std::endl;
254 ss << "selectivity_models: " << this->selectivity_models.size()
255 << std::endl;
256 ss << "models_map: " << this->models_map.size() << std::endl;
257 ss << "n_years: " << this->n_years << std::endl;
258 ss << "n_ages: " << this->n_ages << std::endl;
259 ss << "density_components: " << this->density_components.size()
260 << std::endl;
261 return ss.str();
262 }
263
269 static std::shared_ptr<Information<Type>> GetInstance() {
272 std::make_shared<fims_info::Information<Type>>();
273 }
275 }
276
282 void RegisterParameter(Type& p) {
283 this->fixed_effects_parameters.push_back(&p);
284 }
285
291 void RegisterRandomEffect(Type& re) {
292 this->random_effects_parameters.push_back(&re);
293 }
294
300 void RegisterParameterName(std::string p_name) {
301 this->parameter_names.push_back(p_name);
302 }
303
309 void RegisterRandomEffectName(std::string re_name) {
310 this->random_effects_names.push_back(re_name);
311 }
312
317 void SetupPriors() {
319 it != density_components.end(); ++it) {
320 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
321 (*it).second;
322 if (d->input_type == "prior") {
323 FIMS_INFO_LOG("Setup prior for distribution " + fims::to_string(d->id));
325 FIMS_INFO_LOG("Link prior from distribution " + fims::to_string(d->id) +
326 " to parameter " + fims::to_string(d->key[0]));
327 d->priors.resize(d->key.size());
328 for (size_t i = 0; i < d->key.size(); i++) {
329 FIMS_INFO_LOG("Link prior from distribution " +
330 fims::to_string(d->id) + " to parameter " +
331 fims::to_string(d->key[0]));
332 vmit = this->variable_map.find(d->key[i]);
333 d->priors[i] = (*vmit).second;
334 }
335 FIMS_INFO_LOG("Prior size for distribution " + fims::to_string(d->id) +
336 "is: " + fims::to_string(d->observed_values.size()));
337 }
338 }
339 }
340
346 for (density_components_iterator it = this->density_components.begin();
347 it != this->density_components.end(); ++it) {
348 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
349 (*it).second;
350 if (d->input_type == "random_effects") {
351 FIMS_INFO_LOG("Setup random effects for distribution " +
352 fims::to_string(d->id));
354 FIMS_INFO_LOG("Link random effects from distribution " +
355 fims::to_string(d->id) + " to derived value " +
356 fims::to_string(d->key[0]));
357 vmit = this->variable_map.find(d->key[0]);
358 d->re = (*vmit).second;
359 if (d->key.size() == 2) {
360 vmit = this->variable_map.find(d->key[1]);
361 d->re_expected_values = (*vmit).second;
362 } else {
363 d->re_expected_values = &d->expected_values;
364 }
365 FIMS_INFO_LOG("Random effect size for distribution " +
366 fims::to_string(d->id) +
367 " is: " + fims::to_string(d->observed_values.size()));
368 }
369 }
370 }
371
376 void SetupData() {
377 for (density_components_iterator it = this->density_components.begin();
378 it != this->density_components.end(); ++it) {
379 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
380 (*it).second;
381 if (d->input_type == "data") {
382 FIMS_INFO_LOG("Setup expected value for data distribution " +
383 fims::to_string(d->id));
385 FIMS_INFO_LOG("Link expected value from distribution " +
386 fims::to_string(d->id) + " to derived value " +
387 fims::to_string(d->key[0]));
388 vmit = this->variable_map.find(d->key[0]);
389 d->data_expected_values = (*vmit).second;
391 "Expected value size for distribution " + fims::to_string(d->id) +
392 " is: " + fims::to_string((*d->data_expected_values).size()));
393 }
394 }
395 }
396
404 void SetFleetCatchData(bool& valid_model,
405 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
406 if (f->fleet_observed_catch_data_id_m != static_cast<Type>(-999)) {
407 uint32_t observed_catch_id =
408 static_cast<uint32_t>(f->fleet_observed_catch_data_id_m);
409 data_iterator it = this->data_objects.find(observed_catch_id);
410 if (it != this->data_objects.end()) {
411 f->observed_catch_data = (*it).second;
412 FIMS_INFO_LOG("Catch data for fleet " + fims::to_string(f->id) +
413 " successfully set to " +
414 fims::to_string(f->observed_catch_data->at(1)));
415 } else {
416 valid_model = false;
417 FIMS_ERROR_LOG("Expected catch data not defined for fleet " +
418 fims::to_string(f->id) + ", index " +
419 fims::to_string(observed_catch_id));
420 }
421 }
422 }
423
431 void SetFleetIndexData(bool& valid_model,
432 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
433 if (f->fleet_observed_index_data_id_m != static_cast<Type>(-999)) {
434 uint32_t observed_index_id =
435 static_cast<uint32_t>(f->fleet_observed_index_data_id_m);
436 data_iterator it = this->data_objects.find(observed_index_id);
437 if (it != this->data_objects.end()) {
438 f->observed_index_data = (*it).second;
439 FIMS_INFO_LOG("Index data for fleet " + fims::to_string(f->id) +
440 " successfully set to " +
441 fims::to_string(f->observed_index_data->at(1)));
442 } else {
443 valid_model = false;
444 FIMS_ERROR_LOG("Expected index data not defined for fleet " +
445 fims::to_string(f->id) + ", index " +
446 fims::to_string(observed_index_id));
447 }
448 }
449 }
450
458 void SetAgeCompositionData(bool& valid_model,
459 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
460 if (f->fleet_observed_agecomp_data_id_m != static_cast<Type>(-999)) {
461 uint32_t observed_agecomp_id =
462 static_cast<uint32_t>(f->fleet_observed_agecomp_data_id_m);
463 data_iterator it = this->data_objects.find(observed_agecomp_id);
464 if (it != this->data_objects.end()) {
465 f->observed_agecomp_data = (*it).second;
466 FIMS_INFO_LOG("Observed input age-composition data for fleet " +
467 fims::to_string(f->id) + " successfully set to " +
468 fims::to_string(f->observed_agecomp_data->at(1)));
469 } else {
470 valid_model = false;
472 "Expected age-composition observations not defined for fleet " +
473 fims::to_string(f->id));
474 }
475 }
476 }
477
485 void SetLengthCompositionData(bool& valid_model,
486 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
487 if (f->fleet_observed_lengthcomp_data_id_m != static_cast<Type>(-999)) {
488 uint32_t observed_lengthcomp_id =
489 static_cast<uint32_t>(f->fleet_observed_lengthcomp_data_id_m);
490 data_iterator it = this->data_objects.find(observed_lengthcomp_id);
491 if (it != this->data_objects.end()) {
492 f->observed_lengthcomp_data = (*it).second;
493 FIMS_INFO_LOG("Observed input length-composition data for fleet " +
494 fims::to_string(f->id) + " successfully set to " +
495 fims::to_string(f->observed_lengthcomp_data->at(1)));
496 } else {
497 valid_model = false;
499 "Expected length-composition observations not defined for fleet " +
500 fims::to_string(f->id));
501 }
502 }
503 }
504
513 void SetFleetSelectivityModel(bool& valid_model,
514 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
515 if (f->fleet_selectivity_id_m != static_cast<Type>(-999)) {
516 uint32_t sel_id = static_cast<uint32_t>(
517 f->fleet_selectivity_id_m); // cast as unsigned integer
519 sel_id); // if find, set it, otherwise invalid
520
521 if (it != this->selectivity_models.end()) {
522 f->selectivity = (*it).second; // elements in container held in pair
523 FIMS_INFO_LOG("Selectivity model " +
524 fims::to_string(f->fleet_selectivity_id_m) +
525 " successfully set to fleet " + fims::to_string(f->id));
526 } else {
527 valid_model = false;
528 FIMS_ERROR_LOG("Expected selectivity pattern not defined for fleet " +
529 fims::to_string(f->id) + ", selectivity pattern " +
530 fims::to_string(sel_id));
531 }
532 } else {
533 FIMS_WARNING_LOG("Warning: No selectivity pattern defined for fleet " +
534 fims::to_string(f->id) +
535 ". FIMS requires selectivity be defined for all fleets "
536 "when running a catch at age model.");
537 }
538 }
539
550 bool& valid_model, std::shared_ptr<fims_popdy::Population<Type>> p,
551 std::shared_ptr<fims_popdy::Fleet<Type>> f) {
552 if (p == nullptr || f == nullptr) {
553 valid_model = false;
555 "Unable to set fleet age-to-length conversion because the population "
556 "or fleet "
557 "pointer was null.");
558 return;
559 }
560
561 f->age_to_length_conversion_model =
563
564 if (f->age_to_length_conversion_model != nullptr &&
565 f->age_to_length_conversion_model->IsActive()) {
566 return;
567 }
568
569 if (!f->requires_age_length_mapping) {
570 return;
571 }
572
573 if (f->n_lengths == 0) {
574 valid_model = false;
575 FIMS_ERROR_LOG("Fleet " + fims::to_string(f->id) +
576 " requires age-to-length conversion but has no fleet "
577 "length observation bins. Provide length_bin rows or "
578 "length_comp rows with length values.");
579 return;
580 }
581
582 valid_model = false;
584 "Fleet " + fims::to_string(f->id) +
585 " has fleet length observation bins but no usable "
586 "age-to-length conversion path. Provide fixed "
587 "age-to-length conversion of size " +
588 fims::to_string(f->n_ages * f->n_lengths) +
589 " or use a supported growth-derived age-to-length conversion path.");
590 }
591
600 void SetRecruitment(bool& valid_model,
601 std::shared_ptr<fims_popdy::Population<Type>> p) {
602 if (p->recruitment_id != static_cast<Type>(-999)) {
603 uint32_t recruitment_uint = static_cast<uint32_t>(p->recruitment_id);
604
606 this->recruitment_models.find(recruitment_uint);
607
608 if (it != this->recruitment_models.end()) {
609 p->recruitment = (*it).second; // recruitment defined in population.hpp
610 FIMS_INFO_LOG("Recruitment model " + fims::to_string(recruitment_uint) +
611 " successfully set to population " +
612 fims::to_string(p->id));
613 } else {
614 valid_model = false;
616 "Expected recruitment function not defined for "
617 "population " +
618 fims::to_string(p->id) + ", recruitment function " +
619 fims::to_string(recruitment_uint));
620 }
621 } else {
623 "No recruitment function defined for population " +
624 fims::to_string(p->id) +
625 ". FIMS requires recruitment functions be defined for all "
626 "populations when running a catch at age model.");
627 }
628 }
629
638 void SetRecruitmentProcess(bool& valid_model,
639 std::shared_ptr<fims_popdy::Population<Type>> p) {
640 std::shared_ptr<fims_popdy::RecruitmentBase<Type>> r = p->recruitment;
641 // if recruitment is defined
642 if (r) {
643 if (r->process_id != static_cast<Type>(-999)) {
644 uint32_t process_uint = static_cast<uint32_t>(r->process_id);
646 this->recruitment_process_models.find(process_uint);
647
648 if (it != this->recruitment_process_models.end()) {
649 r->process = (*it).second; // recruitment process
651 "Recruitment Process model " + fims::to_string(process_uint) +
652 " successfully set to population " + fims::to_string(p->id));
653 (*it).second->recruitment = r;
654 } else {
655 valid_model = false;
657 "Expected recruitment process function not defined for "
658 "population " +
659 fims::to_string(p->id) + ", recruitment process function " +
660 fims::to_string(process_uint));
661 }
662 } else {
664 "No recruitment process function defined for population " +
665 fims::to_string(p->id) +
666 ". FIMS requires recruitment process functions be defined for all "
667 "recruitments when running a catch at age model.");
668 }
669 }
670 }
671
680 const std::shared_ptr<fims_popdy::Population<Type>>& p) {
682
683 for (std::size_t fleet_index = 0; fleet_index < p->fleets.size();
684 ++fleet_index) {
685 const std::shared_ptr<fims_popdy::Fleet<Type>>& fleet =
686 p->fleets[fleet_index];
687
688 if (fleet == nullptr) {
689 continue;
690 }
691
692 if (!fleet->requires_age_length_mapping || fleet->n_lengths == 0) {
693 fleet->length_bin_edges = fims::Vector<double>();
694 continue;
695 }
696
697 if (fleet->lengths.size() != fleet->n_lengths) {
698 throw std::runtime_error(
699 "Fleet length_bin centers are not consistent with n_lengths");
700 }
701
702 fleet->length_bin_edges =
704 fleet->lengths);
705
706 fleet_edges.emplace_back(fleet->length_bin_edges);
707 }
708
709 return fleet_edges;
710 }
711
726 const fims_popdy::SizeGrid& size_grid,
727 const fims::Vector<fims::Vector<double>>& fleet_edges) {
728 if (!size_grid.IsConsistent() || size_grid.n_bins == 0 ||
729 fleet_edges.size() == 0) {
730 return;
731 }
732
733 for (std::size_t population_bin_index = 0;
734 population_bin_index < size_grid.n_bins; ++population_bin_index) {
735 const double population_left = size_grid.edges[population_bin_index];
736 const double population_right = size_grid.edges[population_bin_index + 1];
737 const double population_bin_width = population_right - population_left;
738 const double population_tolerance =
739 1e-12 * (population_bin_width > 1.0 ? population_bin_width : 1.0);
740
741 for (std::size_t fleet_index = 0; fleet_index < fleet_edges.size();
742 ++fleet_index) {
743 const fims::Vector<double>& edges = fleet_edges[fleet_index];
744
745 for (std::size_t fleet_bin_index = 1; fleet_bin_index < edges.size();
746 ++fleet_bin_index) {
747 const double fleet_left = edges[fleet_bin_index - 1];
748 const double fleet_right = edges[fleet_bin_index];
749 const double overlap_left = std::max(population_left, fleet_left);
750 const double overlap_right = std::min(population_right, fleet_right);
751
752 if (!(overlap_right > overlap_left)) {
753 continue;
754 }
755
756 const double fleet_bin_width = fleet_right - fleet_left;
757 if (population_bin_width > fleet_bin_width + population_tolerance) {
758 throw std::runtime_error(
759 "Population biological size grid contains at least one bin "
760 "that is coarser than an overlapping active fleet observation "
761 "bin. Provide a finer biological size-grid override or correct "
762 "the fleet bin setup.");
763 }
764 }
765 }
766 }
767 }
768
787 bool& valid_model, std::shared_ptr<fims_popdy::Population<Type>> p) {
789
790 try {
791 fleet_edges = PrepareFleetObservationBinEdges(p);
792 } catch (const std::exception& e) {
793 valid_model = false;
795 "Failed to prepare fleet observation-bin geometry for population " +
796 fims::to_string(p->id) + ": " + e.what());
797 return;
798 }
799
800 if (p->size_grid.IsConsistent() && p->size_grid.n_bins > 0) {
801 try {
802 EnforcePopulationGridNotCoarserThanFleetBins(p->size_grid, fleet_edges);
803 } catch (const std::exception& e) {
804 valid_model = false;
806 "Population " + fims::to_string(p->id) +
807 " has a biological size grid that is incompatible with active "
808 "fleet observation bins: " +
809 e.what());
810 }
811 return;
812 }
813
814 const bool size_grid_missing = p->size_grid.n_bins == 0 &&
815 p->size_grid.edges.size() == 0 &&
816 p->size_grid.centers.size() == 0;
817
818 if (size_grid_missing) {
819 try {
820 if (fleet_edges.size() == 0) {
821 throw std::runtime_error(
822 "No resolvable fleet observation-bin geometry was available "
823 "to build the default biological size grid");
824 }
825
827 fleet_edges);
828 EnforcePopulationGridNotCoarserThanFleetBins(p->size_grid, fleet_edges);
829
830 const std::size_t regular_bin_count =
831 p->size_grid.n_bins > 0 ? p->size_grid.n_bins - 1 : 0;
832
833 if (regular_bin_count > 200) {
835 "Built-in default biological size grid created more than 200 "
836 "regular bins for population " +
837 fims::to_string(p->id) +
838 ". This may slow model evaluation. Consider providing a "
839 "biological size-grid override if needed.");
840 }
841
842 } catch (const std::exception& e) {
843 valid_model = false;
845 "Failed to initialize default population size grid for "
846 "population " +
847 fims::to_string(p->id) + ": " + e.what());
848 }
849 return;
850 }
851
852 valid_model = false;
854 "Population " + fims::to_string(p->id) +
855 " has an invalid biological size grid. Provide a consistent override "
856 "or leave the grid empty so FIMS can build the default.");
857 }
858
867 std::shared_ptr<fims_popdy::Population<Type>> p,
869 growth_observation) {
870 std::shared_ptr<fims_popdy::GrowthDerivedSizeProvider<Type>> size_provider =
871 std::make_shared<fims_popdy::GrowthDerivedSizeProvider<Type>>();
872
873 size_provider->SetGrowth(growth_observation);
874 size_provider->SetPopulationDimensions(p->n_years, p->n_ages);
875 size_provider->SetPopulationSizeGrid(&(p->size_grid));
876
877 p->size_distribution_provider = size_provider;
878 }
879
888 void SetGrowth(bool& valid_model,
889 std::shared_ptr<fims_popdy::Population<Type>> p) {
890 if (p->growth_id != static_cast<Type>(-999)) {
891 uint32_t growth_uint = static_cast<uint32_t>(p->growth_id);
893 growth_uint); // growth_models is specified in information.hpp
894 // and used in rcpp
895 // at the head of information.hpp; are the
896 // dimensions of ages defined in rcpp or where?
897 if (it != this->growth_models.end()) {
898 p->growth =
899 (*it).second; // growth defined in population.hpp (the object
900 // is called p, growth is within p)
902 growth_observation = std::dynamic_pointer_cast<
904 p->growth)) {
905 growth_observation->Initialize(p->n_years, p->n_ages, 1);
906
907 if (p->ages.size() > 0) {
908 double min_age = p->ages[0];
909 for (size_t i = 1; i < p->ages.size(); ++i) {
910 if (p->ages[i] < min_age) {
911 min_age = p->ages[i];
912 }
913 }
914 growth_observation->SetAgeOffset(static_cast<double>(min_age));
915 }
916
917 const bool population_has_size_grid_input =
918 p->size_grid.n_bins > 0 || p->size_grid.edges.size() > 0 ||
919 p->size_grid.centers.size() > 0;
920
921 bool any_length_based_fleet = false;
922 for (std::size_t i = 0; i < p->fleets.size(); ++i) {
923 if (p->fleets[i] != nullptr &&
924 p->fleets[i]->requires_age_length_mapping &&
925 p->fleets[i]->n_lengths > 0) {
926 any_length_based_fleet = true;
927 break;
928 }
929 }
930
931 if (population_has_size_grid_input || any_length_based_fleet) {
932 EnsurePopulationSizeGrid(valid_model, p);
933 if (!valid_model) {
934 return;
935 }
936 ConfigureGrowthDerivedSizeProvider(p, growth_observation);
937 }
938 }
939 FIMS_INFO_LOG("Growth model " + fims::to_string(growth_uint) +
940 " successfully set to population " +
941 fims::to_string(p->id));
942 } else {
943 valid_model = false;
944 FIMS_ERROR_LOG("Expected growth function not defined for population " +
945 fims::to_string(p->id) + ", growth function " +
946 fims::to_string(growth_uint));
947 }
948 } else {
949 FIMS_WARNING_LOG("Growth function undefined for population " +
950 fims::to_string(p->id) +
951 ". FIMS requires growth functions be defined for all "
952 "populations when running a catch at age model.");
953 }
954 }
955
964 void SetMaturity(bool& valid_model,
965 std::shared_ptr<fims_popdy::Population<Type>> p) {
966 if (p->maturity_id != static_cast<Type>(-999)) {
967 uint32_t maturity_uint = static_cast<uint32_t>(p->maturity_id);
969 maturity_uint); // >maturity_models is specified in
970 // information.hpp and used in rcpp
971 if (it != this->maturity_models.end()) {
972 p->maturity = (*it).second; // >maturity defined in population.hpp
973 FIMS_INFO_LOG("Maturity model " + fims::to_string(maturity_uint) +
974 " successfully set to population " +
975 fims::to_string(p->id));
976 } else {
977 valid_model = false;
979 "Expected maturity function not defined for population " +
980 fims::to_string(p->id) + ", maturity function " +
981 fims::to_string(maturity_uint));
982 }
983 } else {
984 FIMS_WARNING_LOG("Maturity function undefined for population " +
985 fims::to_string(p->id) +
986 ". FIMS requires maturity functions be defined for all "
987 "populations when running a catch at age model.");
988 }
989 }
990
997 void CreateFleetObjects(bool& valid_model) {
998 for (fleet_iterator it = this->fleets.begin(); it != this->fleets.end();
999 ++it) {
1000 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
1001 FIMS_INFO_LOG("Initializing fleet " + fims::to_string(f->id));
1002
1003 SetFleetCatchData(valid_model, f);
1004
1005 SetFleetIndexData(valid_model, f);
1006
1007 SetAgeCompositionData(valid_model, f);
1008
1009 SetLengthCompositionData(valid_model, f);
1010
1011 SetFleetSelectivityModel(valid_model, f);
1012 }
1013 }
1014
1021 void SetDataObjects(bool& valid_model) {
1022 for (density_components_iterator it = this->density_components.begin();
1023 it != this->density_components.end(); ++it) {
1024 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
1025 (*it).second;
1026
1027 // set data objects if distribution is a data type
1028 if (d->input_type == "data") {
1029 if (d->observed_data_id_m != static_cast<Type>(-999)) {
1030 uint32_t observed_data_id =
1031 static_cast<uint32_t>(d->observed_data_id_m);
1032 data_iterator it = this->data_objects.find(observed_data_id);
1033
1034 if (it != this->data_objects.end()) {
1035 d->data_observed_values = (*it).second;
1036 FIMS_INFO_LOG("Observed data " + fims::to_string(observed_data_id) +
1037 " successfully set to density component " +
1038 fims::to_string(d->id));
1039 } else {
1040 valid_model = false;
1042 "Expected data observations not defined for density "
1043 "component " +
1044 fims::to_string(d->id) + ", observed data " +
1045 fims::to_string(observed_data_id));
1046 }
1047 } else {
1048 valid_model = false;
1049 FIMS_ERROR_LOG("No data input for density component" +
1050 fims::to_string(d->id));
1051 }
1052 }
1053 }
1054 }
1055
1062 void CreatePopulationObjects(bool& valid_model) {
1063 for (population_iterator it = this->populations.begin();
1064 it != this->populations.end(); ++it) {
1065 std::shared_ptr<fims_popdy::Population<Type>> p = (*it).second;
1066
1067 FIMS_INFO_LOG("Initializing population " + fims::to_string(p->id));
1068 // check if population has fleets
1069 typename std::set<uint32_t>::iterator fleet_ids_it;
1070
1071 for (fleet_ids_it = p->fleet_ids.begin();
1072 fleet_ids_it != p->fleet_ids.end(); ++fleet_ids_it) {
1073 // error check and set population elements
1074 // check me - add another fleet iterator to push information from
1075 // for (fleet_iterator it = this->fleets.begin(); it !=
1076 // this->fleets.end();
1077 // ++it) {
1078
1079 fleet_iterator it = this->fleets.find(*fleet_ids_it);
1080
1081 if (it != this->fleets.end()) {
1082 // Initialize fleet object
1083 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
1084 // population to the individual fleets This is to pass catch at age
1085 // from population to fleets?
1086 // any shared member in p (population is pushed into fleets)
1087 p->fleets.push_back(f);
1088 } else {
1089 valid_model = false;
1090 FIMS_ERROR_LOG("Fleet \"" + fims::to_string(*fleet_ids_it) +
1091 "\" undefined, not found for Population \"" +
1092 fims::to_string(p->id) + "\". ");
1093 }
1094 }
1095
1096 // set information dimensions
1097 this->n_years = std::max(this->n_years, p->n_years);
1098 this->n_ages = std::max(this->n_ages, p->n_ages);
1099
1100 SetRecruitment(valid_model, p);
1101
1102 SetRecruitmentProcess(valid_model, p);
1103
1104 SetGrowth(valid_model, p);
1105 for (size_t i = 0; i < p->fleets.size(); ++i) {
1106 SetFleetAgeToLengthConversionModel(valid_model, p, p->fleets[i]);
1107 }
1108
1109 SetMaturity(valid_model, p);
1110 }
1111 }
1112
1116 void CreateModelingObjects(bool& valid_model) {
1117 for (model_map_iterator it = this->models_map.begin();
1118 it != this->models_map.end(); ++it) {
1119 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>& model = (*it).second;
1120 std::set<uint32_t>::iterator jt;
1121
1122 for (jt = model->population_ids.begin();
1123 jt != model->population_ids.end(); ++jt) {
1124 population_iterator pt = this->populations.find((*jt));
1125
1126 if (pt != this->populations.end()) {
1127 std::shared_ptr<fims_popdy::Population<Type>> p = (*pt).second;
1128 model->populations.push_back(p);
1129 for (size_t i = 0; i < p->fleets.size(); i++) {
1130 uint32_t local_fleet_id = p->fleets[i]->GetId();
1131 model->fleets[local_fleet_id] = p->fleets[i];
1132 FIMS_INFO_LOG(std::string("Linked fleet id ") +
1133 fims::to_string(local_fleet_id) +
1134 std::string(" into model id ") +
1135 fims::to_string(model->GetId()));
1136 }
1137 } else {
1138 valid_model = false;
1139 FIMS_ERROR_LOG("No population object defined for model " +
1140 fims::to_string(model->GetId()));
1141 }
1142 }
1143 model->Initialize();
1144 }
1145 }
1146
1158 FIMS_INFO_LOG("Creating model and checking for required components...");
1159 bool valid_model = true;
1160
1161 CreateFleetObjects(valid_model);
1162
1163 SetDataObjects(valid_model);
1164
1165 CreatePopulationObjects(valid_model);
1166
1167 CreateModelingObjects(valid_model);
1168
1169 // setup priors, random effect, and data density components
1170 SetupPriors();
1172 SetupData();
1173
1174 if (valid_model) {
1175 FIMS_INFO_LOG("Model successfully created.");
1176 } else {
1177 FIMS_ERROR_LOG("Model creation failed.");
1178 }
1179
1180 return valid_model;
1181 }
1182
1188 size_t GetNages() const { return n_ages; }
1189
1195 void SetNages(size_t n_ages) { this->n_ages = n_ages; }
1196
1202 size_t GetNyears() const { return n_years; }
1203
1209 void SetNyears(size_t n_years) { this->n_years = n_years; }
1210
1216 std::vector<Type*>& GetParameters() { return parameters; }
1217
1223 std::vector<Type*>& GetFixedEffectsParameters() {
1225 }
1226
1232 std::vector<Type*>& GetRandomEffectsParameters() {
1234 }
1235
1243 bool CheckModel() {
1244 bool valid_model = true;
1245 for (model_map_iterator it = this->models_map.begin();
1246 it != this->models_map.end(); ++it) {
1247 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>& model = (*it).second;
1248 std::set<uint32_t>::iterator jt;
1249
1250 for (jt = model->population_ids.begin();
1251 jt != model->population_ids.end(); ++jt) {
1252 population_iterator pt = this->populations.find((*jt));
1253
1254 if (pt != this->populations.end()) {
1255 std::shared_ptr<fims_popdy::Population<Type>> p = (*pt).second;
1256
1257 if (model->model_type_m == "caa") {
1258 typename std::set<uint32_t>::iterator fleet_ids_it;
1259 for (fleet_ids_it = p->fleet_ids.begin();
1260 fleet_ids_it != p->fleet_ids.end(); ++fleet_ids_it) {
1261 fleet_iterator it = this->fleets.find(*fleet_ids_it);
1262
1263 if (it != this->fleets.end()) {
1264 // Initialize fleet object
1265 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
1266
1267 if (f->fleet_selectivity_id_m == static_cast<Type>(-999)) {
1268 valid_model = false;
1270 "No selectivity pattern defined for fleet " +
1271 fims::to_string(f->id) +
1272 ". FIMS requires selectivity be defined for all fleets "
1273 "when running a catch at age model.");
1274 }
1275 }
1276 }
1277
1278 if (p->recruitment_id == static_cast<Type>(-999)) {
1279 valid_model = false;
1281 "No recruitment function defined for population " +
1282 fims::to_string(p->id) +
1283 ". FIMS requires recruitment functions be defined for all "
1284 "populations when running a catch at age model.");
1285 }
1286
1287 std::shared_ptr<fims_popdy::RecruitmentBase<Type>> r =
1288 p->recruitment;
1289 r = p->recruitment;
1290 if (r->process_id == static_cast<Type>(-999)) {
1291 valid_model = false;
1293 "No recruitment process function defined for population " +
1294 fims::to_string(p->id) +
1295 ". FIMS requires recruitment process functions be defined "
1296 "for all "
1297 "recruitments when running a catch at age model.");
1298 }
1299
1300 if (p->growth_id == static_cast<Type>(-999)) {
1301 valid_model = false;
1303 "No growth function defined for population " +
1304 fims::to_string(p->id) +
1305 ". FIMS requires growth functions be defined for all "
1306 "populations when running a catch at age model.");
1307 }
1308
1309 if (p->maturity_id == static_cast<Type>(-999)) {
1310 valid_model = false;
1311
1313 "No maturity function defined for population " +
1314 fims::to_string(p->id) +
1315 ". FIMS requires maturity functions be defined for all "
1316 "populations when running a catch at age model.");
1317 }
1318 }
1319 }
1320 }
1321 }
1322 return valid_model;
1323 }
1324};
1325
1326template <typename Type>
1327std::shared_ptr<Information<Type>> Information<Type>::fims_information =
1328 nullptr;
1330} // namespace fims_info
1331
1332#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:679
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:345
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:309
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:1223
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:431
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:888
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:725
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:964
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:786
void SetDataObjects(bool &valid_model)
Loop over all density components and set pointers to data objects.
Definition information.hpp:1021
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:1062
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:485
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:513
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:282
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:291
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:600
void SetNages(size_t n_ages)
Set the Nages object.
Definition information.hpp:1195
size_t GetNages() const
Get the Nages object.
Definition information.hpp:1188
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:1209
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:638
bool CheckModel()
Checks to make sure all required modules are present for specified model.
Definition information.hpp:1243
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:1157
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:458
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:549
void CreateFleetObjects(bool &valid_model)
Loop over all fleets and set pointers to fleet objects.
Definition information.hpp:997
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:404
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:866
std::vector< Type * > & GetRandomEffectsParameters()
Get the Random Effects Parameters object.
Definition information.hpp:1232
std::vector< std::string > random_effects_names
Definition information.hpp:55
std::vector< Type * > & GetParameters()
Get the Parameters object.
Definition information.hpp:1216
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:317
size_t GetNyears() const
Get the n_years object.
Definition information.hpp:1202
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:300
void SetupData()
Loop over distributions and set links to distribution expected value if distribution is a data type.
Definition information.hpp:376
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:234
static std::shared_ptr< Information< Type > > GetInstance()
Returns a singleton Information object for type T.
Definition information.hpp:269
void CreateModelingObjects(bool &valid_model)
Loop over all models and set pointers to population objects.
Definition information.hpp:1116
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