/// Compute a partially filled force constants matrix that contains only the rows
/// that appear in the definition of the dynamical matrix. (those where the displaced
/// atom is an image in `ForceConstants::DESIGNATED_CELL`)
///
/// This basically follows Phonopy's method for `--writefc` to a T, although it
/// is a bit smarter in some places, and probably dumber in other places.
///
/// Notable differences from phonopy include:
///
/// * This uses a sparse format for anything indexed by atoms (primitive or super)
/// * Phonopy translates each displaced atom to the origin and performs
///   expensive brute force overlap searches, while this leaves everything where
///   they are and adjusts indices to simulate translation by a lattice point)
Compute a partially filled force constants matrix that contains only the rows
that appear in the definition of the dynamical matrix. (those where the displaced
atom is an image in `ForceConstants::DESIGNATED_CELL`)

This basically follows Phonopy's method for `--writefc` to a T, although it
is a bit smarter in some places, and probably dumber in other places.

Notable differences from phonopy include.

This uses a sparse format for anything indexed by atoms (primitive or super)
Phonopy translates each displaced atom to the origin and performs
expensive brute force overlap searches, while this leaves everything where
they are and adjusts indices to simulate translation by a lattice point)
Compute a partially filled force constants matrix that contains only the rows that appear in the definition of the dynamical matrix . ( those where the displaced atom is an image in ` ForceConstants :: DESIGNATED_CELL ` ) This basically follows Phonopy ' s method for ` -- writefc ` to a T although it is a bit smarter in some places and probably dumber in other places . Notable differences from phonopy include . This uses a sparse format for anything indexed by atoms ( primitive or super ) Phonopy translates each displaced atom to the origin and performs expensive brute force overlap searches while this leaves everything where they are and adjusts indices to simulate translation by a lattice point )
pub fn compute_required_rows(
        // Displacements, using the same supercell indices that the corresponding
        // `force_sets` were generated from.  Currently these are all required to use
        // the images in `ForceConstants::DESIGNATED_CELL`. (this requirement is checked)
        //
        // Furthermore, for each symmetry star of sites in the primitive cell, only one of those
        // sites may appear in this list. (this requirement is checked)
        super_displacements: &[(usize, V3)], // [displacement] -> (super_displaced, cart_disp)
        force_sets: &[BTreeMap<usize, V3>],  // [displacement][affected] -> cart_force
        cart_rots: &[M33],                   // [sg_index] -> matrix
        super_deperms: &[Perm],              // [sg_index] -> permutation on supercell
        sc: &SupercellToken,
    ) -> FailResult<ForceConstants>
    {
        // wrap data with information about index type
        //
        // most type annotations in here are not strictly necessary, but serve as a stop-gap measure
        // to ensure that at least *something* close to the public interface stops compiling if the
        // newtyped indices in Context are changed (to remind you to check callers)
        let super_displacements: &[(SuperI, V3)] = index_cast(super_displacements);
        let super_displacements: &Indexed<DispI, [_]> = Indexed::from_raw_ref(super_displacements);
        let force_sets: &[BTreeMap<SuperI, V3>] = index_cast(force_sets);
        let force_sets: &Indexed<DispI, [_]> = Indexed::from_raw_ref(force_sets);
        let cart_rots: &Indexed<OperI, [M33]> = Indexed::from_raw_ref(cart_rots);
        let super_deperms: &Indexed<OperI, [Perm]> = Indexed::from_raw_ref(super_deperms);
        let sc = SupercellWrapper::new(sc);
        let primitive_atoms: Indexed<SuperI, Vec<PrimI>> = sc.atom_primitive_atoms();
        let lattice_points: Indexed<SuperI, Vec<V3<i32>>> = sc.atom_lattice_points();
        let primitive_atoms = &primitive_atoms[..];
        let lattice_points = &lattice_points[..];
        let displacements: Indexed<DispI, Vec<(PrimI, V3)>> = {
            super_displacements.iter()
                .map(|&(super_disp, force)| {
                    if lattice_points[super_disp] != sc.designated_lattice_point {
                        // (NOTE: this requirement could easily be lifted by correcting the indices in
                        //        force sets by applying lattice point translations that move the displaced
                        //        atom to DESIGNATED_CELL.  I have not implemented this because I haven't
                        //        needed it.)
                        bail!(
                            "\
                                ForceConstants currently requires input forces to use displaced atoms in \
                                ForceConstants::DESIGNATED_CELL (= {:?}). (found atom with cell {:?})\
                            ",
                            ForceConstants::DESIGNATED_CELL,
                            sc.raw.cell_from_lattice_point(lattice_points[super_disp]),
                        )
                    }
                    Ok((primitive_atoms[super_disp], force))
                }).collect::<FailResult<_>>()?
        };
        Context {
            displacements: &displacements,
            sc, primitive_atoms, lattice_points, force_sets,
            cart_rots, super_deperms,
        }.compute_force_constants()
    }
pub fn compute_required_rows ( // Displacements, using the same supercell indices that the corresponding // `force_sets` were generated from.  Currently these are all required to use // the images in `ForceConstants::DESIGNATED_CELL`. (this requirement is checked) // // Furthermore, for each symmetry star of sites in the primitive cell, only one of those // sites may appear in this list. (this requirement is checked) super_displacements : & [ ( usize , V3 ) ] , // [displacement] -> (super_displaced, cart_disp) force_sets : & [ BTreeMap < usize , V3 > ] , // [displacement][affected] -> cart_force cart_rots : & [ M33 ] , // [sg_index] -> matrix super_deperms : & [ Perm ] , // [sg_index] -> permutation on supercell sc : & SupercellToken , ) -> FailResult < ForceConstants > { // wrap data with information about index type // // most type annotations in here are not strictly necessary, but serve as a stop-gap measure // to ensure that at least *something* close to the public interface stops compiling if the // newtyped indices in Context are changed (to remind you to check callers) let super_displacements : & [ ( SuperI , V3 ) ] = index_cast ( super_displacements ) ; let super_displacements : & Indexed < DispI , [ _ ] > = Indexed :: from_raw_ref ( super_displacements ) ; let force_sets : & [ BTreeMap < SuperI , V3 > ] = index_cast ( force_sets ) ; let force_sets : & Indexed < DispI , [ _ ] > = Indexed :: from_raw_ref ( force_sets ) ; let cart_rots : & Indexed < OperI , [ M33 ] > = Indexed :: from_raw_ref ( cart_rots ) ; let super_deperms : & Indexed < OperI , [ Perm ] > = Indexed :: from_raw_ref ( super_deperms ) ; let sc = SupercellWrapper :: new ( sc ) ; let primitive_atoms : Indexed < SuperI , Vec < PrimI > > = sc . atom_primitive_atoms ( ) ; let lattice_points : Indexed < SuperI , Vec < V3 < i32 > > > = sc . atom_lattice_points ( ) ; let primitive_atoms = & primitive_atoms [ .. ] ; let lattice_points = & lattice_points [ .. ] ; let displacements : Indexed < DispI , Vec < ( PrimI , V3 ) > > = { super_displacements . iter ( ) . map ( | & ( super_disp , force ) | { if lattice_points [ super_disp ] != sc . designated_lattice_point { // (NOTE: this requirement could easily be lifted by correcting the indices in //        force sets by applying lattice point translations that move the displaced //        atom to DESIGNATED_CELL.  I have not implemented this because I haven't //        needed it.) bail ! ( " \
 \
 \
 " ForceConstants DESIGNATED_CELL sc raw cell_from_lattice_point ( lattice_points [ super_disp ] ) ) } Ok ( ( primitive_atoms [ super_disp ] , force ) ) } ) . collect :: < FailResult < _ > > ( ) ? } ; Context { displacements : & displacements , sc , primitive_atoms , lattice_points , force_sets , cart_rots , super_deperms , } . compute_force_constants ( ) }
Compute a partially filled force constants matrix that contains only the rows
that appear in the definition of the dynamical matrix.
Compute a partially filled force constants matrix that contains only the rows that appear in the definition of the dynamical matrix .
super_displacements
&[(usize, V3)]
force_sets
&[BTreeMap<usize, V3>]
cart_rots
&[M33]
super_deperms
&[Perm]
sc
&SupercellToken