def test_products(self): p = 5 np.random.seed(13) n = 3 Vx = np.random.random(n) Vy = np.random.random(n) Vz = np.random.random(n) V_r = displacive.products(Vx, Vy, Vz, p) V_r = V_r.reshape(displacive.number(np.arange(p + 1)).sum(), n) np.testing.assert_array_almost_equal(V_r[0, :], Vx**0 * Vy**0 * Vz**0) np.testing.assert_array_almost_equal(V_r[1, :], Vx**1 * Vy**0 * Vz**0) np.testing.assert_array_almost_equal(V_r[2, :], Vx**0 * Vy**1 * Vz**0) np.testing.assert_array_almost_equal(V_r[3, :], Vx**0 * Vy**0 * Vz**1) np.testing.assert_array_almost_equal(V_r[4, :], Vx**2 * Vy**0 * Vz**0) np.testing.assert_array_almost_equal(V_r[5, :], Vx**1 * Vy**1 * Vz**0) np.testing.assert_array_almost_equal(V_r[6, :], Vx**0 * Vy**2 * Vz**0) np.testing.assert_array_almost_equal(V_r[7, :], Vx**1 * Vy**0 * Vz**1) np.testing.assert_array_almost_equal(V_r[8, :], Vx**0 * Vy**1 * Vz**1) np.testing.assert_array_almost_equal(V_r[9, :], Vx**0 * Vy**0 * Vz**2)
def displacive_parameters(self, p, centering): coeffs = displacive.coefficients(p) start = (np.cumsum(displacive.number(np.arange(p + 1))) - displacive.number(np.arange(p + 1)))[::2] end = np.cumsum(displacive.number(np.arange(p + 1)))[::2] even = [] for k in range(len(end)): even += range(start[k], end[k]) even = np.array(even) nuclear = ['P', 'I', 'F', 'R', 'C', 'A', 'B'] cntr = np.argwhere([x in centering for x in nuclear])[0][0] cntr += 1 return coeffs, even, cntr
def test_coefficients(self): p = 5 coeffs = displacive.coefficients(p) numbers = displacive.number(np.arange(p + 1)) self.assertEqual(coeffs.size, numbers.sum()) self.assertEqual(coeffs[0], 1) even = np.isreal(coeffs) odd = ~np.isreal(coeffs) end = np.cumsum(numbers) start = end - numbers self.assertTrue(even[start[0]:end[0]].all()) self.assertTrue(odd[start[1]:end[1]].all()) self.assertTrue(even[start[2]:end[2]].all()) self.assertTrue(odd[start[3]:end[3]].all()) self.assertTrue(even[start[4]:end[4]].all()) self.assertTrue(odd[start[5]:end[5]].all()) self.assertAlmostEqual(coeffs[0], 1) self.assertAlmostEqual(coeffs[1], 1j) self.assertAlmostEqual(coeffs[2], 1j) self.assertAlmostEqual(coeffs[3], 1j) self.assertAlmostEqual(coeffs[4], -0.5) self.assertAlmostEqual(coeffs[5], -1) self.assertAlmostEqual(coeffs[6], -0.5) self.assertAlmostEqual(coeffs[7], -1) self.assertAlmostEqual(coeffs[8], -1) self.assertAlmostEqual(coeffs[9], -0.5)
def intensity(U_k, A_k, Q_k, coeffs, cond, p, i_dft, factors, subtract=True): """ Chemical scattering intensity. Parameters ---------- U_k : 1d array Fourier transform of Taylor expansion displacement products A_k : 1d array Fourier transform of relative site occupancies Q_k : 1d array Fourier transform of Taylor expansion wavevector products coeffs : 1d array Taylor expansion coefficients cond : 1d array Array indices corresponding to nuclear Bragg peaks p : int Order of Taylor expansion i_dft: 1d array, int Array indices of Fourier transform corresponding to reciprocal space factors: 1d array Prefactors of form factors, phase factors, and composition factors Returns ------- I : 1d array Array has a flattened shape of size ``i_dft.shape[0]`` """ n_prod = coeffs.shape[0] n_peaks = i_dft.shape[0] n_atm = factors.shape[0] // n_peaks factors = factors.reshape(n_peaks, n_atm) n_uvw = U_k.shape[0] // n_prod // n_atm U_k = U_k.reshape(n_prod, n_uvw, n_atm) A_k = A_k.reshape(n_prod, n_uvw, n_atm) Q_k = Q_k.reshape(n_prod, n_peaks) start = (np.cumsum(number(np.arange(p + 1))) - number(np.arange(p + 1)))[::2] end = np.cumsum(number(np.arange(p + 1)))[::2] even = [] for k in range(len(end)): even += range(start[k], end[k]) even = np.array(even) V_k = np.einsum('ijk,kj->ji', coeffs*(U_k[:,i_dft,:]+\ A_k[:,i_dft,:]).T, Q_k) V_k_nuc = np.einsum('ijk,kj->ji', (coeffs[even]*(U_k[:,i_dft,:][even,:]+\ A_k[:,i_dft,:][even,:]).T), Q_k[even,:])[cond] prod = factors * V_k prod_nuc = factors[cond, :] * V_k_nuc F = np.sum(prod, axis=1) F_nuc = np.sum(prod_nuc, axis=1) if subtract: F[cond] -= F_nuc I = np.real(F)**2 + np.imag(F)**2 return I / (n_uvw * n_atm) else: F_bragg = np.zeros(F.shape, dtype=complex) F_bragg[cond] = F_nuc I = np.real(F)**2 + np.imag(F)**2 return I / (n_uvw * n_atm), F_bragg
def structure(U_k, A_k, Q_k, coeffs, cond, p, i_dft, factors): """ Partial displacive structure factor. Parameters ---------- U_k : 1d array Fourier transform of Taylor expansion displacement products A_k : 1d array Fourier transform of relative site occupancies times Taylor expansion displacement products Q_k : 1d array Fourier transform of Taylor expansion wavevector products coeffs : 1d array Taylor expansion coefficients cond : 1d array Array indices corresponding to nuclear Bragg peaks p : int Order of Taylor expansion i_dft: 1d array, int Array indices of Fourier transform corresponding to reciprocal space factors: 1d array Prefactors of scattering lengths, phase factors, and occupancies Returns ------- F : 1d array Array has a flattened shape of size ``coeffs.shape[0]*i_dft.shape[0]`` F_nuc : 1d array Array has a flattened shape of size ``cond.sum()*i_dft.shape[0]`` prod : 1d array Array has a flattened shape of size ``coeffs.shape[0]*i_dft.shape[0]*n_atm`` prod_nuc : 1d array Array has a flattened shape of size ``coeffs.sum()*i_dft.shape[0]*n_atm`` V_k : 1d array Array has a flattened shape of size ``coeffs.shape[0]*i_dft.shape[0]*n_atm`` V_k_nuc : 1d array Array has a flattened shape of size ``coeffs.sum()*i_dft.shape[0]*n_atm`` even : 1d array, int Array indices of the even Taylor expandion coefficients bragg : 1d array, int Array has a flattened shape of size ``coeffs.sum()`` """ n_prod = coeffs.shape[0] n_peaks = i_dft.shape[0] n_atm = factors.shape[0] // n_peaks factors = factors.reshape(n_peaks, n_atm) n_uvw = U_k.shape[0] // n_prod // n_atm U_k = U_k.reshape(n_prod, n_uvw, n_atm) A_k = A_k.reshape(n_prod, n_uvw, n_atm) Q_k = Q_k.reshape(n_prod, n_peaks) start = (np.cumsum(number(np.arange(p + 1))) - number(np.arange(p + 1)))[::2] end = np.cumsum(number(np.arange(p + 1)))[::2] even = [] for k in range(len(end)): even += range(start[k], end[k]) even = np.array(even) V_k = np.einsum('ijk,kj->ji', coeffs*(U_k[:,i_dft,:]+\ A_k[:,i_dft,:]).T, Q_k) V_k_nuc = np.einsum('ijk,kj->ji', (coeffs[even]*(U_k[:,i_dft,:][even,:]+\ A_k[:,i_dft,:][even,:]).T), Q_k[even,:])[cond] prod = factors * V_k prod_nuc = factors[cond, :] * V_k_nuc F = np.sum(prod, axis=1) F_nuc = np.sum(prod_nuc, axis=1) bragg = np.arange(n_peaks)[cond] return F, \ F_nuc, \ prod.flatten(), \ prod_nuc.flatten(), \ V_k.flatten(), \ V_k_nuc.flatten(), \ even, \ bragg
def test_numbers(self): m = np.arange(10) n = displacive.numbers(m) np.testing.assert_array_equal(np.diff(n), displacive.number(m[1:]))
def test_number(self): m = np.arange(10) n = displacive.number(m) np.testing.assert_array_equal(np.diff(n), 2 + m[:-1])