FIMS  v0.10.0
Loading...
Searching...
No Matches
growth_derived_size_provider.hpp
Go to the documentation of this file.
1
9#ifndef FIMS_POPULATION_DYNAMICS_GROWTH_DERIVED_SIZE_PROVIDER_HPP
10#define FIMS_POPULATION_DYNAMICS_GROWTH_DERIVED_SIZE_PROVIDER_HPP
11
12#include <cstddef>
13#include <memory>
14#include <stdexcept>
15
16#include "../growth/growth_model_adapter.hpp"
18#include "size_products.hpp"
19#include "../../common/def.hpp"
20#include "../../common/fims_math.hpp"
21
22namespace fims_popdy {
23
34template <typename Type>
36 public:
37 GrowthDerivedSizeProvider() = default;
38
45 std::shared_ptr<GrowthDerivedObservationBase<Type>> growth)
46 : growth_observation_(growth) {}
47
48 const SizeGrid* TryGetSizeGrid() const override {
49 return population_size_grid_;
50 }
51
53 population_size_grid_ = population_size_grid;
54 size_products_prepared_ = false;
55 plus_group_warning_emitted_ = false;
56 }
57
58 void SetPopulationDimensions(std::size_t n_years,
59 std::size_t n_ages) override {
60 n_years_ = n_years;
61 n_ages_ = n_ages;
62 size_products_prepared_ = false;
63 plus_group_warning_emitted_ = false;
64 }
65
66 void PrepareSizeProducts() override {
67 if (!population_size_grid_) {
68 throw std::runtime_error(
69 "GrowthDerivedSizeProvider requires a population biological size "
70 "grid");
71 }
72
73 if (!population_size_grid_->IsConsistent()) {
74 throw std::runtime_error(
75 "GrowthDerivedSizeProvider requires a consistent population "
76 "biological size grid");
77 }
78
79 if (population_size_grid_->n_bins == 0) {
80 throw std::runtime_error(
81 "GrowthDerivedSizeProvider requires a population biological size grid"
82 " with at least one bin");
83 }
84
85 if (n_years_ == 0 || n_ages_ == 0) {
86 throw std::runtime_error(
87 "GrowthDerivedSizeProvider requires nonzero population dimensions");
88 }
89
90 const GrowthProducts<Type>& growth_products = PreparedGrowthProducts();
91
92 if (growth_products.n_years != n_years_ ||
93 growth_products.n_ages != n_ages_) {
94 throw std::runtime_error(
95 "GrowthDerivedSizeProvider growth products do not match "
96 "configured population dimensions");
97 }
98
99 if (growth_products.n_sexes != 1) {
100 throw std::runtime_error(
101 "GrowthDerivedSizeProvider currently requires pooled growth "
102 "products with n_sexes == 1");
103 }
104
105 size_products_.ResizeProbSizeOnly(n_years_, n_ages_,
106 population_size_grid_->n_bins);
107
108 const Type plus_group_warning_threshold = static_cast<Type>(0.01);
109 bool plus_group_warning_needed = false;
110 std::size_t warning_year_index = 0;
111 std::size_t warning_age_index = 0;
112
113 for (std::size_t year_index = 0; year_index < n_years_; ++year_index) {
114 for (std::size_t age_index = 0; age_index < n_ages_; ++age_index) {
115 fims::Vector<Type> prob_row(population_size_grid_->n_bins);
116 Type row_sum = static_cast<Type>(0.0);
117 const Type minimum_bin_prob = static_cast<Type>(1e-12);
118
119 for (std::size_t size_bin_index = 0;
120 size_bin_index < population_size_grid_->n_bins; ++size_bin_index) {
121 Type bin_prob = PopulationSizeBinProb(growth_products, year_index,
124
126 row_sum += bin_prob;
127 }
128
129 for (std::size_t size_bin_index = 0;
130 size_bin_index < population_size_grid_->n_bins; ++size_bin_index) {
131 size_products_.ProbSize(year_index, age_index, size_bin_index) =
133 }
134
135 const Type plus_group_prob = size_products_.ProbSize(
136 year_index, age_index, population_size_grid_->n_bins - 1);
137
143 }
144 }
145 }
146
147 if (plus_group_warning_needed && !plus_group_warning_emitted_) {
149 "Growth-derived size preparation placed more than 0.01 "
150 "probability in the terminal biological plus-group bin for at "
151 "least one year-age row. First occurrence was year index " +
152 fims::to_string(warning_year_index) + ", age index " +
153 fims::to_string(warning_age_index) +
154 ". The population biological size grid may need to be widened.");
155 plus_group_warning_emitted_ = true;
156 }
157
158 size_products_prepared_ = true;
159 }
160
162 size_products_prepared_ = false;
163 }
164
165 const Type& MeanLAA(std::size_t year_index,
166 std::size_t age_index) const override {
167 return PreparedGrowthProducts().MeanLAA(year_index, age_index, 0);
168 }
169
170 const Type& SdLAA(std::size_t year_index,
171 std::size_t age_index) const override {
172 return PreparedGrowthProducts().SdLAA(year_index, age_index, 0);
173 }
174
175 const Type& ProbSize(std::size_t year_index, std::size_t age_index,
176 std::size_t size_bin_index) const override {
177 if (!size_products_prepared_) {
178 throw std::runtime_error(
179 "GrowthDerivedSizeProvider requires prepared size products");
180 }
181
182 return size_products_.ProbSize(year_index, age_index, size_bin_index);
183 }
184
190 void SetGrowth(std::shared_ptr<GrowthDerivedObservationBase<Type>> growth) {
191 growth_observation_ = growth;
192 size_products_prepared_ = false;
193 plus_group_warning_emitted_ = false;
194 }
195
196 private:
197 Type PopulationSizeBinProb(const GrowthProducts<Type>& growth_products,
198 std::size_t year_index, std::size_t age_index,
199 std::size_t size_bin_index) const {
200 if (!population_size_grid_ || population_size_grid_->n_bins == 0) {
201 throw std::runtime_error(
202 "GrowthDerivedSizeProvider requires a population biological size grid"
203 " before computing ProbSize");
204 }
205
206 const Type mean_laa = growth_products.MeanLAA(year_index, age_index, 0);
207 const Type sd_laa =
208 fims_math::ad_max(growth_products.SdLAA(year_index, age_index, 0),
209 static_cast<Type>(1e-8));
210
211 if (population_size_grid_->n_bins == 1) {
212 return static_cast<Type>(1.0);
213 }
214
215 if (size_bin_index == 0) {
216 const Type upper = static_cast<Type>(population_size_grid_->edges[1]);
217 return fims_math::pnorm(upper, mean_laa, sd_laa);
218 }
219
220 if (size_bin_index + 1 == population_size_grid_->n_bins) {
221 const Type lower = static_cast<Type>(
222 population_size_grid_->edges[population_size_grid_->n_bins - 1]);
223 return fims_math::pnorm(static_cast<Type>(2.0) * mean_laa - lower,
225 }
226
227 const Type lower =
228 static_cast<Type>(population_size_grid_->edges[size_bin_index]);
229 const Type upper =
230 static_cast<Type>(population_size_grid_->edges[size_bin_index + 1]);
231
232 return fims_math::pnorm(upper, mean_laa, sd_laa) -
233 fims_math::pnorm(lower, mean_laa, sd_laa);
234 }
235
236 const GrowthProducts<Type>& PreparedGrowthProducts() const {
237 if (!growth_observation_) {
238 throw std::runtime_error(
239 "GrowthDerivedSizeProvider requires a linked growth object");
240 }
241
243 growth_observation_->TryGetPreparedGrowthProducts();
244
245 if (!growth_products) {
246 throw std::runtime_error(
247 "GrowthDerivedSizeProvider requires prepared growth products");
248 }
249
250 return *growth_products;
251 }
252
253 std::shared_ptr<GrowthDerivedObservationBase<Type>> growth_observation_;
254 const SizeGrid* population_size_grid_ = nullptr;
255 std::size_t n_years_ = 0;
256 std::size_t n_ages_ = 0;
257 bool size_products_prepared_ = false;
258 bool plus_group_warning_emitted_ = false;
259 SizeProducts<Type> size_products_;
260};
261
262} // namespace fims_popdy
263
264#endif /* FIMS_POPULATION_DYNAMICS_GROWTH_DERIVED_SIZE_PROVIDER_HPP */
Definition fims_vector.hpp:27
Generic capability interface for growth models that can feed the growth-derived age-to-length convers...
Definition growth_model_adapter.hpp:26
Size provider that converts growth outputs to population size products.
Definition growth_derived_size_provider.hpp:35
void PrepareSizeProducts() override
Prepare size products for the current model state.
Definition growth_derived_size_provider.hpp:66
void SetPopulationDimensions(std::size_t n_years, std::size_t n_ages) override
Configure the provider dimensions for prepared size products.
Definition growth_derived_size_provider.hpp:58
void SetPopulationSizeGrid(const SizeGrid *population_size_grid) override
Configure the provider to use the canonical population size grid.
Definition growth_derived_size_provider.hpp:52
const Type & MeanLAA(std::size_t year_index, std::size_t age_index) const override
Read prepared mean length-at-age.
Definition growth_derived_size_provider.hpp:165
void SetGrowth(std::shared_ptr< GrowthDerivedObservationBase< Type > > growth)
Replace the Growth-derived observation object used by this provider.
Definition growth_derived_size_provider.hpp:190
GrowthDerivedSizeProvider(std::shared_ptr< GrowthDerivedObservationBase< Type > > growth)
Construct a provider linked to a Growth-derived observation object.
Definition growth_derived_size_provider.hpp:44
const SizeGrid * TryGetSizeGrid() const override
Return the biological size grid used by this provider.
Definition growth_derived_size_provider.hpp:48
const Type & SdLAA(std::size_t year_index, std::size_t age_index) const override
Read prepared spread of length-at-age.
Definition growth_derived_size_provider.hpp:170
const Type & ProbSize(std::size_t year_index, std::size_t age_index, std::size_t size_bin_index) const override
Read prepared age-to-size probability on the population grid.
Definition growth_derived_size_provider.hpp:175
void InvalidatePreparedSizeProducts() override
Invalidate any prepared size state held by this provider.
Definition growth_derived_size_provider.hpp:161
Base interface for objects that provide population-level size distributions.
Definition size_distribution_provider_base.hpp:30
#define FIMS_WARNING_LOG(MESSAGE)
Definition def.hpp:648
The population dynamics of FIMS.
Definition catch_at_age.hpp:45
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 SizeDistributionProviderBase interface for prepared population-level size products.
Defines the SizeProducts container for cached population-level size outputs on the biological size gr...
Growth "products" in a consistent (year, age, sex) space.
Definition growth_products.hpp:26
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