9#ifndef FIMS_POPULATION_DYNAMICS_GROWTH_DERIVED_SIZE_PROVIDER_HPP
10#define FIMS_POPULATION_DYNAMICS_GROWTH_DERIVED_SIZE_PROVIDER_HPP
35template <
typename Type>
36class GrowthDerivedSizeProvider :
public SizeDistributionProviderBase<Type> {
38 GrowthDerivedSizeProvider() =
default;
47 : growth_observation_(growth) {}
50 return population_size_grid_;
54 population_size_grid_ = population_size_grid;
55 size_products_prepared_ =
false;
56 plus_group_warning_emitted_ =
false;
60 std::size_t n_ages)
override {
63 size_products_prepared_ =
false;
64 plus_group_warning_emitted_ =
false;
68 if (!population_size_grid_) {
69 throw std::runtime_error(
70 "GrowthDerivedSizeProvider requires a population biological size "
74 if (!population_size_grid_->IsConsistent()) {
75 throw std::runtime_error(
76 "GrowthDerivedSizeProvider requires a consistent population "
77 "biological size grid");
80 if (population_size_grid_->n_bins == 0) {
81 throw std::runtime_error(
82 "GrowthDerivedSizeProvider requires a population biological size grid"
83 " with at least one bin");
86 if (n_years_ == 0 || n_ages_ == 0) {
87 throw std::runtime_error(
88 "GrowthDerivedSizeProvider requires nonzero population dimensions");
93 if (growth_products.
n_years != n_years_ ||
94 growth_products.
n_ages != n_ages_) {
95 throw std::runtime_error(
96 "GrowthDerivedSizeProvider growth products do not match "
97 "configured population dimensions");
100 if (growth_products.
n_sexes != 1) {
101 throw std::runtime_error(
102 "GrowthDerivedSizeProvider currently requires pooled growth "
103 "products with n_sexes == 1");
106 size_products_.ResizeProbSizeOnly(n_years_, n_ages_,
107 population_size_grid_->n_bins);
109 const Type plus_group_warning_threshold =
static_cast<Type
>(0.01);
110 bool plus_group_warning_needed =
false;
111 std::size_t warning_year_index = 0;
112 std::size_t warning_age_index = 0;
114 for (std::size_t year_index = 0; year_index < n_years_; ++year_index) {
115 for (std::size_t age_index = 0; age_index < n_ages_; ++age_index) {
117 Type row_sum =
static_cast<Type
>(0.0);
118 const Type minimum_bin_prob =
static_cast<Type
>(1e-12);
120 for (std::size_t size_bin_index = 0;
121 size_bin_index < population_size_grid_->n_bins; ++size_bin_index) {
122 Type bin_prob = PopulationSizeBinProb(growth_products, year_index,
123 age_index, size_bin_index) +
126 prob_row[size_bin_index] = bin_prob;
130 for (std::size_t size_bin_index = 0;
131 size_bin_index < population_size_grid_->n_bins; ++size_bin_index) {
132 size_products_.ProbSize(year_index, age_index, size_bin_index) =
133 prob_row[size_bin_index] / row_sum;
136 const Type plus_group_prob = size_products_.ProbSize(
137 year_index, age_index, population_size_grid_->n_bins - 1);
139 if (!plus_group_warning_needed &&
140 plus_group_prob > plus_group_warning_threshold) {
141 plus_group_warning_needed =
true;
142 warning_year_index = year_index;
143 warning_age_index = age_index;
148 if (plus_group_warning_needed && !plus_group_warning_emitted_) {
150 "Growth-derived size preparation placed more than 0.01 "
151 "probability in the terminal biological plus-group bin for at "
152 "least one year-age row. First occurrence was year index " +
155 ". The population biological size grid may need to be widened.");
156 plus_group_warning_emitted_ =
true;
163 for (std::size_t size_bin_index = 0;
164 size_bin_index < population_size_grid_->n_bins; ++size_bin_index) {
165 weight_at_bin[size_bin_index] =
166 growth_observation_->EvaluateWeightAtLength(
static_cast<Type
>(
167 population_size_grid_->centers[size_bin_index]));
170 mean_weight_at_age_.resize(n_years_ * n_ages_);
171 for (std::size_t year_index = 0; year_index < n_years_; ++year_index) {
172 for (std::size_t age_index = 0; age_index < n_ages_; ++age_index) {
173 Type mean_weight =
static_cast<Type
>(0.0);
174 for (std::size_t size_bin_index = 0;
175 size_bin_index < population_size_grid_->n_bins; ++size_bin_index) {
177 size_products_.ProbSize(year_index, age_index, size_bin_index) *
178 weight_at_bin[size_bin_index];
180 mean_weight_at_age_[year_index * n_ages_ + age_index] = mean_weight;
184 size_products_prepared_ =
true;
188 size_products_prepared_ =
false;
192 std::size_t age_index)
const override {
193 return PreparedGrowthProducts().MeanLAA(year_index, age_index, 0);
196 const Type&
SdLAA(std::size_t year_index,
197 std::size_t age_index)
const override {
198 return PreparedGrowthProducts().SdLAA(year_index, age_index, 0);
201 const Type&
ProbSize(std::size_t year_index, std::size_t age_index,
202 std::size_t size_bin_index)
const override {
203 if (!size_products_prepared_) {
204 throw std::runtime_error(
205 "GrowthDerivedSizeProvider requires prepared size products");
208 return size_products_.ProbSize(year_index, age_index, size_bin_index);
230 std::size_t age_index)
const override {
231 if (!size_products_prepared_) {
232 throw std::runtime_error(
233 "GrowthDerivedSizeProvider requires prepared size products");
236 if (year_index >= n_years_ || age_index >= n_ages_) {
237 throw std::out_of_range(
238 "GrowthDerivedSizeProvider mean weight-at-age index out of range");
241 return mean_weight_at_age_[year_index * n_ages_ + age_index];
250 growth_observation_ = growth;
251 size_products_prepared_ =
false;
252 plus_group_warning_emitted_ =
false;
257 std::size_t year_index, std::size_t age_index,
258 std::size_t size_bin_index)
const {
259 if (!population_size_grid_ || population_size_grid_->
n_bins == 0) {
260 throw std::runtime_error(
261 "GrowthDerivedSizeProvider requires a population biological size grid"
262 " before computing ProbSize");
265 const Type mean_laa = growth_products.
MeanLAA(year_index, age_index, 0);
268 static_cast<Type
>(1e-8));
270 if (population_size_grid_->
n_bins == 1) {
271 return static_cast<Type
>(1.0);
274 if (size_bin_index == 0) {
275 const Type upper =
static_cast<Type
>(population_size_grid_->edges[1]);
276 return fims_math::pnorm(upper, mean_laa, sd_laa);
279 if (size_bin_index + 1 == population_size_grid_->n_bins) {
280 const Type lower =
static_cast<Type
>(
281 population_size_grid_->edges[population_size_grid_->n_bins - 1]);
282 return fims_math::pnorm(
static_cast<Type
>(2.0) * mean_laa - lower,
287 static_cast<Type
>(population_size_grid_->edges[size_bin_index]);
289 static_cast<Type
>(population_size_grid_->edges[size_bin_index + 1]);
291 return fims_math::pnorm(upper, mean_laa, sd_laa) -
292 fims_math::pnorm(lower, mean_laa, sd_laa);
295 const GrowthProducts<Type>& PreparedGrowthProducts()
const {
296 if (!growth_observation_) {
297 throw std::runtime_error(
298 "GrowthDerivedSizeProvider requires a linked growth object");
301 const GrowthProducts<Type>* growth_products =
302 growth_observation_->TryGetPreparedGrowthProducts();
304 if (!growth_products) {
305 throw std::runtime_error(
306 "GrowthDerivedSizeProvider requires prepared growth products");
309 return *growth_products;
312 std::shared_ptr<GrowthDerivedObservationBase<Type>> growth_observation_;
313 const SizeGrid* population_size_grid_ =
nullptr;
314 std::size_t n_years_ = 0;
315 std::size_t n_ages_ = 0;
316 bool size_products_prepared_ =
false;
317 bool plus_group_warning_emitted_ =
false;
318 SizeProducts<Type> size_products_;
319 fims::Vector<Type> mean_weight_at_age_;
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
void PrepareSizeProducts() override
Prepare size products for the current model state.
Definition growth_derived_size_provider.hpp:67
const Type & MeanWeightAtAge(std::size_t year_index, std::size_t age_index) const override
Mean weight-at-age averaged over the population length-at-age distribution.
Definition growth_derived_size_provider.hpp:229
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:59
void SetPopulationSizeGrid(const SizeGrid *population_size_grid) override
Configure the provider to use the canonical population size grid.
Definition growth_derived_size_provider.hpp:53
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:191
void SetGrowth(std::shared_ptr< GrowthDerivedObservationBase< Type > > growth)
Replace the Growth-derived observation object used by this provider.
Definition growth_derived_size_provider.hpp:249
GrowthDerivedSizeProvider(std::shared_ptr< GrowthDerivedObservationBase< Type > > growth)
Construct a provider linked to a Growth-derived observation object.
Definition growth_derived_size_provider.hpp:45
const SizeGrid * TryGetSizeGrid() const override
Return the biological size grid used by this provider.
Definition growth_derived_size_provider.hpp:49
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:196
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:201
void InvalidatePreparedSizeProducts() override
Invalidate any prepared size state held by this provider.
Definition growth_derived_size_provider.hpp:187
Platform macros and the core FIMS logging system.
#define FIMS_WARNING_LOG(MESSAGE)
Definition def.hpp:648
std::string to_string(T v)
Definition def.hpp:735
A collection of mathematical functions used in FIMS.
const Type ad_max(const Type &a, const Type &b, Type C=1e-5)
Definition fims_math.hpp:380
adapts product-style growth models to the GrowthBase interface used by caa.
The population dynamics of FIMS.
Definition catch_at_age.hpp:45
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
Type & MeanLAA(std::size_t y, std::size_t a, std::size_t s)
Access mean length-at-age by reference.
Definition growth_products.hpp:90
std::size_t n_years
Definition growth_products.hpp:27
Type & SdLAA(std::size_t y, std::size_t a, std::size_t s)
Access standard deviation of length-at-age by reference.
Definition growth_products.hpp:101
std::size_t n_sexes
Definition growth_products.hpp:29
std::size_t n_ages
Definition growth_products.hpp:28
Population-level biological size grid.
Definition size_grid.hpp:26
std::size_t n_bins
Definition size_grid.hpp:27