fn sum_densities_atom(chunk: &[isize],
                      densities: &[Vec<f64>],
                      atoms: &Atoms,
                      voxel_map: &VoxelMap,
                      index: usize,
                      progress_bar: &Bar)
                      -> ChargeSumResult {
    let mut bader_charge =
        vec![vec![0.0; densities.len()]; atoms.positions.len()];
    let mut bader_volume = vec![0.0; atoms.positions.len()];
    let mut surface_distance = vec![f64::INFINITY; atoms.positions.len()];
    chunk.iter()
         .enumerate()
         .try_for_each(|(voxel_index, voxel)| -> Result<()> {
             let p = index * chunk.len() + voxel_index;
             match voxel.cmp(&-1) {
                 // If we are at an interior point sum the charge and volume.
                 std::cmp::Ordering::Greater => {
                     bader_charge[*voxel as usize].iter_mut()
                                                  .zip(densities)
                                                  .for_each(|(bc, density)| {
                                                      *bc += density[p];
                                                  });
                     bader_volume[*voxel as usize] += 1.0;
                 }
                 // If instead it is a weight then it is at a boundary between atoms.
                 std::cmp::Ordering::Less => {
                     let weights = voxel_map.weight_get(*voxel);
                     let atom_number = weights[0] as usize;
                     let minimum_distance = &mut surface_distance[atom_number];
                     let p_cartesian = voxel_map.grid.to_cartesian(p as isize);
                     let p_cartesian =
                         utils::dot(p_cartesian,
                                    voxel_map.grid.voxel_lattice.to_cartesian);
                     let mut p_lll_fractional =
                         utils::dot(p_cartesian,
                                    atoms.reduced_lattice.to_fractional);
                     for f in &mut p_lll_fractional {
                         *f = f.rem_euclid(1.);
                     }
                     let p_lll_cartesian = utils::dot(p_lll_fractional,
                                                      atoms.reduced_lattice
                                                           .to_cartesian);
                     let atom = atoms.reduced_positions[atom_number];
                     for atom_shift in
                         atoms.reduced_lattice.cartesian_shift_matrix.iter()
                     {
                         let distance = {
                             (p_lll_cartesian[0]
                                  - (atom[0] + atom_shift[0]))
                                                              .powi(2)
                                 + (p_lll_cartesian[1]
                                    - (atom[1] + atom_shift[1]))
                                                                .powi(2)
                                 + (p_lll_cartesian[2]
                                    - (atom[2] + atom_shift[2]))
                                                                .powi(2)
                         };
                         if distance < *minimum_distance {
                             *minimum_distance = distance;
                         }
                     }
                     for w in weights.iter() {
                         let maxima = *w as usize;
                         let weight = w - maxima as f64;
                         bader_charge[maxima].iter_mut()
                                             .zip(densities)
                                             .for_each(|(bc, density)| {
                                                 *bc += density[p] * weight;
                                             });
                         bader_volume[maxima] += weight;
                     }
                 }
                 // Vacuum
                 std::cmp::Ordering::Equal => (),
             }
             progress_bar.tick();
             Ok(())
         })
         .context("Iterating through a chunk of the voxel map.")?;
    Ok((bader_charge, bader_volume, surface_distance))
}
/// Sum the densities for when the maxima are Bader atoms.
/// Chunk is a slice of the voxel map.
Sum the densities for when the maxima are Bader atoms.
Chunk is a slice of the voxel map.
Sum the densities for when the maxima are Bader atoms . Chunk is a slice of the voxel map .
fn sum_densities_atom(chunk: &[isize],
                      densities: &[Vec<f64>],
                      atoms: &Atoms,
                      voxel_map: &VoxelMap,
                      index: usize,
                      progress_bar: &Bar)
                      -> ChargeSumResult {
    let mut bader_charge =
        vec![vec![0.0; densities.len()]; atoms.positions.len()];
    let mut bader_volume = vec![0.0; atoms.positions.len()];
    let mut surface_distance = vec![f64::INFINITY; atoms.positions.len()];
    chunk.iter()
         .enumerate()
         .try_for_each(|(voxel_index, voxel)| -> Result<()> {
             let p = index * chunk.len() + voxel_index;
             match voxel.cmp(&-1) {
                 // If we are at an interior point sum the charge and volume.
                 std::cmp::Ordering::Greater => {
                     bader_charge[*voxel as usize].iter_mut()
                                                  .zip(densities)
                                                  .for_each(|(bc, density)| {
                                                      *bc += density[p];
                                                  });
                     bader_volume[*voxel as usize] += 1.0;
                 }
                 // If instead it is a weight then it is at a boundary between atoms.
                 std::cmp::Ordering::Less => {
                     let weights = voxel_map.weight_get(*voxel);
                     let atom_number = weights[0] as usize;
                     let minimum_distance = &mut surface_distance[atom_number];
                     let p_cartesian = voxel_map.grid.to_cartesian(p as isize);
                     let p_cartesian =
                         utils::dot(p_cartesian,
                                    voxel_map.grid.voxel_lattice.to_cartesian);
                     let mut p_lll_fractional =
                         utils::dot(p_cartesian,
                                    atoms.reduced_lattice.to_fractional);
                     for f in &mut p_lll_fractional {
                         *f = f.rem_euclid(1.);
                     }
                     let p_lll_cartesian = utils::dot(p_lll_fractional,
                                                      atoms.reduced_lattice
                                                           .to_cartesian);
                     let atom = atoms.reduced_positions[atom_number];
                     for atom_shift in
                         atoms.reduced_lattice.cartesian_shift_matrix.iter()
                     {
                         let distance = {
                             (p_lll_cartesian[0]
                                  - (atom[0] + atom_shift[0]))
                                                              .powi(2)
                                 + (p_lll_cartesian[1]
                                    - (atom[1] + atom_shift[1]))
                                                                .powi(2)
                                 + (p_lll_cartesian[2]
                                    - (atom[2] + atom_shift[2]))
                                                                .powi(2)
                         };
                         if distance < *minimum_distance {
                             *minimum_distance = distance;
                         }
                     }
                     for w in weights.iter() {
                         let maxima = *w as usize;
                         let weight = w - maxima as f64;
                         bader_charge[maxima].iter_mut()
                                             .zip(densities)
                                             .for_each(|(bc, density)| {
                                                 *bc += density[p] * weight;
                                             });
                         bader_volume[maxima] += weight;
                     }
                 }
                 // Vacuum
                 std::cmp::Ordering::Equal => (),
             }
             progress_bar.tick();
             Ok(())
         })
         .context("Iterating through a chunk of the voxel map.")?;
    Ok((bader_charge, bader_volume, surface_distance))
}
fn sum_densities_atom ( chunk : & [ isize ] , densities : & [ Vec < f64 > ] , atoms : & Atoms , voxel_map : & VoxelMap , index : usize , progress_bar : & Bar ) -> ChargeSumResult { let mut bader_charge = vec ! [ vec [ 0.0 densities len ( ) ] atoms positions len ( ) ] ; let mut bader_volume = vec ! [ 0.0 atoms positions len ( ) ] ; let mut surface_distance = vec ! [ f64 INFINITY atoms positions len ( ) ] ; chunk . iter ( ) . enumerate ( ) . try_for_each ( | ( voxel_index , voxel ) | -> Result < ( ) > { let p = index * chunk . len ( ) + voxel_index ; match voxel . cmp ( & - 1 ) { // If we are at an interior point sum the charge and volume. std :: cmp :: Ordering :: Greater => { bader_charge [ * voxel as usize ] . iter_mut ( ) . zip ( densities ) . for_each ( | ( bc , density ) | { * bc += density [ p ] ; } ) ; bader_volume [ * voxel as usize ] += 1.0 ; } // If instead it is a weight then it is at a boundary between atoms. std :: cmp :: Ordering :: Less => { let weights = voxel_map . weight_get ( * voxel ) ; let atom_number = weights [ 0 ] as usize ; let minimum_distance = & mut surface_distance [ atom_number ] ; let p_cartesian = voxel_map . grid . to_cartesian ( p as isize ) ; let p_cartesian = utils :: dot ( p_cartesian , voxel_map . grid . voxel_lattice . to_cartesian ) ; let mut p_lll_fractional = utils :: dot ( p_cartesian , atoms . reduced_lattice . to_fractional ) ; for f in & mut p_lll_fractional { * f = f . rem_euclid ( 1. ) ; } let p_lll_cartesian = utils :: dot ( p_lll_fractional , atoms . reduced_lattice . to_cartesian ) ; let atom = atoms . reduced_positions [ atom_number ] ; for atom_shift in atoms . reduced_lattice . cartesian_shift_matrix . iter ( ) { let distance = { ( p_lll_cartesian [ 0 ] - ( atom [ 0 ] + atom_shift [ 0 ] ) ) . powi ( 2 ) + ( p_lll_cartesian [ 1 ] - ( atom [ 1 ] + atom_shift [ 1 ] ) ) . powi ( 2 ) + ( p_lll_cartesian [ 2 ] - ( atom [ 2 ] + atom_shift [ 2 ] ) ) . powi ( 2 ) } ; if distance < * minimum_distance { * minimum_distance = distance ; } } for w in weights . iter ( ) { let maxima = * w as usize ; let weight = w - maxima as f64 ; bader_charge [ maxima ] . iter_mut ( ) . zip ( densities ) . for_each ( | ( bc , density ) | { * bc += density [ p ] * weight ; } ) ; bader_volume [ maxima ] += weight ; } } // Vacuum std :: cmp :: Ordering :: Equal => ( ) , } progress_bar . tick ( ) ; Ok ( ( ) ) } ) . context ( " " ) ? ; Ok ( ( bader_charge , bader_volume , surface_distance ) ) }
Sum the densities for when the maxima are Bader atoms.
Sum the densities for when the maxima are Bader atoms .
chunk
&[isize]
densities
&[Vec<f64>]
atoms
&Atoms
voxel_map
&VoxelMap
index
usize
progress_bar
&Bar
chunk
&[isize]
densities
&[Vec<f64>]
atoms
&Atoms
voxel_map
&VoxelMap
index
usize
progress_bar
&Bar