1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
use core::{num::Wrapping, ops::ControlFlow};
use necsim_core_bond::PositiveF64;
use crate::{
cogs::{
event_sampler::EventHandler, ActiveLineageSampler, CoalescenceSampler, DispersalSampler,
EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore,
SpeciationProbability, TurnoverRate,
},
event::{DispersalEvent, SpeciationEvent},
lineage::Lineage,
reporter::Reporter,
simulation::Simulation,
};
impl<
M: MathsCore,
H: Habitat<M>,
G: RngCore<M>,
S: LineageStore<M, H>,
X: EmigrationExit<M, H, G, S>,
D: DispersalSampler<M, H, G>,
C: CoalescenceSampler<M, H, S>,
T: TurnoverRate<M, H>,
N: SpeciationProbability<M, H>,
E: EventSampler<M, H, G, S, X, D, C, T, N>,
I: ImmigrationEntry<M>,
A: ActiveLineageSampler<M, H, G, S, X, D, C, T, N, E, I>,
> Simulation<M, H, G, S, X, D, C, T, N, E, I, A>
{
#[inline]
pub(in super::super) fn simulate_and_report_local_step_or_early_stop_or_finish<
P: Reporter,
F: FnOnce(PositiveF64) -> ControlFlow<(), ()>,
>(
&mut self,
reporter: &mut P,
early_peek: F,
) -> ControlFlow<(), ()> {
self.with_mut_split_active_lineage_sampler_and_rng_and_migration_balance(
|active_lineage_sampler, simulation, rng, migration_balance| {
// Fetch the next `chosen_lineage` to be simulated at `event_time`
if let Some((chosen_lineage, event_time)) = active_lineage_sampler
.pop_active_lineage_and_event_time(simulation, rng, early_peek)
{
let global_reference = chosen_lineage.global_reference.clone();
// Sample the next `event` for the `chosen_lineage`
// or emigrate the `chosen_lineage`
let dispersal =
simulation.with_mut_split_event_sampler(|event_sampler, simulation| {
event_sampler.sample_event_for_lineage_at_event_time_or_emigrate(
chosen_lineage,
event_time,
simulation,
rng,
EventHandler {
speciation: |event: SpeciationEvent, reporter: &mut P| {
// Report the local speciation event
reporter.report_speciation((&event).into());
None
},
dispersal: |event: DispersalEvent, reporter: &mut P| {
// Report the local dispersal event
reporter.report_dispersal((&event).into());
if event.interaction.is_coalescence() {
None
} else {
Some(event.target)
}
},
emigration: |_| {
// Emigration increments the migration balance
// (less local work)
*migration_balance += Wrapping(1_u64);
None
},
},
reporter,
)
});
if let Some(dispersal_target) = dispersal {
active_lineage_sampler.push_active_lineage(
Lineage {
global_reference,
indexed_location: dispersal_target,
last_event_time: event_time.into(),
},
simulation,
rng,
);
}
ControlFlow::Continue(())
} else {
ControlFlow::Break(())
}
},
)
}
}