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
use core::num::Wrapping;
use crate::{
cogs::{
ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler,
Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, SpeciationProbability,
TurnoverRate,
},
event::DispersalEvent,
lineage::{Lineage, MigratingLineage},
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>
{
pub(in super::super) fn simulate_and_report_immigration_step<P: Reporter>(
&mut self,
reporter: &mut P,
migrating_lineage: MigratingLineage,
) {
self.with_mut_split_active_lineage_sampler_and_rng_and_migration_balance(
|active_lineage_sampler, simulation, rng, migration_balance| {
// Immigration decrements the migration balance (extra external work)
*migration_balance -= Wrapping(1_u64);
// Sample the missing coalescence using the random sample generated
// in the remote sublandscape from where the lineage emigrated
let (dispersal_target, interaction) = simulation
.coalescence_sampler
.sample_interaction_at_location(
migrating_lineage.dispersal_target,
&simulation.habitat,
&simulation.lineage_store,
migrating_lineage.coalescence_rng_sample,
);
// NOTE: event time rules
// - event time monotonically increases locally
// - events from the same individual must have unique event times
// - events from different individuals should not, but can have the the same
// event time - currently this can only occur through partitioning / in the
// independent algorithm
// TODO: inconsistency between monolithic and independent algorithm
// - a jumps to b at the same time as b jumps to a
// - independent: no coalescence occurs
// - monolithic: coalescence will occur, which one depends on which one is
// executed first, i.e. random
// In the event of migration without coalescence, the lineage has
// to be added to the active lineage sampler and lineage store
if !interaction.is_coalescence() {
active_lineage_sampler.push_active_lineage(
Lineage {
global_reference: migrating_lineage.global_reference.clone(),
indexed_location: dispersal_target.clone(),
last_event_time: migrating_lineage.event_time.into(),
},
simulation,
rng,
);
}
// Report the migration dispersal event
reporter.report_dispersal(
&DispersalEvent {
origin: migrating_lineage.dispersal_origin,
prior_time: migrating_lineage.prior_time,
event_time: migrating_lineage.event_time,
global_lineage_reference: migrating_lineage.global_reference,
target: dispersal_target,
interaction,
}
.into(),
);
},
);
}
}