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]]), )
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.", )
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
def recip_lattice_cart(self): return real2recip(self.lattice_cart)
def kpoint_path_cartesian(self): """ The reicprocal space sampling path in Cartesian coordinates. """ return np.asarray( frac2cart(real2recip(self.lattice_cart), self.kpoint_path))
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)