示例#1
0
    def test_phase(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

        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)

        nu, nv, nw = 5, 3, 4

        Rx, Ry, Rz = space.cell(nu, nv, nw, A)

        atm = np.array(['Fe', 'Co'])
        u, v, w = np.array([0, 0.2]), np.array([0, 0.3]), np.array([0, 0.4])

        ux, uy, uz = crystal.transform(u, v, w, A)

        rx, ry, rz, atms = space.real(ux, uy, uz, Rx, Ry, Rz, atm)

        h, k, l = np.array([-7, -3]), np.array([2, 2]), np.array([2, 5])

        Qh, Qk, Ql = crystal.vector(h, k, l, B)

        Qx, Qy, Qz = crystal.transform(Qh, Qk, Ql, R)

        phase_factor = scattering.phase(Qx, Qy, Qz, rx, ry, rz)

        np.testing.assert_array_almost_equal(phase_factor, 1 + 0j)
示例#2
0
    def reciprocal_space_coordinate_transform(self, h, k, l, B, R):

        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)

        return Qx, Qy, Qz, Qx_norm, Qy_norm, Qz_norm, Q
示例#3
0
    def test_vector(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

        B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_)

        h, k, l = -3, 1, 2

        Qh, Qk, Ql = crystal.vector(h, k, l, B)

        d = crystal.d(a, b, c, alpha, beta, gamma, h, k, l)

        Q = np.sqrt(Qh**2 + Qk**2 + Ql**2)

        self.assertAlmostEqual(d, 2 * np.pi / Q)
示例#4
0
    def test_structural(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 = [-5, 5], 11
        k_range, nk = [-5, 5], 11
        l_range, nl = [-5, 5], 11

        nu, nv, nw, n_atm = 5, 5, 5, 3

        u = np.array([0.2, 0.1, 0.3])
        v = np.array([0.3, 0.4, 0.2])
        w = np.array([0.4, 0.5, 0.1])

        atm = np.array(['Fe', 'Mn', 'Co'])
        occupancy = np.array([0.75, 0.5, 0.6])

        U11 = np.array([0.5, 0.3, 0.1])
        U22 = np.array([0.6, 0.4, 0.3])
        U33 = np.array([0.4, 0.6, 0.2])
        U23 = np.array([0.05, -0.03, -0.01])
        U13 = np.array([-0.04, 0.02, 0.02])
        U12 = np.array([0.03, -0.02, 0.01])

        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)
        D = crystal.cartesian_displacement(a, b, c, alpha, beta, gamma)

        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)

        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)

        I = monocrystal.structural(occupancy, U11, U22, U33, U23, U13, U12, ux,
                                   uy, uz, atm, h_range, k_range, l_range,
                                   indices, symop, W, B, R, D, twins, variants,
                                   nh, nk, nl, nu, nv, nw, Nu, Nv, Nw)

        hmin, hmax = h_range
        kmin, kmax = k_range
        lmin, lmax = l_range

        h, k, l = np.meshgrid(np.arange(hmin, hmax + 1),
                              np.arange(kmin, kmax + 1),
                              np.arange(lmin, lmax + 1),
                              indexing='ij')

        h, k, l = h.flatten(), k.flatten(), l.flatten()

        Qh, Qk, Ql = crystal.vector(h, k, l, B)

        Q = np.sqrt(Qh**2 + Qk**2 + Ql**2)

        n_hkl = Q.size

        phase_factor = np.exp(2j * np.pi *
                              (h[:, np.newaxis] * u + k[:, np.newaxis] * v +
                               l[:, np.newaxis] * w))

        scattering_power = scattering.length(atm, n_hkl).reshape(n_hkl, n_atm)

        T = np.exp(-2 * np.pi**2 *
                   (U11 * (h * a_)[:, np.newaxis]**2 + U22 *
                    (k * b_)[:, np.newaxis]**2 + U33 *
                    (l * c_)[:, np.newaxis]**2 + U23 *
                    (k * l * b_ * c_ * 2)[:, np.newaxis] + U13 *
                    (h * l * a_ * c_ * 2)[:, np.newaxis] + U12 *
                    (h * k * a_ * b_ * 2)[:, np.newaxis]))

        factors = scattering_power * occupancy * T * phase_factor

        F = factors.sum(axis=1)

        I_ref = np.abs(F)**2 / (nu * nv * nw * n_atm)

        np.testing.assert_array_almost_equal(I, I_ref)
示例#5
0
    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)
示例#6
0
    def test_magnetic(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(['Fe3+', 'Mn3+'])
        occupancy = np.array([0.75, 0.5])
        g = np.array([2., 2.])

        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)

        T = space.debye_waller(h_range, k_range, l_range, nh, nk, nl, U11, U22,
                               U33, U23, U13, U12, a_, b_, c_)

        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)
        D = crystal.cartesian_displacement(a, b, c, alpha, beta, gamma)

        Sx, Sy, Sz = magnetic.spin(nu, nv, nw, n_atm)

        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)

        form_factor = magnetic.form(Q, atm, g=g)

        Sx_k, Sy_k, Sz_k, i_dft = magnetic.transform(Sx, Sy, Sz, H, K, L, nu,
                                                     nv, nw, n_atm)

        factors = space.prefactors(form_factor, phase_factor, occupancy)

        factors *= T

        I_ref = magnetic.intensity(Qx_norm, Qy_norm, Qz_norm, Sx_k, Sy_k, Sz_k,
                                   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)

        I = monocrystal.magnetic(Sx, Sy, Sz, occupancy, U11, U22, U33, U23,
                                 U13, U12, ux, uy, uz, atm, h_range, k_range,
                                 l_range, indices, symop, W, B, R, D, twins,
                                 variants, nh, nk, nl, nu, nv, nw, Nu, Nv, Nw,
                                 g)

        np.testing.assert_array_almost_equal(I, I_ref)
示例#7
0
    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])

        T = space.debye_waller(h_range, k_range, l_range, nh, nk, nl, U11, U22,
                               U33, U23, U13, U12, a_, b_, c_)

        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)

        A_r = occupational.composition(nu, nv, nw, n_atm, value=occupancy)

        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)

        A_k, i_dft = occupational.transform(A_r, H, K, L, nu, nv, nw, n_atm)

        factors = space.prefactors(scattering_length, phase_factor, occupancy)

        factors *= T

        I = occupational.intensity(A_k, i_dft, factors)

        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)
        T = T.reshape(n_hkl, n_atm)

        A_i, A_j, A_m = A_r[i], A_r[j], A_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]
        T_k, T_l, T_n = T[:, k], T[:, l], T[:, n]

        I_ref = ((c_n**2*(b_n*b_n.conj()).real*A_m**2*T_n**2).sum(axis=1)\
              + 2*(c_k*c_l*(b_k*b_l.conj()).real*A_i*A_j*T_k*T_l*\
                   np.cos(Qx[:,np.newaxis]*rx_ij+\
                          Qy[:,np.newaxis]*ry_ij+\
                          Qz[:,np.newaxis]*rz_ij)).sum(axis=1))/n_xyz

        np.testing.assert_array_almost_equal(I, I_ref)
示例#8
0
    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])

        T = space.debye_waller(h_range, k_range, l_range, nh, nk, nl, U11, U22,
                               U33, U23, U13, U12, a_, b_, c_)

        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)

        A_r = occupational.composition(nu, nv, nw, n_atm, value=occupancy)

        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)

        A_k, i_dft = occupational.transform(A_r, H, K, L, nu, nv, nw, n_atm)

        factors = space.prefactors(scattering_length, phase_factor, occupancy)

        factors *= T

        F, prod = occupational.structure(A_k, 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)
        T = T.reshape(n_hkl, n_atm)

        A_m = A_r[m]
        c_n = occupancy[n]
        b_n = bc[n]
        T_n = T[:, n]

        prod_ref = (c_n*b_n*A_m*T_n*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)
示例#9
0
    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)
示例#10
0
    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)
示例#11
0
    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(['Fe3+', 'Mn3+'])
        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])

        T = space.debye_waller(h_range, k_range, l_range, nh, nk, nl, U11, U22,
                               U33, U23, U13, U12, a_, b_, c_)

        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)

        Sx, Sy, Sz = magnetic.spin(nu, nv, nw, n_atm)

        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)

        form_factor = magnetic.form(Q, atm, g=2)

        Sx_k, Sy_k, Sz_k, i_dft = magnetic.transform(Sx, Sy, Sz, H, K, L, nu,
                                                     nv, nw, n_atm)

        factors = space.prefactors(form_factor, phase_factor, occupancy)

        factors *= T

        Fx, Fy, Fz, \
        prod_x, prod_y, prod_z = magnetic.structure(Qx_norm, Qy_norm, Qz_norm,
                                                    Sx_k, Sy_k, Sz_k, 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]

        mf = form_factor.reshape(n_hkl, n_atm)
        T = T.reshape(n_hkl, n_atm)

        Sx_m = Sx[m]
        Sy_m = Sy[m]
        Sz_m = Sz[m]
        c_n = occupancy[n]
        f_n = mf[:, n]
        T_n = T[:, n]

        prod_x_ref = (c_n*f_n*Sx_m*T_n*np.exp(1j*(Qx[:,np.newaxis]*rx_m+\
                                                  Qy[:,np.newaxis]*ry_m+\
                                                  Qz[:,np.newaxis]*rz_m)))

        prod_y_ref = (c_n*f_n*Sy_m*T_n*np.exp(1j*(Qx[:,np.newaxis]*rx_m+\
                                                  Qy[:,np.newaxis]*ry_m+\
                                                  Qz[:,np.newaxis]*rz_m)))

        prod_z_ref = (c_n*f_n*Sz_m*T_n*np.exp(1j*(Qx[:,np.newaxis]*rx_m+\
                                                  Qy[:,np.newaxis]*ry_m+\
                                                  Qz[:,np.newaxis]*rz_m)))

        Fx_ref = prod_x_ref.sum(axis=1)
        Fy_ref = prod_y_ref.sum(axis=1)
        Fz_ref = prod_z_ref.sum(axis=1)

        prod_x_ref = prod_x_ref.reshape(n_hkl, nu * nv * nw, n_atm).sum(axis=1)
        prod_y_ref = prod_y_ref.reshape(n_hkl, nu * nv * nw, n_atm).sum(axis=1)
        prod_z_ref = prod_z_ref.reshape(n_hkl, nu * nv * nw, n_atm).sum(axis=1)

        prod_x_ref = prod_x_ref.flatten()
        prod_y_ref = prod_y_ref.flatten()
        prod_z_ref = prod_z_ref.flatten()

        np.testing.assert_array_almost_equal(Fx, Fx_ref)
        np.testing.assert_array_almost_equal(Fy, Fy_ref)
        np.testing.assert_array_almost_equal(Fz, Fz_ref)
        np.testing.assert_array_almost_equal(prod_x, prod_x_ref)
        np.testing.assert_array_almost_equal(prod_y, prod_y_ref)
        np.testing.assert_array_almost_equal(prod_z, prod_z_ref)
示例#12
0
    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(['Fe3+', 'Mn3+'])
        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])

        T = space.debye_waller(h_range, k_range, l_range, nh, nk, nl, U11, U22,
                               U33, U23, U13, U12, a_, b_, c_)

        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)

        Sx, Sy, Sz = magnetic.spin(nu, nv, nw, n_atm)

        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)

        form_factor = magnetic.form(Q, atm, g=2)

        Sx_k, Sy_k, Sz_k, i_dft = magnetic.transform(Sx, Sy, Sz, H, K, L, nu,
                                                     nv, nw, n_atm)

        factors = space.prefactors(form_factor, phase_factor, occupancy)

        factors *= T

        I = magnetic.intensity(Qx_norm, Qy_norm, Qz_norm, \
                               Sx_k, Sy_k, Sz_k, i_dft, factors)

        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]

        mf = form_factor.reshape(n_hkl, n_atm)
        T = T.reshape(n_hkl, n_atm)

        Sx_i, Sx_j, Sx_m = Sx[i], Sx[j], Sx[m]
        Sy_i, Sy_j, Sy_m = Sy[i], Sy[j], Sy[m]
        Sz_i, Sz_j, Sz_m = Sz[i], Sz[j], Sz[m]
        c_k, c_l, c_n = occupancy[k], occupancy[l], occupancy[n]
        f_k, f_l, f_n = mf[:, k], mf[:, l], mf[:, n]
        T_k, T_l, T_n = T[:, k], T[:, l], T[:, n]

        Q_norm_dot_S_i = Qx_norm[:,np.newaxis]*Sx_i\
                       + Qy_norm[:,np.newaxis]*Sy_i\
                       + Qz_norm[:,np.newaxis]*Sz_i
        Q_norm_dot_S_j = Qx_norm[:,np.newaxis]*Sx_j\
                       + Qy_norm[:,np.newaxis]*Sy_j\
                       + Qz_norm[:,np.newaxis]*Sz_j
        Q_norm_dot_S_m = Qx_norm[:,np.newaxis]*Sx_m\
                       + Qy_norm[:,np.newaxis]*Sy_m\
                       + Qz_norm[:,np.newaxis]*Sz_m

        Sx_perp_i = Sx_i - (Q_norm_dot_S_i) * Qx_norm[:, np.newaxis]
        Sx_perp_j = Sx_j - (Q_norm_dot_S_j) * Qx_norm[:, np.newaxis]
        Sx_perp_m = Sx_m - (Q_norm_dot_S_m) * Qx_norm[:, np.newaxis]

        Sy_perp_i = Sy_i - (Q_norm_dot_S_i) * Qy_norm[:, np.newaxis]
        Sy_perp_j = Sy_j - (Q_norm_dot_S_j) * Qy_norm[:, np.newaxis]
        Sy_perp_m = Sy_m - (Q_norm_dot_S_m) * Qy_norm[:, np.newaxis]

        Sz_perp_i = Sz_i - (Q_norm_dot_S_i) * Qz_norm[:, np.newaxis]
        Sz_perp_j = Sz_j - (Q_norm_dot_S_j) * Qz_norm[:, np.newaxis]
        Sz_perp_m = Sz_m - (Q_norm_dot_S_m) * Qz_norm[:, np.newaxis]

        I_ref = ((c_n**2*(f_n*f_n.conj()).real*T_n**2*\
                  (Sx_perp_m**2+Sy_perp_m**2+Sz_perp_m**2)).sum(axis=1)\
              + 2*(c_k*c_l*(f_k*f_l.conj()).real*T_k*T_l*\
                  (Sx_perp_i*Sx_perp_j+Sy_perp_i*Sy_perp_j+Sz_perp_i*Sz_perp_j)*\
                   np.cos(Qx[:,np.newaxis]*rx_ij+\
                          Qy[:,np.newaxis]*ry_ij+\
                          Qz[:,np.newaxis]*rz_ij)).sum(axis=1))/n_xyz

        np.testing.assert_array_almost_equal(I, I_ref)