pub fn sum_bader_densities(densities: &[Vec<f64>],
                           voxel_map: &VoxelMap,
                           atoms: &Atoms,
                           atoms_map: Option<&[usize]>,
                           threads: usize,
                           maxima_len: usize,
                           progress_bar: Bar)
                           -> ChargeSumResult {
    let pbar = &progress_bar;
    // Only spawn threads if more than 1 thread is required.
    // This minimises overhead?
    let (mut bader_charge, mut bader_volume, mut surface_distance) =
        match threads.cmp(&1) {
            std::cmp::Ordering::Greater => {
                let mut surface_distance =
                    vec![f64::INFINITY; atoms.positions.len()];
                let mut bader_charge =
                    vec![vec![0.0; densities.len()]; maxima_len];
                let mut bader_volume = vec![0.0; maxima_len];
                // Calculate the size of the vector to be passed to each thread.
                let chunk_size = (voxel_map.voxel_map.len() / threads)
                                 + (voxel_map.voxel_map.len() % threads).min(1);
                thread::scope(|s| {
                let spawned_threads = voxel_map.voxel_map
                                               .chunks(chunk_size)
                                               .enumerate()
                                               .map(|(index, chunk)| {
                                                   if let Some(am) = atoms_map {
                                                       s.spawn(move |_| {
                                          match sum_densities_bader(chunk,
                                                                    densities,
                                                                    am,
                                                                    atoms,
                                                                    voxel_map,
                                                                    index,
                                                                    pbar)
                                  {
                                      Ok(result) => result,
                                      _ => panic!("Unable to sum densities."),
                                  }
                                      })
                                                   } else {
                                                       s.spawn(move |_| {
                                          match sum_densities_atom(chunk,
                                                                   densities,
                                                                   atoms,
                                                                   voxel_map,
                                                                   index,
                                                                   pbar)
                                  {
                                      Ok(result) => result,
                                      _ => panic!("Unable to sum densities."),
                                  }
                                      })
                                                   }
                                               })
                                               .collect::<Vec<_>>();
                // Join each thread and collect the results.
                // If one thread terminates before the other this is not operated on first.
                // Either use the sorted index to remove vacuum from the summation or
                // find a way to operate on finshed threads first (ideally both).
                for thread in spawned_threads {
                    if let Ok((tmp_bc, tmp_bv, tmp_sd)) = thread.join() {
                        for (bc, density) in
                            bader_charge.iter_mut().zip(tmp_bc.into_iter())
                        {
                            bc.iter_mut()
                              .zip(density.iter())
                              .for_each(|(a, b)| {
                                  *a += b;
                              });
                        }
                        bader_volume.iter_mut()
                                    .zip(tmp_bv.into_iter())
                                    .for_each(|(a, b)| {
                                        *a += b;
                                    });
                        surface_distance.iter_mut()
                                        .zip(tmp_sd.into_iter())
                                        .for_each(|(a, b)| {
                                            *a = a.min(b);
                                        });
                    } else {
                        panic!("Unable to join thread in sum_bader_densities.")
                    };
                }
            }).unwrap();
                // The distance isn't square rooted in the calcation of distance to save time.
                // As we need to filter out the infinite distances (atoms with no assigned maxima)
                // we can square root here also.
                surface_distance.iter_mut()
                            .for_each(|d| {
                                match (*d).partial_cmp(&f64::INFINITY) {
                                    Some(std::cmp::Ordering::Less) => *d = d.powf(0.5),
                                    _ => *d = 0.0,
                                }
                            });
                (bader_charge, bader_volume, surface_distance)
            }
            _ => {
                    match atoms_map {
                    Some(am) => sum_densities_bader(&voxel_map.voxel_map,
                                  densities,
                                  am,
                                  atoms,
                                  voxel_map,
                                  0,
                                  pbar).context("Unable to sum bader densities")?,
                    None => sum_densities_atom(&voxel_map.voxel_map,
                                               densities,
                                               atoms,
                                               voxel_map,
                                               0,
                                               pbar).context("Unable to sum bader densities")?
                }
            }
        };
    // The distance isn't square rooted in the calcation of distance to save time.
    // As we need to filter out the infinite distances (atoms with no assigned maxima)
    // we can square root here also.
    for bc in bader_charge.iter_mut() {
        bc.iter_mut().for_each(|a| {
                         *a *= voxel_map.grid.voxel_lattice.volume;
                     });
    }
    bader_volume.iter_mut().for_each(|a| {
                               *a *= voxel_map.grid.voxel_lattice.volume;
                           });
    surface_distance.iter_mut().for_each(|d| {
                                   match (*d).partial_cmp(&f64::INFINITY) {
                                       Some(std::cmp::Ordering::Less) => {
                                           *d = d.powf(0.5)
                                       }
                                       _ => *d = 0.0,
                                   }
                               });
    Ok((bader_charge, bader_volume, surface_distance))
}
/// Sums the densities of each Bader volume.
Sums the densities of each Bader volume.
Sums the densities of each Bader volume .
pub fn sum_bader_densities(densities: &[Vec<f64>],
                           voxel_map: &VoxelMap,
                           atoms: &Atoms,
                           atoms_map: Option<&[usize]>,
                           threads: usize,
                           maxima_len: usize,
                           progress_bar: Bar)
                           -> ChargeSumResult {
    let pbar = &progress_bar;
    // Only spawn threads if more than 1 thread is required.
    // This minimises overhead?
    let (mut bader_charge, mut bader_volume, mut surface_distance) =
        match threads.cmp(&1) {
            std::cmp::Ordering::Greater => {
                let mut surface_distance =
                    vec![f64::INFINITY; atoms.positions.len()];
                let mut bader_charge =
                    vec![vec![0.0; densities.len()]; maxima_len];
                let mut bader_volume = vec![0.0; maxima_len];
                // Calculate the size of the vector to be passed to each thread.
                let chunk_size = (voxel_map.voxel_map.len() / threads)
                                 + (voxel_map.voxel_map.len() % threads).min(1);
                thread::scope(|s| {
                let spawned_threads = voxel_map.voxel_map
                                               .chunks(chunk_size)
                                               .enumerate()
                                               .map(|(index, chunk)| {
                                                   if let Some(am) = atoms_map {
                                                       s.spawn(move |_| {
                                          match sum_densities_bader(chunk,
                                                                    densities,
                                                                    am,
                                                                    atoms,
                                                                    voxel_map,
                                                                    index,
                                                                    pbar)
                                  {
                                      Ok(result) => result,
                                      _ => panic!("Unable to sum densities."),
                                  }
                                      })
                                                   } else {
                                                       s.spawn(move |_| {
                                          match sum_densities_atom(chunk,
                                                                   densities,
                                                                   atoms,
                                                                   voxel_map,
                                                                   index,
                                                                   pbar)
                                  {
                                      Ok(result) => result,
                                      _ => panic!("Unable to sum densities."),
                                  }
                                      })
                                                   }
                                               })
                                               .collect::<Vec<_>>();
                // Join each thread and collect the results.
                // If one thread terminates before the other this is not operated on first.
                // Either use the sorted index to remove vacuum from the summation or
                // find a way to operate on finshed threads first (ideally both).
                for thread in spawned_threads {
                    if let Ok((tmp_bc, tmp_bv, tmp_sd)) = thread.join() {
                        for (bc, density) in
                            bader_charge.iter_mut().zip(tmp_bc.into_iter())
                        {
                            bc.iter_mut()
                              .zip(density.iter())
                              .for_each(|(a, b)| {
                                  *a += b;
                              });
                        }
                        bader_volume.iter_mut()
                                    .zip(tmp_bv.into_iter())
                                    .for_each(|(a, b)| {
                                        *a += b;
                                    });
                        surface_distance.iter_mut()
                                        .zip(tmp_sd.into_iter())
                                        .for_each(|(a, b)| {
                                            *a = a.min(b);
                                        });
                    } else {
                        panic!("Unable to join thread in sum_bader_densities.")
                    };
                }
            }).unwrap();
                // The distance isn't square rooted in the calcation of distance to save time.
                // As we need to filter out the infinite distances (atoms with no assigned maxima)
                // we can square root here also.
                surface_distance.iter_mut()
                            .for_each(|d| {
                                match (*d).partial_cmp(&f64::INFINITY) {
                                    Some(std::cmp::Ordering::Less) => *d = d.powf(0.5),
                                    _ => *d = 0.0,
                                }
                            });
                (bader_charge, bader_volume, surface_distance)
            }
            _ => {
                    match atoms_map {
                    Some(am) => sum_densities_bader(&voxel_map.voxel_map,
                                  densities,
                                  am,
                                  atoms,
                                  voxel_map,
                                  0,
                                  pbar).context("Unable to sum bader densities")?,
                    None => sum_densities_atom(&voxel_map.voxel_map,
                                               densities,
                                               atoms,
                                               voxel_map,
                                               0,
                                               pbar).context("Unable to sum bader densities")?
                }
            }
        };
    // The distance isn't square rooted in the calcation of distance to save time.
    // As we need to filter out the infinite distances (atoms with no assigned maxima)
    // we can square root here also.
    for bc in bader_charge.iter_mut() {
        bc.iter_mut().for_each(|a| {
                         *a *= voxel_map.grid.voxel_lattice.volume;
                     });
    }
    bader_volume.iter_mut().for_each(|a| {
                               *a *= voxel_map.grid.voxel_lattice.volume;
                           });
    surface_distance.iter_mut().for_each(|d| {
                                   match (*d).partial_cmp(&f64::INFINITY) {
                                       Some(std::cmp::Ordering::Less) => {
                                           *d = d.powf(0.5)
                                       }
                                       _ => *d = 0.0,
                                   }
                               });
    Ok((bader_charge, bader_volume, surface_distance))
}
pub fn sum_bader_densities ( densities : & [ Vec < f64 > ] , voxel_map : & VoxelMap , atoms : & Atoms , atoms_map : Option < & [ usize ] > , threads : usize , maxima_len : usize , progress_bar : Bar ) -> ChargeSumResult { let pbar = & progress_bar ; // Only spawn threads if more than 1 thread is required. // This minimises overhead? let ( mut bader_charge , mut bader_volume , mut surface_distance ) = match threads . cmp ( & 1 ) { std :: cmp :: Ordering :: Greater => { let mut surface_distance = vec ! [ f64 INFINITY atoms positions len ( ) ] ; let mut bader_charge = vec ! [ vec [ 0.0 densities len ( ) ] maxima_len ] ; let mut bader_volume = vec ! [ 0.0 maxima_len ] ; // Calculate the size of the vector to be passed to each thread. let chunk_size = ( voxel_map . voxel_map . len ( ) / threads ) + ( voxel_map . voxel_map . len ( ) % threads ) . min ( 1 ) ; thread :: scope ( | s | { let spawned_threads = voxel_map . voxel_map . chunks ( chunk_size ) . enumerate ( ) . map ( | ( index , chunk ) | { if let Some ( am ) = atoms_map { s . spawn ( move | _ | { match sum_densities_bader ( chunk , densities , am , atoms , voxel_map , index , pbar ) { Ok ( result ) => result , _ => panic ! ( " " ) , } } ) } else { s . spawn ( move | _ | { match sum_densities_atom ( chunk , densities , atoms , voxel_map , index , pbar ) { Ok ( result ) => result , _ => panic ! ( " " ) , } } ) } } ) . collect :: < Vec < _ > > ( ) ; // Join each thread and collect the results. // If one thread terminates before the other this is not operated on first. // Either use the sorted index to remove vacuum from the summation or // find a way to operate on finshed threads first (ideally both). for thread in spawned_threads { if let Ok ( ( tmp_bc , tmp_bv , tmp_sd ) ) = thread . join ( ) { for ( bc , density ) in bader_charge . iter_mut ( ) . zip ( tmp_bc . into_iter ( ) ) { bc . iter_mut ( ) . zip ( density . iter ( ) ) . for_each ( | ( a , b ) | { * a += b ; } ) ; } bader_volume . iter_mut ( ) . zip ( tmp_bv . into_iter ( ) ) . for_each ( | ( a , b ) | { * a += b ; } ) ; surface_distance . iter_mut ( ) . zip ( tmp_sd . into_iter ( ) ) . for_each ( | ( a , b ) | { * a = a . min ( b ) ; } ) ; } else { panic ! ( " " ) } ; } } ) . unwrap ( ) ; // The distance isn't square rooted in the calcation of distance to save time. // As we need to filter out the infinite distances (atoms with no assigned maxima) // we can square root here also. surface_distance . iter_mut ( ) . for_each ( | d | { match ( * d ) . partial_cmp ( & f64 :: INFINITY ) { Some ( std :: cmp :: Ordering :: Less ) => * d = d . powf ( 0.5 ) , _ => * d = 0.0 , } } ) ; ( bader_charge , bader_volume , surface_distance ) } _ => { match atoms_map { Some ( am ) => sum_densities_bader ( & voxel_map . voxel_map , densities , am , atoms , voxel_map , 0 , pbar ) . context ( " " ) ? , None => sum_densities_atom ( & voxel_map . voxel_map , densities , atoms , voxel_map , 0 , pbar ) . context ( " " ) ? } } } ; // The distance isn't square rooted in the calcation of distance to save time. // As we need to filter out the infinite distances (atoms with no assigned maxima) // we can square root here also. for bc in bader_charge . iter_mut ( ) { bc . iter_mut ( ) . for_each ( | a | { * a *= voxel_map . grid . voxel_lattice . volume ; } ) ; } bader_volume . iter_mut ( ) . for_each ( | a | { * a *= voxel_map . grid . voxel_lattice . volume ; } ) ; surface_distance . iter_mut ( ) . for_each ( | d | { match ( * d ) . partial_cmp ( & f64 :: INFINITY ) { Some ( std :: cmp :: Ordering :: Less ) => { * d = d . powf ( 0.5 ) } _ => * d = 0.0 , } } ) ; Ok ( ( bader_charge , bader_volume , surface_distance ) ) }
Sums the densities of each Bader volume.
Sums the densities of each Bader volume .
densities
&[Vec<f64>]
voxel_map
&VoxelMap
atoms
&Atoms
atoms_map
Option<&[usize]>
threads
usize
maxima_len
usize
progress_bar
Bar
densities
&[Vec<f64>]
voxel_map
&VoxelMap
atoms
&Atoms
atoms_map
Option<&[usize]>
threads
usize
maxima_len
usize
progress_bar
Bar