11#ifndef FIMS_COMMON_INFORMATION_HPP
12#define FIMS_COMMON_INFORMATION_HPP
39template <
typename Type>
45 static std::shared_ptr<Information<Type>>
54 std::vector<std::string>
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
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>>>
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
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
117 std::map<uint32_t, std::shared_ptr<fims_popdy::Population<Type>>>
121 typename std::map<uint32_t,
122 std::shared_ptr<fims_popdy::Population<Type>>>::iterator
128 std::shared_ptr<fims_distributions::DensityComponentBase<Type>>>
131 typedef typename std::map<
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
163 void ResetRecruitmentLinks() noexcept {
164 auto detach = [](
auto& models) {
165 for (
auto& entry : models) {
166 const auto& recruitment = entry.second;
168 recruitment->process.reset();
169 recruitment->recruitment.reset();
189 this->parameter_names.clear();
190 this->parameters.clear();
198 ResetRecruitmentLinks();
207 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
210 d->data_observed_values.reset();
211 d->data_expected_values =
nullptr;
213 d->re_expected_values =
nullptr;
228 std::stringstream ss;
229 ss <<
"Information object State:\n";
231 ss <<
"populations: " << this->
populations.size() << 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;
241 ss <<
"random_effects_parameters: "
245 ss <<
"recruitment_process_models: "
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;
265 std::make_shared<fims_info::Information<Type>>();
294 this->parameter_names.push_back(p_name);
313 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
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++) {
323 fims::to_string(d->id) +
" to parameter " +
324 fims::to_string(d->key[0]));
326 d->priors[i] = (*vmit).second;
328 FIMS_INFO_LOG(
"Prior size for distribution " + fims::to_string(d->id) +
329 "is: " + fims::to_string(d->observed_values.size()));
341 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
343 if (d->input_type ==
"random_effects") {
345 fims::to_string(d->id));
348 fims::to_string(d->id) +
" to derived value " +
349 fims::to_string(d->key[0]));
351 d->re = (*vmit).second;
352 if (d->key.size() == 2) {
354 d->re_expected_values = (*vmit).second;
356 d->re_expected_values = &d->expected_values;
359 fims::to_string(d->id) +
360 " is: " + fims::to_string(d->observed_values.size()));
372 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
374 if (d->input_type ==
"data") {
375 FIMS_INFO_LOG(
"Setup expected value for data distribution " +
376 fims::to_string(d->id));
379 fims::to_string(d->id) +
" to derived value " +
380 fims::to_string(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()));
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);
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)));
411 fims::to_string(f->id) +
", index " +
412 fims::to_string(observed_catch_id));
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);
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)));
438 fims::to_string(f->id) +
", index " +
439 fims::to_string(observed_index_id));
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);
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)));
465 "Expected age-composition observations not defined for fleet " +
466 fims::to_string(f->id));
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);
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)));
492 "Expected length-composition observations not defined for fleet " +
493 fims::to_string(f->id));
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);
515 f->selectivity = (*it).second;
517 fims::to_string(f->fleet_selectivity_id_m) +
518 " successfully set to fleet " + fims::to_string(f->id));
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));
527 fims::to_string(f->id) +
528 ". FIMS requires selectivity be defined for all fleets "
529 "when running a catch at age model.");
545 if (p ==
nullptr || f ==
nullptr) {
548 "Unable to set fleet age-to-length conversion because the population "
550 "pointer was null.");
554 f->age_to_length_conversion_model =
557 if (f->age_to_length_conversion_model !=
nullptr &&
558 f->age_to_length_conversion_model->IsActive()) {
562 if (!f->requires_age_length_mapping) {
566 if (f->n_lengths == 0) {
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.");
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.");
595 if (p->recruitment_id !=
static_cast<Type
>(-999)) {
596 uint32_t recruitment_uint =
static_cast<uint32_t
>(p->recruitment_id);
602 p->recruitment = (*it).second;
603 FIMS_INFO_LOG(
"Recruitment model " + fims::to_string(recruitment_uint) +
604 " successfully set to population " +
605 fims::to_string(p->id));
609 "Expected recruitment function not defined for "
611 fims::to_string(p->id) +
", recruitment function " +
612 fims::to_string(recruitment_uint));
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.");
633 std::shared_ptr<fims_popdy::RecruitmentBase<Type>> r = p->recruitment;
636 if (r->process_id !=
static_cast<Type
>(-999)) {
637 uint32_t process_uint =
static_cast<uint32_t
>(r->process_id);
642 r->process = (*it).second;
644 "Recruitment Process model " + fims::to_string(process_uint) +
645 " successfully set to population " + fims::to_string(p->id));
646 (*it).second->recruitment = r;
650 "Expected recruitment process function not defined for "
652 fims::to_string(p->id) +
", recruitment process function " +
653 fims::to_string(process_uint));
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.");
676 for (std::size_t fleet_index = 0; fleet_index < p->fleets.size();
678 const std::shared_ptr<fims_popdy::Fleet<Type>>& fleet =
679 p->fleets[fleet_index];
681 if (fleet ==
nullptr) {
685 if (!fleet->requires_age_length_mapping || fleet->n_lengths == 0) {
690 if (fleet->lengths.size() != fleet->n_lengths) {
691 throw std::runtime_error(
692 "Fleet length_bin centers are not consistent with n_lengths");
695 fleet->length_bin_edges =
722 fleet_edges.size() == 0) {
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);
734 for (std::size_t fleet_index = 0; fleet_index < fleet_edges.size();
738 for (std::size_t fleet_bin_index = 1; fleet_bin_index < edges.
size();
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);
745 if (!(overlap_right > overlap_left)) {
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.");
785 }
catch (
const std::exception& e) {
788 "Failed to prepare fleet observation-bin geometry for population " +
789 fims::to_string(p->id) +
": " + e.what());
793 if (p->size_grid.IsConsistent() && p->size_grid.n_bins > 0) {
796 }
catch (
const std::exception& e) {
799 "Population " + fims::to_string(p->id) +
800 " has a biological size grid that is incompatible with active "
801 "fleet observation bins: " +
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;
811 if (size_grid_missing) {
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");
823 const std::size_t regular_bin_count =
824 p->size_grid.n_bins > 0 ? p->size_grid.n_bins - 1 : 0;
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.");
835 }
catch (
const std::exception& e) {
838 "Failed to initialize default population size grid for "
840 fims::to_string(p->id) +
": " + e.what());
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.");
862 growth_observation) {
863 std::shared_ptr<fims_popdy::GrowthDerivedSizeProvider<Type>> size_provider =
864 std::make_shared<fims_popdy::GrowthDerivedSizeProvider<Type>>();
866 size_provider->SetGrowth(growth_observation);
867 size_provider->SetPopulationDimensions(p->n_years, p->n_ages);
868 size_provider->SetPopulationSizeGrid(&(p->size_grid));
870 p->size_distribution_provider = size_provider;
883 if (p->growth_id !=
static_cast<Type
>(-999)) {
884 uint32_t growth_uint =
static_cast<uint32_t
>(p->growth_id);
895 growth_observation = std::dynamic_pointer_cast<
898 growth_observation->Initialize(p->n_years, p->n_ages, 1);
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];
907 growth_observation->SetAgeOffset(
static_cast<double>(min_age));
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;
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;
924 if (population_has_size_grid_input || any_length_based_fleet) {
932 FIMS_INFO_LOG(
"Growth model " + fims::to_string(growth_uint) +
933 " successfully set to population " +
934 fims::to_string(p->id));
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));
943 fims::to_string(p->id) +
944 ". FIMS requires growth functions be defined for all "
945 "populations when running a catch at age model.");
959 if (p->maturity_id !=
static_cast<Type
>(-999)) {
960 uint32_t maturity_uint =
static_cast<uint32_t
>(p->maturity_id);
965 p->maturity = (*it).second;
966 FIMS_INFO_LOG(
"Maturity model " + fims::to_string(maturity_uint) +
967 " successfully set to population " +
968 fims::to_string(p->id));
972 "Expected maturity function not defined for population " +
973 fims::to_string(p->id) +
", maturity function " +
974 fims::to_string(maturity_uint));
978 fims::to_string(p->id) +
979 ". FIMS requires maturity functions be defined for all "
980 "populations when running a catch at age model.");
993 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
994 FIMS_INFO_LOG(
"Initializing fleet " + fims::to_string(f->id));
1017 std::shared_ptr<fims_distributions::DensityComponentBase<Type>> d =
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);
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));
1033 valid_model =
false;
1035 "Expected data observations not defined for density "
1037 fims::to_string(d->id) +
", observed data " +
1038 fims::to_string(observed_data_id));
1041 valid_model =
false;
1043 fims::to_string(d->id));
1058 std::shared_ptr<fims_popdy::Population<Type>> p = (*it).second;
1060 FIMS_INFO_LOG(
"Initializing population " + fims::to_string(p->id));
1062 typename std::set<uint32_t>::iterator fleet_ids_it;
1064 for (fleet_ids_it = p->fleet_ids.begin();
1065 fleet_ids_it != p->fleet_ids.end(); ++fleet_ids_it) {
1074 if (it != this->
fleets.end()) {
1076 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
1080 p->fleets.push_back(f);
1082 valid_model =
false;
1084 "\" undefined, not found for Population \"" +
1085 fims::to_string(p->id) +
"\". ");
1090 this->n_years = std::max(this->n_years, p->n_years);
1091 this->n_ages = std::max(this->n_ages, p->n_ages);
1098 for (
size_t i = 0; i < p->fleets.size(); ++i) {
1112 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>& model = (*it).second;
1113 std::set<uint32_t>::iterator jt;
1115 for (jt = model->population_ids.begin();
1116 jt != model->population_ids.end(); ++jt) {
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];
1126 fims::to_string(local_fleet_id) +
1127 std::string(
" into model id ") +
1128 fims::to_string(model->GetId()));
1131 valid_model =
false;
1133 fims::to_string(model->GetId()));
1136 model->Initialize();
1151 FIMS_INFO_LOG(
"Creating model and checking for required components...");
1152 bool valid_model =
true;
1237 bool valid_model =
true;
1240 std::shared_ptr<fims_popdy::FisheryModelBase<Type>>& model = (*it).second;
1241 std::set<uint32_t>::iterator jt;
1243 for (jt = model->population_ids.begin();
1244 jt != model->population_ids.end(); ++jt) {
1248 std::shared_ptr<fims_popdy::Population<Type>> p = (*pt).second;
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) {
1256 if (it != this->
fleets.end()) {
1258 std::shared_ptr<fims_popdy::Fleet<Type>> f = (*it).second;
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.");
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.");
1280 std::shared_ptr<fims_popdy::RecruitmentBase<Type>> r =
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 "
1290 "recruitments when running a catch at age model.");
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.");
1302 if (p->maturity_id ==
static_cast<Type
>(-999)) {
1303 valid_model =
false;
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.");
1319template <
typename Type>
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
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 > ¢ers)
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