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
107
108
109
110
111
112
use necsim_core::{
    cogs::{MathsCore, RngCore},
    reporter::Reporter,
};
use necsim_impls_std::event_log::recorder::EventLogConfig;
use rustcoalescence_algorithms::AlgorithmDispatch;
use rustcoalescence_scenarios::Scenario;
use serde::{Deserialize, Serialize};

use necsim_partitioning_core::partition::PartitionSize;

#[derive(Debug, Serialize, Deserialize)]
pub enum Partitioning {
    Monolithic(necsim_partitioning_monolithic::MonolithicPartitioning),
    #[cfg(feature = "mpi-partitioning")]
    #[serde(alias = "MPI")]
    Mpi(necsim_partitioning_mpi::MpiPartitioning),
    #[cfg(feature = "threads-partitioning")]
    Threads(necsim_partitioning_threads::ThreadsPartitioning),
}

impl Partitioning {
    pub fn get_size(&self) -> PartitionSize {
        use necsim_partitioning_core::Partitioning;

        match self {
            Self::Monolithic(partitioning) => partitioning.get_size(),
            #[cfg(feature = "mpi-partitioning")]
            Self::Mpi(partitioning) => partitioning.get_size(),
            #[cfg(feature = "threads-partitioning")]
            Self::Threads(partitioning) => partitioning.get_size(),
        }
    }

    pub fn get_event_log_check(&self) -> (anyhow::Result<()>, anyhow::Result<()>) {
        match self {
            Self::Monolithic(_) => (Ok(()), Ok(())),
            #[cfg(feature = "mpi-partitioning")]
            Self::Mpi(_) => (
                Err(anyhow::anyhow!(
                    necsim_partitioning_mpi::MpiLocalPartitionError::MissingEventLog
                )),
                Ok(()),
            ),
            #[cfg(feature = "threads-partitioning")]
            Self::Threads(_) => (
                Err(anyhow::anyhow!(
                    necsim_partitioning_mpi::MpiLocalPartitionError::MissingEventLog
                )),
                Ok(()),
            ),
        }
    }

    #[cfg_attr(
        not(any(
            feature = "gillespie-algorithms",
            feature = "independent-algorithm",
            feature = "cuda-algorithm"
        )),
        allow(dead_code)
    )]
    pub fn get_logical_partition_size<
        M: MathsCore,
        G: RngCore<M>,
        O: Scenario<M, G>,
        R: Reporter,
        A: AlgorithmDispatch<M, G, O, R>,
    >(
        &self,
        algorithm_args: &A::Arguments,
    ) -> PartitionSize {
        match self {
            Partitioning::Monolithic(partitioning) => {
                A::get_logical_partition_size(algorithm_args, partitioning)
            },
            #[cfg(feature = "mpi-partitioning")]
            Partitioning::Mpi(partitioning) => {
                A::get_logical_partition_size(algorithm_args, partitioning)
            },
            #[cfg(feature = "threads-partitioning")]
            Partitioning::Threads(partitioning) => {
                A::get_logical_partition_size(algorithm_args, partitioning)
            },
        }
    }

    #[cfg_attr(
        not(any(
            feature = "gillespie-algorithms",
            feature = "independent-algorithm",
            feature = "cuda-algorithm"
        )),
        allow(dead_code)
    )]
    pub fn will_report_live(&self, event_log: &Option<EventLogConfig>) -> bool {
        // TODO: get this information from the partitioning
        match self {
            Partitioning::Monolithic(_) => event_log.is_none(),
            #[cfg(feature = "mpi-partitioning")]
            Partitioning::Mpi(_) => false,
            #[cfg(feature = "threads-partitioning")]
            Partitioning::Threads(_) => false,
        }
    }
}

impl Default for Partitioning {
    fn default() -> Self {
        Self::Monolithic(necsim_partitioning_monolithic::MonolithicPartitioning::default())
    }
}