Пример #1
0
    def _cart_dists(self, s1, s2, avg_lattice, mask, normalization, lll_frac_tol=None):
        """
        Finds a matching in cartesian space. Finds an additional
        fractional translation vector to minimize RMS distance

        Args:
            s1, s2: numpy arrays of fractional coordinates. len(s1) >= len(s2)
            avg_lattice: Lattice on which to calculate distances
            mask: numpy array of booleans. mask[i, j] = True indicates
                that s2[i] cannot be matched to s1[j]
            normalization (float): inverse normalization length

        Returns:
            Distances from s2 to s1, normalized by (V/Natom) ^ 1/3
            Fractional translation vector to apply to s2.
            Mapping from s1 to s2, i.e. with numpy slicing, s1[mapping] => s2
        """
        if len(s2) > len(s1):
            raise ValueError("s1 must be larger than s2")
        if mask.shape != (len(s2), len(s1)):
            raise ValueError("mask has incorrect shape")

        # vectors are from s2 to s1
        vecs, d_2 = pbc_shortest_vectors(avg_lattice, s2, s1, mask,
                                         return_d2=True,
                                         lll_frac_tol=lll_frac_tol)
        lin = LinearAssignment(d_2)
        s = lin.solution
        short_vecs = vecs[np.arange(len(s)), s]
        translation = np.average(short_vecs, axis=0)
        f_translation = avg_lattice.get_fractional_coords(translation)
        new_d2 = np.sum((short_vecs - translation) ** 2, axis=-1)

        return new_d2 ** 0.5 * normalization, f_translation, s
Пример #2
0
    def _cart_dists(self, s1, s2, avg_lattice, mask, normalization, lll_frac_tol=None):
        """
        Finds a matching in cartesian space. Finds an additional
        fractional translation vector to minimize RMS distance

        Args:
            s1, s2: numpy arrays of fractional coordinates. len(s1) >= len(s2)
            avg_lattice: Lattice on which to calculate distances
            mask: numpy array of booleans. mask[i, j] = True indicates
                that s2[i] cannot be matched to s1[j]
            normalization (float): inverse normalization length

        Returns:
            Distances from s2 to s1, normalized by (V/Natom) ^ 1/3
            Fractional translation vector to apply to s2.
            Mapping from s1 to s2, i.e. with numpy slicing, s1[mapping] => s2
        """
        if len(s2) > len(s1):
            raise ValueError("s1 must be larger than s2")
        if mask.shape != (len(s2), len(s1)):
            raise ValueError("mask has incorrect shape")

        # vectors are from s2 to s1
        vecs, d_2 = pbc_shortest_vectors(avg_lattice, s2, s1, mask,
                                         return_d2=True,
                                         lll_frac_tol=lll_frac_tol)
        lin = LinearAssignment(d_2)
        s = lin.solution
        short_vecs = vecs[np.arange(len(s)), s]
        translation = np.average(short_vecs, axis=0)
        f_translation = avg_lattice.get_fractional_coords(translation)
        new_d2 = np.sum((short_vecs - translation) ** 2, axis=-1)

        return new_d2 ** 0.5 * normalization, f_translation, s
Пример #3
0
def get_ionic_pol_change(struct2, struct1, psp_table, extra_trans=None):
    """should already be translated"""
    LOGGER.info("Finding ionic change in polarization")
    if extra_trans is None:
        extra_trans = np.array([0., 0., 0.])
    else:
        # convert extra_trans to cartesian
        extra_trans = np.array(extra_trans) * np.array(struct2.lattice.abc)
    mask = get_mask(struct2, struct1)
    vecs, d_2 = pbc_shortest_vectors(struct2.lattice,
                                     struct2.frac_coords,
                                     struct1.frac_coords,
                                     mask,
                                     return_d2=True,
                                     lll_frac_tol=[0.4, 0.4, 0.4])
    lin = LinearAssignment(d_2)
    s = lin.solution
    species = [struct1[i].species_string for i in s]
    short_vecs = vecs[np.arange(len(s)), s]
    LOGGER.debug("Displacements:")
    LOGGER.debug(short_vecs)
    pol_change = np.array([0., 0., 0.])
    for v, sp in zip(short_vecs, species):
        pol_change += (v -
                       extra_trans) * psp_table.pseudo_with_symbol(sp).Z_val
        LOGGER.debug("{}\t{}\t{}".format(
            sp,
            psp_table.pseudo_with_symbol(sp).Z_val, v))
    return (ECHARGE * 10**20) * pol_change / struct2.lattice.volume