// Input: Rows for each symmetry-star representative.
// Output: Rows for every primitive atom.
Rows for each symmetry-star representative.
Output: Rows for every primitive atom.
Rows for each symmetry - star representative . Output : Rows for every primitive atom .
fn derive_rows_by_symmetry(
        &self,
        star_data: &Indexed<StarI, [StarData]>,
        prim_data: &Indexed<PrimI, [PrimData]>,
        computed_rows: BTreeMap<PrimI, BTreeMap<SuperI, M3<V3<f64>>>>,
    ) -> Indexed<PrimI, Vec<BTreeMap<SuperI, M3<V3<f64>>>>>
    {
        prim_data.iter_enumerated().map(|(prim, data)| {
            let &PrimData { star, ref opers_from_rep } = data;
            let representative = star_data[star].representative;
            if computed_rows.contains_key(&prim) {
                assert_eq!(prim, representative, "(BUG!) bad input to derive_rows_by_symmetry");
                computed_rows[&prim].clone()
            } else {
                assert_ne!(prim, representative, "(BUG!) bad input to derive_rows_by_symmetry");
                // any operator will do; all should produce the same data.
                //
                // TODO: maybe we should verify that the 3x3 FC matrix is (approximately)
                //       invariant under the operations that map the site into itself?
                let &oper = opers_from_rep.get(0).expect("(BUG!) was checked earlier");
                // Visualize the operation described in the documentation of `get_corrected_rotate`.
                //
                // Performing this operation on a set of data would permute all indices according to the
                // deperm returned by `get_corrected_rotate`, and would rotate all displacements and forces
                // by the rotation part of the operator.  How does this impact the force constants?
                //
                // Clearly, the columns will be permuted by the deperm:
                let (rotated_prim, apply_deperm) = self.get_corrected_rotate(oper, representative);
                assert_eq!(rotated_prim, prim, "(BUG) oper produced different row?!");
                // But their contents will also be transformed by the rotation.
                //
                // Consider that the new force and displacement are each obtained by rotating the old
                // vectors by R, and substitute into the force constants equation. (`F = - U Phi`,
                // recalling that rsp2 prefers a row-vector-centric formalism for everything except
                // spatial transformation operators like R)
                //
                // The result:      Phi_new = R.T.inv() Phi_old R.T
                // or equivalently: Phi_new = R Phi_old R.T
                let cart_rot = self.cart_rots[oper];
                computed_rows[&representative].iter()
                    .map(|(&affected, fc_matrix)| {
                        let affected = apply_deperm(affected);
                        // FIXME: This could use a test where cart_rot != cart_rot.t()
                        // (for AB blg, cart_rot is currently always able to be E or i)
                        let fc_matrix = cart_rot * fc_matrix * cart_rot.t();
                        (affected, fc_matrix)
                    })
                    .collect()
            }
        }).collect()
    }
fn derive_rows_by_symmetry ( & self , star_data : & Indexed < StarI , [ StarData ] > , prim_data : & Indexed < PrimI , [ PrimData ] > , computed_rows : BTreeMap < PrimI , BTreeMap < SuperI , M3 < V3 < f64 > > > > , ) -> Indexed < PrimI , Vec < BTreeMap < SuperI , M3 < V3 < f64 > > > > > { prim_data . iter_enumerated ( ) . map ( | ( prim , data ) | { let & PrimData { star , ref opers_from_rep } = data ; let representative = star_data [ star ] . representative ; if computed_rows . contains_key ( & prim ) { assert_eq ! ( prim representative " " ) ; computed_rows [ & prim ] . clone ( ) } else { assert_ne ! ( prim representative " " ) ; // any operator will do; all should produce the same data. // // TODO: maybe we should verify that the 3x3 FC matrix is (approximately) //       invariant under the operations that map the site into itself? let & oper = opers_from_rep . get ( 0 ) . expect ( " " ) ; // Visualize the operation described in the documentation of `get_corrected_rotate`. // // Performing this operation on a set of data would permute all indices according to the // deperm returned by `get_corrected_rotate`, and would rotate all displacements and forces // by the rotation part of the operator.  How does this impact the force constants? // // Clearly, the columns will be permuted by the deperm: let ( rotated_prim , apply_deperm ) = self . get_corrected_rotate ( oper , representative ) ; assert_eq ! ( rotated_prim prim " " ) ; // But their contents will also be transformed by the rotation. // // Consider that the new force and displacement are each obtained by rotating the old // vectors by R, and substitute into the force constants equation. (`F = - U Phi`, // recalling that rsp2 prefers a row-vector-centric formalism for everything except // spatial transformation operators like R) // // The result:      Phi_new = R.T.inv() Phi_old R.T // or equivalently: Phi_new = R Phi_old R.T let cart_rot = self . cart_rots [ oper ] ; computed_rows [ & representative ] . iter ( ) . map ( | ( & affected , fc_matrix ) | { let affected = apply_deperm ( affected ) ; // FIXME: This could use a test where cart_rot != cart_rot.t() // (for AB blg, cart_rot is currently always able to be E or i) let fc_matrix = cart_rot * fc_matrix * cart_rot . t ( ) ; ( affected , fc_matrix ) } ) . collect ( ) } } ) . collect ( ) }
Input: Rows for each symmetry-star representative.
Input : Rows for each symmetry - star representative .
&self
star_data
&Indexed<StarI, [StarData]>
prim_data
&Indexed<PrimI, [PrimData]>
computed_rows
BTreeMap<PrimI, BTreeMap<SuperI, M3<V3<f64>>>>