/// Identify which pairs of atoms are close enough to interact and build a list of
/// interactions.
///
/// This will warn or generate errors when bond lengths fall into the reactive regime,
/// as if the `check_distances` method was called.
Identify which pairs of atoms are close enough to interact and build a list of
interactions.

This will warn or generate errors when bond lengths fall into the reactive regime,
as if the `check_distances` method was called.
Identify which pairs of atoms are close enough to interact and build a list of interactions . This will warn or generate errors when bond lengths fall into the reactive regime as if the ` check_distances ` method was called .
pub fn compute(
        potential: P,
        coords: &Coords,
        types: &[P::AtomType],
        bond_graph: &PeriodicGraph,
    ) -> FailResult<Self> {
        let mut bond_div = IndexVec::<SiteI, _>::from_raw(vec![BondI(0)]);
        bond_div.raw.reserve(bond_graph.node_count());
        let mut bond_source = IndexVec::<BondI, SiteI>::with_capacity(bond_graph.edge_count());
        let mut bond_target = IndexVec::<BondI, SiteI>::with_capacity(bond_graph.edge_count());
        let mut bond_image_diff = IndexVec::<BondI, V3<i32>>::with_capacity(bond_graph.edge_count());
        let site_type = IndexVec::<SiteI, _>::from_raw(types.to_vec());
        let carts = coords.to_carts();
        // Make a pass to get all the bond divs right.
        for node in bond_graph.node_indices() {
            let site_i = SiteI(node.index());
            for frac_bond_ij in bond_graph.frac_bonds_from(site_i.index()) {
                let site_j = SiteI(frac_bond_ij.to);
                let cart_vector = frac_bond_ij.cart_vector_using_carts(coords.lattice(), &carts);
                if let IsInteracting(false) = potential.check_distance(
                    cart_vector.norm(), (site_type[site_i].clone(), site_type[site_j].clone()),
                )? {
                    continue;
                }
                bond_source.push(site_i);
                bond_target.push(site_j);
                bond_image_diff.push(frac_bond_ij.image_diff);
            } // for bond_ij
            let num_bonds = bond_target.len() - bond_div.raw.last().unwrap().index();
            if let Some(max_bonds) = P::max_bonds() {
                if num_bonds > max_bonds {
                    bail!("An atom has too many bonds! ({}, max: {})", num_bonds, max_bonds);
                }
            }
            bond_div.push(BondI(bond_target.len()));
        } // for node
        // Get the index of each bond's reverse.
        let mut bond_reverse_index = IndexVec::<BondI, _>::new();
        // We can no longer use bond_graph.frac_bonds_from because not all bonds in the input
        // graph are represented in our vectors.
        let frac_bonds_from = |site_i: SiteI| {
            let range = bond_div[site_i].0..bond_div[site_i.next()].0;
            zip_eq!(
                &bond_source.raw[range.clone()],
                &bond_target.raw[range.clone()],
                &bond_image_diff.raw[range.clone()],
            ).map(|(&SiteI(from), &SiteI(to), &image_diff)| FracBond { from, to, image_diff })
        };
        for node in bond_graph.node_indices() {
            let site_i = SiteI(node.index());
            for frac_bond_ij in frac_bonds_from(site_i) {
                let site_j = SiteI(frac_bond_ij.to);
                let sbindex_ji = {
                    frac_bonds_from(site_j)
                        .position(|bond| frac_bond_ij == bond.flip())
                };
                let sbindex_ji = match sbindex_ji {
                    Some(x) => x,
                    None => bail!("A bond has no counterpart in the reverse direction!"),
                };
                let bond_ji = BondI(bond_div[site_j].0 + sbindex_ji);
                bond_reverse_index.push(bond_ji);
            } // for bond_ij
        } // for node
        assert_eq!(bond_reverse_index.len(), bond_div.raw.last().unwrap().0);
        Ok(Interactions {
            potential, bond_div, site_type,
            bond_target, bond_image_diff, bond_reverse_index, bond_source,
        })
    }
pub fn compute ( potential : P , coords : & Coords , types : & [ P :: AtomType ] , bond_graph : & PeriodicGraph , ) -> FailResult < Self > { let mut bond_div = IndexVec :: < SiteI , _ > :: from_raw ( vec ! [ BondI ( 0 ) ] ) ; bond_div . raw . reserve ( bond_graph . node_count ( ) ) ; let mut bond_source = IndexVec :: < BondI , SiteI > :: with_capacity ( bond_graph . edge_count ( ) ) ; let mut bond_target = IndexVec :: < BondI , SiteI > :: with_capacity ( bond_graph . edge_count ( ) ) ; let mut bond_image_diff = IndexVec :: < BondI , V3 < i32 > > :: with_capacity ( bond_graph . edge_count ( ) ) ; let site_type = IndexVec :: < SiteI , _ > :: from_raw ( types . to_vec ( ) ) ; let carts = coords . to_carts ( ) ; // Make a pass to get all the bond divs right. for node in bond_graph . node_indices ( ) { let site_i = SiteI ( node . index ( ) ) ; for frac_bond_ij in bond_graph . frac_bonds_from ( site_i . index ( ) ) { let site_j = SiteI ( frac_bond_ij . to ) ; let cart_vector = frac_bond_ij . cart_vector_using_carts ( coords . lattice ( ) , & carts ) ; if let IsInteracting ( false ) = potential . check_distance ( cart_vector . norm ( ) , ( site_type [ site_i ] . clone ( ) , site_type [ site_j ] . clone ( ) ) , ) ? { continue ; } bond_source . push ( site_i ) ; bond_target . push ( site_j ) ; bond_image_diff . push ( frac_bond_ij . image_diff ) ; } // for bond_ij let num_bonds = bond_target . len ( ) - bond_div . raw . last ( ) . unwrap ( ) . index ( ) ; if let Some ( max_bonds ) = P :: max_bonds ( ) { if num_bonds > max_bonds { bail ! ( " " num_bonds max_bonds ) ; } } bond_div . push ( BondI ( bond_target . len ( ) ) ) ; } // for node // Get the index of each bond's reverse. let mut bond_reverse_index = IndexVec :: < BondI , _ > :: new ( ) ; // We can no longer use bond_graph.frac_bonds_from because not all bonds in the input // graph are represented in our vectors. let frac_bonds_from = | site_i : SiteI | { let range = bond_div [ site_i ] . 0 .. bond_div [ site_i . next ( ) ] . 0 ; zip_eq ! ( bond_source raw [ range clone ( ) ] bond_target raw [ range clone ( ) ] bond_image_diff raw [ range clone ( ) ] ) . map ( | ( & SiteI ( from ) , & SiteI ( to ) , & image_diff ) | FracBond { from , to , image_diff } ) } ; for node in bond_graph . node_indices ( ) { let site_i = SiteI ( node . index ( ) ) ; for frac_bond_ij in frac_bonds_from ( site_i ) { let site_j = SiteI ( frac_bond_ij . to ) ; let sbindex_ji = { frac_bonds_from ( site_j ) . position ( | bond | frac_bond_ij == bond . flip ( ) ) } ; let sbindex_ji = match sbindex_ji { Some ( x ) => x , None => bail ! ( " " ) , } ; let bond_ji = BondI ( bond_div [ site_j ] . 0 + sbindex_ji ) ; bond_reverse_index . push ( bond_ji ) ; } // for bond_ij } // for node assert_eq ! ( bond_reverse_index len ( ) bond_div raw last ( ) unwrap ( ) 0 ) ; Ok ( Interactions { potential , bond_div , site_type , bond_target , bond_image_diff , bond_reverse_index , bond_source , } ) }
Identify which pairs of atoms are close enough to interact and build a list of
interactions.
Identify which pairs of atoms are close enough to interact and build a list of interactions .
potential
P
coords
&Coords
types
&[P::AtomType]
bond_graph
&PeriodicGraph