Пример #1
0
    def test_recip2real(self):
        real_lattice = [
            [5.5902240, 0, 0],
            [3.7563195, 4.1401290, 0],
            [-2.9800295, -1.3200288, 8.5321695],
        ]
        recip_lattice = real2recip(real_lattice)
        np.testing.assert_array_almost_equal(
            np.asarray(recip_lattice),
            np.asarray([
                [1.1239595, -1.0197632, 0.2347956],
                [0.0, 1.5176303, 0.2347956],
                [0, 0, 0.7364112],
            ]),
        )

        real_lattice = [
            [6.0235150, 0, 0],
            [0.0, 5.6096010, 0],
            [-5.0202472, 0, 10.0218337],
        ]
        recip_lattice = real2recip(real_lattice)
        np.testing.assert_array_almost_equal(
            np.asarray(recip_lattice),
            np.asarray([[1.0431094, 0, 0.5225256], [0, 1.1200770, 0],
                        [0, 0, 0.6269494]]),
        )
Пример #2
0
 def test_cart2abc_star(self):
     castep_fname = REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep"
     self.assertTrue(os.path.isfile(castep_fname))
     test_doc, success = castep2dict(castep_fname,
                                     db=True,
                                     verbosity=VERBOSITY)
     self.assertTrue(success)
     self.assertTrue(
         np.allclose(
             real2recip(test_doc["lattice_cart"]),
             2 * np.pi * np.asarray(cart2abcstar(test_doc["lattice_cart"])),
         ),
         msg="Conversion cart2abc failed.",
     )
Пример #3
0
    def calc_pxrd(self):
        """ Calculate the PXRD pattern. """

        # set crystallographic data
        lattice_abc = np.asarray(self.doc.lattice_abc)
        lattice_cart = np.asarray(self.doc.lattice_cart)
        positions_abs = np.asarray(self.doc.positions_abs)
        site_occupancies = np.asarray(self.doc.site_occupancies)

        # find allowed reciprocal lattice points within limiting sphere
        min_r, max_r = [
            2 / self.wavelength * np.sin(np.pi / 180 * t / 2)
            for t in self.two_theta_bounds
        ]
        Ns = np.floor(max_r * lattice_abc[0, :]).astype(int)

        recip = np.asarray(real2recip(lattice_cart)).T
        qs = np.zeros((2 * sum(Ns), 3), dtype=np.float64)
        hkls = np.asarray(list(
            itertools.product(range(-Ns[0],
                                    Ns[0] + 1), range(-Ns[1], Ns[1] + 1),
                              range(-Ns[2], Ns[2] + 1))),
                          dtype=np.float64)
        hkls = hkls[np.argsort(np.linalg.norm(hkls, axis=-1))]
        qs = np.dot(recip, hkls.T).T

        # filter out by theta bounds
        q_mags = np.linalg.norm(qs, axis=-1)
        allowed = np.where(
            np.logical_and(q_mags <= max_r * 2 * np.pi,
                           q_mags >= min_r * 2 * np.pi))
        qs = qs[allowed]
        hkls = hkls[allowed]

        # compute Bragg condition to find peak locations
        sin_tau = np.linalg.norm(qs, axis=1) * self.wavelength / (4 * np.pi)
        sin_tau[sin_tau > 1] = 0
        taus = 2 * np.arcsin(sin_tau)

        # compute structure factor S(q) as sum of atomic scattering factors
        S_q = np.zeros_like(taus)

        if self.progress:
            import tqdm
            bar = tqdm.tqdm
        else:

            def bar(x):
                return x

        for ind, q_vector in bar(enumerate(qs)):
            # accumulate atomic scattering factors
            atomic_factor = {}
            for species in set(self.doc.atom_types):
                atomic_factor[species] = self.atomic_scattering_factor(
                    q_mags[ind], species)
            factors = np.array(
                [atomic_factor[species] for species in self.doc.atom_types])
            F_s = np.sum(
                np.exp(1j * positions_abs @ q_vector) * factors *
                site_occupancies)
            S_q[ind] = np.abs(F_s)**2

        # apply Lorentz correction for polarisation and finite size effects
        S_q *= 2 * (1 + np.cos(taus)**2 * np.cos(2 * self.theta_m)**2) / (
            np.sin(taus) * np.sin(0.5 * taus))

        # thermal correction assuming no Debye-Waller factor
        S_q *= np.exp(-np.sin(taus)**2 / self.wavelength**2)**2
        S_q /= np.max(S_q)

        # create histogram and broaden onto 2 theta space in degrees
        self.peak_positions = (180 / np.pi) * taus
        self.hkls = hkls
        self.two_thetas = np.arange(
            self.two_theta_bounds[0],
            self.two_theta_bounds[1] + self.two_theta_resolution,
            self.two_theta_resolution)

        self.pattern, bins = np.histogram(self.peak_positions,
                                          bins=self.two_thetas,
                                          weights=S_q)

        if self.lorentzian_width > 0:
            self.pattern = self._broadening_unrolled(
                self.pattern,
                self.two_thetas,
                self.lorentzian_width,
                broadening_type='lorentzian')
        else:
            # shift and clip the last two theta value if we didnt do broadening
            self.two_thetas = self.two_thetas[:
                                              -1] + self.two_theta_resolution / 2

        self.pattern /= np.max(self.pattern)

        order = np.argsort(self.peak_positions)
        self.hkls = hkls[order]
        self.peak_intensities = S_q
        self.peak_positions = self.peak_positions[order]

        # alias old name for compatibility...
        self.spectrum = self.pattern
Пример #4
0
 def recip_lattice_cart(self):
     return real2recip(self.lattice_cart)
Пример #5
0
 def kpoint_path_cartesian(self):
     """ The reicprocal space sampling path in Cartesian coordinates. """
     return np.asarray(
         frac2cart(real2recip(self.lattice_cart), self.kpoint_path))
Пример #6
0
    def test_kpt_path(self):

        cell, s = castep2dict(REAL_PATH +
                              "data/Na3Zn4-swap-ReOs-OQMD_759599.castep")
        std_cell, path, seekpath_results = get_seekpath_kpoint_path(
            cell, spacing=0.01, debug=False)
        self.assertEqual(539, len(path))

        self.assertLess(pdf_sim_dist(cell, std_cell), 0.05)

        import glob
        from os import remove
        from matador.utils.cell_utils import frac2cart

        fnames = glob.glob(REAL_PATH + "data/bs_test/*.res")
        spacing = 0.01
        for fname in fnames:
            doc, s = res2dict(fname, db=False)
            doc["cell_volume"] = cart2volume(doc["lattice_cart"])

            std_doc, path, seekpath_results = get_seekpath_kpoint_path(
                doc, spacing=spacing, debug=False)
            seekpath_results_path = get_path(doc2spg(doc))

            rel_path = seekpath_results["explicit_kpoints_rel"]
            abs_path = seekpath_results["explicit_kpoints_abs"]

            cart_kpts = np.asarray(
                frac2cart(real2recip(std_doc["lattice_cart"]), path))
            diffs = np.zeros((len(cart_kpts[:-1])))
            np.testing.assert_array_almost_equal(cart_kpts, abs_path)
            np.testing.assert_array_almost_equal(path, rel_path)
            for ind, kpt in enumerate(cart_kpts[:-1]):
                diffs[ind] = np.sqrt(np.sum((kpt - cart_kpts[ind + 1])**2))
            self.assertLess(
                len(np.where(diffs > 1.1 * spacing)[0]),
                len(seekpath_results["explicit_segments"]),
            )

            if "flrys4-1x109" in fname:
                bs, s = bands2dict(fname.replace(".res", ".bands"))
                np.testing.assert_array_almost_equal(bs["kpoint_path"],
                                                     rel_path)
                np.testing.assert_array_almost_equal(bs["lattice_cart"],
                                                     std_doc["lattice_cart"])
            self.assertLess(
                len(np.where(diffs > 1.1 * spacing)[0]),
                len(seekpath_results["explicit_segments"]),
            )

            cell_path = fname.replace(".res", ".cell")
            doc2cell(std_doc, cell_path)
            new_doc, s = cell2dict(cell_path,
                                   lattice=True,
                                   positions=True,
                                   db=False)
            assert "positions_frac" in new_doc
            remove(cell_path)
            seekpath_new_results = get_path(doc2spg(new_doc))
            self.assertEqual(
                seekpath_new_results["bravais_lattice_extended"],
                seekpath_results_path["bravais_lattice_extended"],
            )

            dist = pdf_sim_dist(doc, std_doc)
            self.assertLess(dist, 0.01)
            dist = pdf_sim_dist(doc, new_doc)
            self.assertLess(dist, 0.01)