fn compute_using_frac_bonds(
        parallel: bool,
        params: &crespi_imp::Params,
        coords: &Coords,
        meta: CommonMeta,
        normal_info: &NormalInfo,
        interaction_pairs: Vec<FracBond>, // to be monomorphic
    ) -> FailResult<(f64, Vec<BondGrad>)> {
        let elements: meta::SiteElements = meta.pick();
        let lattice = coords.lattice();
        let carts = coords.to_carts();

        // HACK: collect to vec so that it implements IntoParallelIterator
        let interaction_pairs = interaction_pairs.into_iter().filter(|bond| bond.is_canonical()).collect::<Vec<_>>();
        // HACK: collect from Rc<[_]> to Vec to impl Send
        let elements = elements.iter().cloned().collect::<Vec<_>>();

        let (part_values, bond_grads) = match normal_info {
            NormalInfo::Z { } => {
                CondIterator::new(interaction_pairs, parallel)
                    .map(|bond| {
                        debug_assert!(bond.is_canonical());
                        debug_assert_eq!(elements[bond.from], Element::CARBON);
                        debug_assert_eq!(elements[bond.to], Element::CARBON);
                        let cart_vector = bond.cart_vector_using_carts(lattice, &carts);
                        let (part_value, part_grad) = params.compute_z(cart_vector);

                        let bond_grad = BondGrad {
                            plus_site: bond.to,
                            minus_site: bond.from,
                            grad: part_grad,
                            cart_vector,
                        };
                        (part_value, bond_grad)
                    }).unzip()
            },

            &NormalInfo::NotZ { kind, ref intralayer_graph } => {
                let normals = Normals::compute(intralayer_graph, coords, kind)?;

                let (part_values, grad_items): (Vec<_>, Vec<_>) = {
                    CondIterator::new(interaction_pairs, parallel)
                        .map(|bond| {
                            debug_assert!(bond.is_canonical());
                            debug_assert_eq!(elements[bond.from], Element::CARBON);
                            debug_assert_eq!(elements[bond.to], Element::CARBON);
                            let cart_vector = bond.cart_vector_using_carts(lattice, &carts);
                            let ni = normals.lookup(bond.from);
                            let nj = normals.lookup(bond.to);

                            let crespi_imp::Output {
                                value, grad_rij, grad_ni, grad_nj,
                            } = params.compute(cart_vector, ni, nj);

                            let bond_grad = BondGrad {
                                plus_site: bond.to,
                                minus_site: bond.from,
                                grad: grad_rij,
                                cart_vector,
                            };
                            (value, (bond_grad, grad_ni, grad_nj))
                        }).unzip()
                };

                let mut bond_grads = Vec::with_capacity(grad_items.len() + 2 * coords.len());
                let mut normal_grads = vec![V3::zero(); coords.len()];
                for (bond_grad, grad_ni, grad_nj) in grad_items {
                    bond_grads.push(bond_grad);
                    normal_grads[bond_grad.minus_site] += grad_ni;
                    normal_grads[bond_grad.plus_site] += grad_nj;
                }

                for (site, d_normal) in normal_grads.into_iter().enumerate() {
                    bond_grads.extend(normals.get_bond_grad_terms(site, d_normal));
                }

                (part_values, bond_grads)
            }, // NormalInfo::NotZ => { ... }
        }; // let (part_values, bond_grads) = match normal_info { ... }
        let value = part_values.iter().sum();
        Ok((value, bond_grads))
    }
/// Compute terms for all of the provided FracBonds, possibly in parallel.
///
/// For z normals, one term is produced per interlayer pair interaction.  For other normals,
/// additional terms are produced for intralayer interactions. (each intralayer bond will appear
/// multiple times, with the endpoint atoms listed in arbitrary order)
Compute terms for all of the provided FracBonds, possibly in parallel.
For z normals, one term is produced per interlayer pair interaction.  For other normals,
additional terms are produced for intralayer interactions. (each intralayer bond will appear
multiple times, with the endpoint atoms listed in arbitrary order)
Compute terms for all of the provided FracBonds possibly in parallel . For z normals one term is produced per interlayer pair interaction . For other normals additional terms are produced for intralayer interactions . ( each intralayer bond will appear multiple times with the endpoint atoms listed in arbitrary order )
fn compute_using_frac_bonds(
        parallel: bool,
        params: &crespi_imp::Params,
        coords: &Coords,
        meta: CommonMeta,
        normal_info: &NormalInfo,
        interaction_pairs: Vec<FracBond>, // to be monomorphic
    ) -> FailResult<(f64, Vec<BondGrad>)> {
        let elements: meta::SiteElements = meta.pick();
        let lattice = coords.lattice();
        let carts = coords.to_carts();
        // HACK: collect to vec so that it implements IntoParallelIterator
        let interaction_pairs = interaction_pairs.into_iter().filter(|bond| bond.is_canonical()).collect::<Vec<_>>();
        // HACK: collect from Rc<[_]> to Vec to impl Send
        let elements = elements.iter().cloned().collect::<Vec<_>>();
        let (part_values, bond_grads) = match normal_info {
            NormalInfo::Z { } => {
                CondIterator::new(interaction_pairs, parallel)
                    .map(|bond| {
                        debug_assert!(bond.is_canonical());
                        debug_assert_eq!(elements[bond.from], Element::CARBON);
                        debug_assert_eq!(elements[bond.to], Element::CARBON);
                        let cart_vector = bond.cart_vector_using_carts(lattice, &carts);
                        let (part_value, part_grad) = params.compute_z(cart_vector);
                        let bond_grad = BondGrad {
                            plus_site: bond.to,
                            minus_site: bond.from,
                            grad: part_grad,
                            cart_vector,
                        };
                        (part_value, bond_grad)
                    }).unzip()
            },
            &NormalInfo::NotZ { kind, ref intralayer_graph } => {
                let normals = Normals::compute(intralayer_graph, coords, kind)?;
                let (part_values, grad_items): (Vec<_>, Vec<_>) = {
                    CondIterator::new(interaction_pairs, parallel)
                        .map(|bond| {
                            debug_assert!(bond.is_canonical());
                            debug_assert_eq!(elements[bond.from], Element::CARBON);
                            debug_assert_eq!(elements[bond.to], Element::CARBON);
                            let cart_vector = bond.cart_vector_using_carts(lattice, &carts);
                            let ni = normals.lookup(bond.from);
                            let nj = normals.lookup(bond.to);
                            let crespi_imp::Output {
                                value, grad_rij, grad_ni, grad_nj,
                            } = params.compute(cart_vector, ni, nj);
                            let bond_grad = BondGrad {
                                plus_site: bond.to,
                                minus_site: bond.from,
                                grad: grad_rij,
                                cart_vector,
                            };
                            (value, (bond_grad, grad_ni, grad_nj))
                        }).unzip()
                };
                let mut bond_grads = Vec::with_capacity(grad_items.len() + 2 * coords.len());
                let mut normal_grads = vec![V3::zero(); coords.len()];
                for (bond_grad, grad_ni, grad_nj) in grad_items {
                    bond_grads.push(bond_grad);
                    normal_grads[bond_grad.minus_site] += grad_ni;
                    normal_grads[bond_grad.plus_site] += grad_nj;
                }
                for (site, d_normal) in normal_grads.into_iter().enumerate() {
                    bond_grads.extend(normals.get_bond_grad_terms(site, d_normal));
                }
                (part_values, bond_grads)
            }, // NormalInfo::NotZ => { ... }
        }; // let (part_values, bond_grads) = match normal_info { ... }
        let value = part_values.iter().sum();
        Ok((value, bond_grads))
    }
fn compute_using_frac_bonds ( parallel : bool , params : & crespi_imp :: Params , coords : & Coords , meta : CommonMeta , normal_info : & NormalInfo , interaction_pairs : Vec < FracBond > , // to be monomorphic ) -> FailResult < ( f64 , Vec < BondGrad > ) > { let elements : meta :: SiteElements = meta . pick ( ) ; let lattice = coords . lattice ( ) ; let carts = coords . to_carts ( ) ; // HACK: collect to vec so that it implements IntoParallelIterator let interaction_pairs = interaction_pairs . into_iter ( ) . filter ( | bond | bond . is_canonical ( ) ) . collect :: < Vec < _ > > ( ) ; // HACK: collect from Rc<[_]> to Vec to impl Send let elements = elements . iter ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) ; let ( part_values , bond_grads ) = match normal_info { NormalInfo :: Z { } => { CondIterator :: new ( interaction_pairs , parallel ) . map ( | bond | { debug_assert ! ( bond is_canonical ( ) ) ; debug_assert_eq ! ( elements [ bond from ] Element CARBON ) ; debug_assert_eq ! ( elements [ bond to ] Element CARBON ) ; let cart_vector = bond . cart_vector_using_carts ( lattice , & carts ) ; let ( part_value , part_grad ) = params . compute_z ( cart_vector ) ; let bond_grad = BondGrad { plus_site : bond . to , minus_site : bond . from , grad : part_grad , cart_vector , } ; ( part_value , bond_grad ) } ) . unzip ( ) } , & NormalInfo :: NotZ { kind , ref intralayer_graph } => { let normals = Normals :: compute ( intralayer_graph , coords , kind ) ? ; let ( part_values , grad_items ) : ( Vec < _ > , Vec < _ > ) = { CondIterator :: new ( interaction_pairs , parallel ) . map ( | bond | { debug_assert ! ( bond is_canonical ( ) ) ; debug_assert_eq ! ( elements [ bond from ] Element CARBON ) ; debug_assert_eq ! ( elements [ bond to ] Element CARBON ) ; let cart_vector = bond . cart_vector_using_carts ( lattice , & carts ) ; let ni = normals . lookup ( bond . from ) ; let nj = normals . lookup ( bond . to ) ; let crespi_imp :: Output { value , grad_rij , grad_ni , grad_nj , } = params . compute ( cart_vector , ni , nj ) ; let bond_grad = BondGrad { plus_site : bond . to , minus_site : bond . from , grad : grad_rij , cart_vector , } ; ( value , ( bond_grad , grad_ni , grad_nj ) ) } ) . unzip ( ) } ; let mut bond_grads = Vec :: with_capacity ( grad_items . len ( ) + 2 * coords . len ( ) ) ; let mut normal_grads = vec ! [ V3 zero ( ) coords len ( ) ] ; for ( bond_grad , grad_ni , grad_nj ) in grad_items { bond_grads . push ( bond_grad ) ; normal_grads [ bond_grad . minus_site ] += grad_ni ; normal_grads [ bond_grad . plus_site ] += grad_nj ; } for ( site , d_normal ) in normal_grads . into_iter ( ) . enumerate ( ) { bond_grads . extend ( normals . get_bond_grad_terms ( site , d_normal ) ) ; } ( part_values , bond_grads ) } , // NormalInfo::NotZ => { ... } } ; // let (part_values, bond_grads) = match normal_info { ... } let value = part_values . iter ( ) . sum ( ) ; Ok ( ( value , bond_grads ) ) }
Compute terms for all of the provided FracBonds, possibly in parallel.
Compute terms for all of the provided FracBonds possibly in parallel .
parallel
bool
params
&crespi_imp::Params
coords
&Coords
meta
CommonMeta
normal_info
&NormalInfo
interaction_pairs
Vec<FracBond>
parallel
bool
params
&crespi_imp::Params
coords
&Coords
meta
CommonMeta
normal_info
&NormalInfo
interaction_pairs
Vec<FracBond>