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(())
                }
            },
        )
    }
}