Commit 28c69dac authored by Adam Reichold's avatar Adam Reichold
Browse files

Add initialiser to produce new insects at constant rate.

parent 15bd2ece
Pipeline #87709 passed with stage
in 7 minutes
......@@ -421,6 +421,12 @@ Finally, an associative set of lists of messages used to relocate mobile entitie
(0..size).filter(|dest| *dest != rank && grid.is_reachable(&params, max_speed, *dest)),
);
let initialiser = Initialiser {
position: Box::new(position),
next_hoverfly: params.init.next_hoverfly(&params, &mut rng),
next_solitary_bee: params.init.next_solitary_bee(&params, &mut rng),
};
Self {
params,
world: World {
......@@ -453,6 +459,86 @@ Finally, an associative set of lists of messages used to relocate mobile entitie
nest_locations: KDTree::new(nest_locations.into()),
visible_nest_locations: Default::default(),
relocations,
initialiser,
}
}
}
\end{code}
TODO
\begin{code}
pub struct Initialiser {
pub position: Box<dyn Fn(&mut Rng) -> Vector>,
pub next_hoverfly: Tick,
pub next_solitary_bee: Tick,
}
impl Initialiser {
#[allow(clippy::too_many_arguments)]
pub fn add_hoverflies(
&mut self,
params: &Params,
grid: &Grid,
tick: Tick,
hoverflies: &mut Vec<Hoverfly>,
rng: &mut Rng,
next_id: &mut NextId,
temporal_network: &mut TemporalNetwork,
) {
while tick >= self.next_hoverfly {
self.next_hoverfly += params.init.next_hoverfly(params, rng);
let position = (self.position)(rng);
let dest = grid.location(&position);
if dest == grid.rank {
let id = next_id.get();
let hoverfly = Hoverfly::new(params, NonZeroU32::new(id).unwrap(), position, rng);
hoverflies.push(hoverfly);
if params.trace_temporal_network {
temporal_network
.node_additions
.push((tick, id, hoverfly.insect.species));
}
}
}
}
#[allow(clippy::too_many_arguments)]
pub fn add_solitary_bees(
&mut self,
params: &Params,
grid: &Grid,
tick: Tick,
solitary_bees: &mut Vec<SolitaryBee>,
rng: &mut Rng,
next_id: &mut NextId,
temporal_network: &mut TemporalNetwork,
) {
while tick >= self.next_solitary_bee {
self.next_solitary_bee += params.init.next_solitary_bee(params, rng);
let position = (self.position)(rng);
let dest = grid.location(&position);
if dest == grid.rank {
let id = next_id.get();
let solitary_bee =
SolitaryBee::new(params, NonZeroU32::new(id).unwrap(), position, rng);
solitary_bees.push(solitary_bee);
if params.trace_temporal_network {
temporal_network
.node_additions
.push((tick, id, solitary_bee.insect.species));
}
}
}
}
}
......
......@@ -39,6 +39,7 @@ use crate::{
},
grid::Grid,
hoverfly::{Clutch, ClutchEvent, ClutchLocation, Hoverfly},
init::Initialiser,
insect::Species as InsectSpecies,
observer::{Observation, Observer},
params::Params,
......@@ -136,6 +137,7 @@ pub struct Model {
pub nest_locations: KDTree<NestLocation>,
visible_nest_locations: Vec<&'static NestLocation>,
relocations: MailBoxes<Relocation>,
initialiser: Initialiser,
}
pub type FlowerContaminators = HashMap<(TaggedIndex, u16), Vec<(u32, Tick)>>;
......@@ -261,6 +263,7 @@ impl Model {
&self.nest_locations,
&mut self.visible_nest_locations,
&mut self.relocations,
&mut self.initialiser,
);
process.exchange(&mut self.relocations);
......@@ -364,6 +367,7 @@ impl World {
nest_locations: &KDTree<NestLocation>,
visible_nest_locations: &mut Vec<&'static NestLocation>,
relocations: &mut MailBoxes<Relocation>,
initialiser: &mut Initialiser,
) {
FlowerPatchEvent::process(
flower_patch_events,
......@@ -454,6 +458,20 @@ by swapping b and e.
idx += 1;
}
initialiser.add_hoverflies(
params,
grid,
self.tick,
&mut self.hoverflies,
&mut self.rng,
&mut self.next_id,
&mut self.temporal_network,
);
while visited_flowers[0].len() < self.hoverflies.len() {
visited_flowers[0].push(Vec::new());
}
\end{code}
Note that the entries of the \inlinecode{visited\_flowers} arrays are never discarded to avoid the overhead of repeatedly freeing and allocating memory. This is possible as while these lists of flowers need to be kept available as long as an insect forages at a flower patch, they can be discarded as soon as the flower patch is left and are regenerated when another flower patch is entered. Since the need for a relocation requires a change in position, it also implies that the insect in question is not currently foraging at a flower patch. After a relocation, an insect can therefore be associated with a previously discarded list of flowers to reuse the underlying allocation instead of including the list of flowers in the transferred entity state.
......
......@@ -312,7 +312,7 @@ The parameters of the random walk used to model insect flight are based on \auto
solitary_bees: vec![solitary_bee].into(),
bumblebees: vec![bumblebee].into(),
transect: Default::default(),
init: Default::default(),
init: Box::new(Init::new(tick)),
trace_temporal_network: false,
}
}
......@@ -387,10 +387,12 @@ pub struct Init {
pub empty_flower_patches: Bernoulli,
pub hoverflies: u32,
pub hoverfly_species: WeightedIndex<usize>,
pub next_hoverfly: Exp<f64>,
pub clutches: u32,
pub clutch_capacity: Pareto<f32>,
pub solitary_bees: u32,
pub solitary_bee_species: WeightedIndex<usize>,
pub next_solitary_bee: Exp<f64>,
pub nests: u32,
pub bumblebee_species: WeightedIndex<usize>,
pub colonies: u32,
......@@ -398,8 +400,8 @@ pub struct Init {
pub infection: Arc<dyn Infection + Send + Sync>,
}
impl Default for Init {
fn default() -> Self {
impl Init {
fn new(tick: Tick) -> Self {
Self {
seed: 0,
landscape: None,
......@@ -410,10 +412,12 @@ impl Default for Init {
empty_flower_patches: Bernoulli::new(0.9).unwrap(),
hoverflies: 3_000,
hoverfly_species: WeightedIndex::new(&[1]).unwrap(),
next_hoverfly: Exp::new(Rate::per_day(1. / 15.) * 3_000. * tick).unwrap(),
clutches: 3_000,
clutch_capacity: Pareto::new(50., 5.).unwrap(),
solitary_bees: 3_000,
solitary_bee_species: WeightedIndex::new(&[1]).unwrap(),
next_solitary_bee: Exp::new(f64::INFINITY).unwrap(),
nests: 12_000,
bumblebee_species: WeightedIndex::new(&[1]).unwrap(),
colonies: 15,
......@@ -424,6 +428,14 @@ impl Default for Init {
}
impl Init {
pub fn next_hoverfly(&self, params: &Params, rng: &mut Rng) -> Tick {
params.tick * self.next_hoverfly.sample(rng) as i64
}
pub fn next_solitary_bee(&self, params: &Params, rng: &mut Rng) -> Tick {
params.tick * self.next_solitary_bee.sample(rng) as i64
}
pub fn clutch_capacity(&self, rng: &mut Rng) -> u16 {
self.clutch_capacity.sample(rng).ceil() as u16
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment