#[must_use]
pub fn competition_growth(
population: f32,
growth_rate: f32,
carrying_capacity: f32,
competitor: f32,
alpha: f32,
) -> f32 {
if carrying_capacity <= 0.0 {
tracing::warn!(
carrying_capacity,
"competition_growth called with non-positive carrying capacity"
);
return 0.0;
}
let result =
growth_rate * population * (1.0 - (population + alpha * competitor) / carrying_capacity);
tracing::trace!(
population,
growth_rate,
carrying_capacity,
competitor,
alpha,
result,
"competition_growth"
);
result
}
#[must_use]
pub fn shannon_diversity(proportions: &[f32]) -> f32 {
let mut h = 0.0_f32;
for &p in proportions {
if p > 0.0 {
h -= p * p.ln();
}
}
tracing::trace!(
species_count = proportions.len(),
diversity = h,
"shannon_diversity"
);
h
}
#[must_use]
pub fn net_primary_productivity(gross_productivity: f32, respiration: f32) -> f32 {
let npp = (gross_productivity - respiration).max(0.0);
tracing::trace!(
gross_productivity,
respiration,
npp,
"net_primary_productivity"
);
npp
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn competition_reduces_growth() {
let alone = competition_growth(50.0, 0.1, 1000.0, 0.0, 0.5);
let competing = competition_growth(50.0, 0.1, 1000.0, 200.0, 0.5);
assert!(competing < alone);
}
#[test]
fn shannon_single_species_zero() {
let h = shannon_diversity(&[1.0]);
assert!(h.abs() < 0.001);
}
#[test]
fn shannon_equal_mix_higher() {
let unequal = shannon_diversity(&[0.9, 0.1]);
let equal = shannon_diversity(&[0.5, 0.5]);
assert!(equal > unequal);
}
#[test]
fn npp_positive() {
assert!(net_primary_productivity(1000.0, 400.0) > 0.0);
}
#[test]
fn npp_zero_when_respiration_exceeds() {
assert_eq!(net_primary_productivity(100.0, 200.0), 0.0);
}
#[test]
fn competition_zero_carrying_capacity() {
assert_eq!(competition_growth(50.0, 0.1, 0.0, 0.0, 0.5), 0.0);
}
#[test]
fn competition_at_carrying_capacity() {
let g = competition_growth(1000.0, 0.1, 1000.0, 0.0, 0.5);
assert!(g.abs() < 0.01, "at capacity, growth should be ~0");
}
#[test]
fn shannon_empty_slice() {
assert_eq!(shannon_diversity(&[]), 0.0);
}
#[test]
fn shannon_diversity_increases_with_species() {
let two = shannon_diversity(&[0.5, 0.5]);
let four = shannon_diversity(&[0.25, 0.25, 0.25, 0.25]);
assert!(four > two, "more equal species = higher diversity");
}
#[test]
fn npp_equal_respiration() {
assert_eq!(net_primary_productivity(500.0, 500.0), 0.0);
}
}