def initialize_displacive(self, Ux, Uy, Uz, H, K, L, Qx, Qy, Qz, indices, factors, nu, nv, nw, n_atm, p, centering): n_uvw = nu * nv * nw coeffs = displacive.coefficients(p) U_r = displacive.products(Ux, Uy, Uz, p) Q_k = displacive.products(Qx, Qy, Qz, p) U_k, i_dft = displacive.transform(U_r, H, K, L, nu, nv, nw, n_atm) H_nuc, K_nuc, L_nuc, \ cond = space.condition(H, K, L, nu, nv, nw, centering) F, F_nuc, \ prod, prod_nuc, \ V_k, V_k_nuc, \ even, \ bragg = displacive.structure(U_k, Q_k, coeffs, cond, p, i_dft, factors) F_orig = np.zeros(indices.size, dtype=complex) F_nuc_orig = np.zeros(bragg.size, dtype=complex) prod_orig = np.zeros(indices.size, dtype=complex) prod_nuc_orig = np.zeros(bragg.size, dtype=complex) V_k_orig = np.zeros(indices.size, dtype=complex) V_k_nuc_orig = np.zeros(bragg.size, dtype=complex) U_k_orig = np.zeros(n_uvw * coeffs.size, dtype=complex) F_cand = np.zeros(indices.shape, dtype=complex) F_nuc_cand = np.zeros(bragg.shape, dtype=complex) prod_cand = np.zeros(indices.shape, dtype=complex) prod_nuc_cand = np.zeros(bragg.shape, dtype=complex) V_k_cand = np.zeros(indices.size, dtype=complex) V_k_nuc_cand = np.zeros(bragg.size, dtype=complex) U_k_cand = np.zeros(n_uvw * coeffs.size, dtype=complex) U_r_orig = np.zeros(coeffs.size, dtype=float) U_r_cand = np.zeros(coeffs.size, dtype=float) return U_r, U_r_orig, U_r_cand, Q_k, \ U_k, U_k_orig, U_k_cand, \ V_k, V_k_orig, V_k_cand, \ V_k_nuc, V_k_nuc_orig, V_k_nuc_cand, \ F, F_orig, F_cand, \ F_nuc, F_nuc_orig, F_nuc_cand, \ prod, prod_orig, prod_cand, \ prod_nuc, prod_nuc_orig, prod_nuc_cand, \ i_dft, coeffs, H_nuc, K_nuc, L_nuc, cond, even, bragg
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 test_displacive(self): a, b, c, alpha, beta, gamma = 5, 6, 7, np.pi / 2, np.pi / 3, np.pi / 4 inv_constants = crystal.reciprocal(a, b, c, alpha, beta, gamma) a_, b_, c_, alpha_, beta_, gamma_ = inv_constants h_range, nh = [-1, 1], 5 k_range, nk = [0, 2], 11 l_range, nl = [-1, 0], 5 nu, nv, nw, n_atm = 2, 5, 4, 2 u = np.array([0.2, 0.1]) v = np.array([0.3, 0.4]) w = np.array([0.4, 0.5]) atm = np.array(['Fe', 'Mn']) occupancy = np.array([0.75, 0.5]) U11 = np.array([0.5, 0.3]) U22 = np.array([0.6, 0.4]) U33 = np.array([0.4, 0.6]) U23 = np.array([0.05, -0.03]) U13 = np.array([-0.04, 0.02]) U12 = np.array([0.03, -0.02]) twins = np.eye(3).reshape(1, 3, 3) variants = np.array([1.0]) W = np.eye(3) A = crystal.cartesian(a, b, c, alpha, beta, gamma) B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_) R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma) U = np.row_stack((U11, U22, U33, U23, U13, U12)) Ux, Uy, Uz = displacive.expansion(nu, nv, nw, n_atm, value=U) index_parameters = space.mapping(h_range, k_range, l_range, nh, nk, nl, nu, nv, nw) h, k, l, H, K, L, indices, inverses, operators = index_parameters Qh, Qk, Ql = crystal.vector(h, k, l, B) Qx, Qy, Qz = crystal.transform(Qh, Qk, Ql, R) Qx_norm, Qy_norm, Qz_norm, Q = space.unit(Qx, Qy, Qz) ux, uy, uz = crystal.transform(u, v, w, A) ix, iy, iz = space.cell(nu, nv, nw, A) rx, ry, rz, atms = space.real(ux, uy, uz, ix, iy, iz, atm) phase_factor = scattering.phase(Qx, Qy, Qz, ux, uy, uz) scattering_length = scattering.length(atm, Q.size) p = 3 coeffs = displacive.coefficients(p) H_nuc, K_nuc, L_nuc, cond = space.condition(H, K, L, nu, nv, nw, centering='P') U_r = displacive.products(Ux, Uy, Uz, p) Q_k = displacive.products(Qx, Qy, Qz, p) U_k, i_dft = displacive.transform(U_r, H, K, L, nu, nv, nw, n_atm) factors = space.prefactors(scattering_length, phase_factor, occupancy) I_ref = displacive.intensity(U_k, Q_k, coeffs, cond, p, i_dft, factors) reduced_params = space.reduced(h_range, k_range, l_range, nh, nk, nl, nu, nv, nw) indices, reverses, symops, Nu, Nv, Nw = reduced_params symop = symmetry.laue_id(symops) centering = 1 even, odd = displacive.indices(p) I = monocrystal.displacive(U_r, coeffs, occupancy, ux, uy, uz, atm, h_range, k_range, l_range, indices, symop, W, B, R, twins, variants, nh, nk, nl, nu, nv, nw, Nu, Nv, Nw, p, even, centering) np.testing.assert_array_almost_equal(I, I_ref)
def test_structure(self): a, b, c, alpha, beta, gamma = 5, 6, 7, np.pi / 2, np.pi / 3, np.pi / 4 inv_constants = crystal.reciprocal(a, b, c, alpha, beta, gamma) a_, b_, c_, alpha_, beta_, gamma_ = inv_constants h_range, nh = [-1, 1], 5 k_range, nk = [0, 2], 11 l_range, nl = [-1, 0], 5 nu, nv, nw, n_atm = 2, 5, 4, 2 u = np.array([0.2, 0.1]) v = np.array([0.3, 0.4]) w = np.array([0.4, 0.5]) atm = np.array(['Fe', 'Mn']) occupancy = np.array([0.75, 0.5]) U11 = np.array([0.5, 0.3]) U22 = np.array([0.6, 0.4]) U33 = np.array([0.4, 0.6]) U23 = np.array([0.05, -0.03]) U13 = np.array([-0.04, 0.02]) U12 = np.array([0.03, -0.02]) A = crystal.cartesian(a, b, c, alpha, beta, gamma) B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_) R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma) U = np.row_stack((U11, U22, U33, U23, U13, U12)) Ux, Uy, Uz = displacive.expansion(nu, nv, nw, n_atm, value=U) index_parameters = space.mapping(h_range, k_range, l_range, nh, nk, nl, nu, nv, nw) h, k, l, H, K, L, indices, inverses, operators = index_parameters Qh, Qk, Ql = crystal.vector(h, k, l, B) Qx, Qy, Qz = crystal.transform(Qh, Qk, Ql, R) Qx_norm, Qy_norm, Qz_norm, Q = space.unit(Qx, Qy, Qz) ux, uy, uz = crystal.transform(u, v, w, A) ix, iy, iz = space.cell(nu, nv, nw, A) rx, ry, rz, atms = space.real(ux, uy, uz, ix, iy, iz, atm) phase_factor = scattering.phase(Qx, Qy, Qz, ux, uy, uz) scattering_length = scattering.length(atm, Q.size) p = 3 coeffs = displacive.coefficients(p) H_nuc, K_nuc, L_nuc, cond = space.condition(H, K, L, nu, nv, nw) U_r = displacive.products(Ux, Uy, Uz, p) Q_k = displacive.products(Qx, Qy, Qz, p) U_k, i_dft = displacive.transform(U_r, H, K, L, nu, nv, nw, n_atm) factors = space.prefactors(scattering_length, phase_factor, occupancy) F, F_nuc, \ prod, prod_nuc, \ V_k, V_k_nuc, \ even, bragg = displacive.structure(U_k, Q_k, coeffs, cond, p, i_dft, factors) n_hkl = Q.size n_xyz = nu * nv * nw * n_atm m = np.arange(n_xyz) n = np.mod(m, n_atm) rx_m = rx[m] ry_m = ry[m] rz_m = rz[m] bc = scattering.length(atm, 1) U_r = U_r.reshape(coeffs.shape[0], n_xyz) Q_k = Q_k.reshape(coeffs.shape[0], n_hkl) U_m = U_r[:, m] c_n = occupancy[n] b_n = bc[n] exp_iQ_dot_U_m = np.dot(coeffs * U_m.T, Q_k).T prod_ref = c_n*b_n*exp_iQ_dot_U_m*np.exp(1j*(Qx[:,np.newaxis]*rx_m+\ Qy[:,np.newaxis]*ry_m+\ Qz[:,np.newaxis]*rz_m)) F_ref = prod_ref.sum(axis=1) prod_ref = prod_ref.reshape(n_hkl, nu * nv * nw, n_atm).sum(axis=1).flatten() np.testing.assert_array_almost_equal(F, F_ref) np.testing.assert_array_almost_equal(prod, prod_ref) cos_iQ_dot_U_m = np.dot((coeffs * U_m.T)[:, even], Q_k[even, :]).T prod_nuc_ref = c_n*b_n*cos_iQ_dot_U_m*\ np.exp(1j*(Qx[:,np.newaxis]*rx_m+\ Qy[:,np.newaxis]*ry_m+\ Qz[:,np.newaxis]*rz_m)) F_nuc_ref = prod_nuc_ref.sum(axis=1)[cond] prod_nuc_ref = prod_nuc_ref.reshape(n_hkl, nu * nv * nw, n_atm).sum(axis=1)[cond].flatten() np.testing.assert_array_almost_equal(F_nuc, F_nuc_ref) np.testing.assert_array_almost_equal(prod_nuc, prod_nuc_ref) factors = (c_n * b_n * cos_iQ_dot_U_m).flatten() F_nuc_ref = space.bragg(Qx, Qy, Qz, rx, ry, rz, factors, cond) np.testing.assert_array_almost_equal(F_nuc, F_nuc_ref)
def test_intensity(self): a, b, c, alpha, beta, gamma = 5, 6, 7, np.pi / 2, np.pi / 3, np.pi / 4 inv_constants = crystal.reciprocal(a, b, c, alpha, beta, gamma) a_, b_, c_, alpha_, beta_, gamma_ = inv_constants h_range, nh = [-1, 1], 5 k_range, nk = [0, 2], 11 l_range, nl = [-1, 0], 5 nu, nv, nw, n_atm = 2, 5, 4, 2 u = np.array([0.2, 0.1]) v = np.array([0.3, 0.4]) w = np.array([0.4, 0.5]) atm = np.array(['Fe', 'Mn']) occupancy = np.array([0.75, 0.5]) U11 = np.array([0.5, 0.3]) U22 = np.array([0.6, 0.4]) U33 = np.array([0.4, 0.6]) U23 = np.array([0.05, -0.03]) U13 = np.array([-0.04, 0.02]) U12 = np.array([0.03, -0.02]) A = crystal.cartesian(a, b, c, alpha, beta, gamma) B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_) R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma) U = np.row_stack((U11, U22, U33, U23, U13, U12)) Ux, Uy, Uz = displacive.expansion(nu, nv, nw, n_atm, value=U) index_parameters = space.mapping(h_range, k_range, l_range, nh, nk, nl, nu, nv, nw) h, k, l, H, K, L, indices, inverses, operators = index_parameters Qh, Qk, Ql = crystal.vector(h, k, l, B) Qx, Qy, Qz = crystal.transform(Qh, Qk, Ql, R) Qx_norm, Qy_norm, Qz_norm, Q = space.unit(Qx, Qy, Qz) ux, uy, uz = crystal.transform(u, v, w, A) ix, iy, iz = space.cell(nu, nv, nw, A) rx, ry, rz, atms = space.real(ux, uy, uz, ix, iy, iz, atm) phase_factor = scattering.phase(Qx, Qy, Qz, ux, uy, uz) scattering_length = scattering.length(atm, Q.size) p = 3 coeffs = displacive.coefficients(p) H_nuc, K_nuc, L_nuc, cond = space.condition(H, K, L, nu, nv, nw, centering='P') U_r = displacive.products(Ux, Uy, Uz, p) Q_k = displacive.products(Qx, Qy, Qz, p) U_k, i_dft = displacive.transform(U_r, H, K, L, nu, nv, nw, n_atm) factors = space.prefactors(scattering_length, phase_factor, occupancy) # I = displacive.intensity(U_k, Q_k, coeffs, cond, p, i_dft, factors) I, F_nuc = displacive.intensity(U_k, Q_k, coeffs, cond, p, i_dft, factors, subtract=False) n_hkl = Q.size n_xyz = nu * nv * nw * n_atm i, j = np.triu_indices(n_xyz, 1) k, l = np.mod(i, n_atm), np.mod(j, n_atm) m = np.arange(n_xyz) n = np.mod(m, n_atm) rx_ij = rx[j] - rx[i] ry_ij = ry[j] - ry[i] rz_ij = rz[j] - rz[i] bc = scattering.length(atm, 1) U_r = U_r.reshape(coeffs.shape[0], n_xyz) Q_k = Q_k.reshape(coeffs.shape[0], n_hkl) U_i, U_j, U_m = U_r[:, i], U_r[:, j], U_r[:, m] c_k, c_l, c_n = occupancy[k], occupancy[l], occupancy[n] b_k, b_l, b_n = bc[k], bc[l], bc[n] exp_iQ_dot_U_m = np.dot(coeffs * U_m.T, Q_k).T exp_iQ_dot_U_i = np.dot(coeffs * U_i.T, Q_k).T exp_iQ_dot_U_j = np.dot(coeffs * U_j.T, Q_k).T I_ref = ((c_n**2*(b_n*b_n.conj()).real*\ (exp_iQ_dot_U_m*exp_iQ_dot_U_m.conj()).real).sum(axis=1)\ + 2*(c_k*c_l*(b_k*b_l.conj()).real* ((exp_iQ_dot_U_i*exp_iQ_dot_U_j.conj()*\ np.cos(Qx[:,np.newaxis]*rx_ij+\ Qy[:,np.newaxis]*ry_ij+\ Qz[:,np.newaxis]*rz_ij)).real+ (exp_iQ_dot_U_i*exp_iQ_dot_U_j.conj()*\ np.sin(Qx[:,np.newaxis]*rx_ij+\ Qy[:,np.newaxis]*ry_ij+\ Qz[:,np.newaxis]*rz_ij)).imag)).sum(axis=1))/n_xyz np.testing.assert_array_almost_equal(I, I_ref)