| 133 | } |
| 134 | |
| 135 | pub fn partition_atoms( |
| 136 | atom_count: usize, |
| 137 | target_molecules: usize, |
| 138 | strategy: PartitionStrategy, |
| 139 | ) -> Result<Vec<MoleculePartition>, HpcParallelError> { |
| 140 | if atom_count == 0 { |
| 141 | return Ok(Vec::new()); |
| 142 | } |
| 143 | if target_molecules == 0 { |
| 144 | return Err(HpcParallelError::InvalidConfig("target_molecules must be > 0")); |
| 145 | } |
| 146 | let molecules = target_molecules.min(atom_count); |
| 147 | let mut boundaries = Vec::with_capacity(molecules + 1); |
| 148 | boundaries.push(0usize); |
| 149 | for i in 1..molecules { |
| 150 | let b = match strategy { |
| 151 | PartitionStrategy::Linear => i * atom_count / molecules, |
| 152 | PartitionStrategy::Nested => { |
| 153 | ((atom_count as f64) * (i as f64 / molecules as f64).sqrt()).round() as usize |
| 154 | } |
| 155 | }; |
| 156 | let last = *boundaries.last().unwrap_or(&0); |
| 157 | boundaries.push(b.clamp(last + 1, atom_count)); |
| 158 | } |
| 159 | boundaries.push(atom_count); |
| 160 | |
| 161 | let mut partitions = Vec::with_capacity(molecules); |
| 162 | for i in 0..molecules { |
| 163 | let start = boundaries[i]; |
| 164 | let end = boundaries[i + 1]; |
| 165 | if end > start { |
| 166 | partitions.push(MoleculePartition { molecule_id: partitions.len(), start, end }); |
| 167 | } |
| 168 | } |
| 169 | Ok(partitions) |
| 170 | } |
| 171 | |
| 172 | pub fn run_parallel<A, R, F, E>( |
| 173 | atoms: &[A], |