Пример #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 test_dipole_dipole_interaction_potential(self):

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

        n = nu * nv * nw * n_atm

        M = 2

        Sx = np.random.random((nu, nv, nw, n_atm, M))
        Sy = np.random.random((nu, nv, nw, n_atm, M))
        Sz = np.random.random((nu, nv, nw, n_atm, M))

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

        atm = np.array(['', ''])

        a, b, c, alpha, beta, gamma = 5, 6, 7, np.pi / 2, np.pi / 2, 2 * np.pi / 3

        A = crystal.cartesian(a, b, c, alpha, beta, gamma)
        B = crystal.cartesian(*crystal.reciprocal(a, b, c, alpha, beta, gamma))
        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)

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

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

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

        i, j = np.triu_indices(n)

        Qijm = np.zeros((n, n, 6))
        Qijkl = np.zeros((n, n, 3, 3))

        Q = interaction.dipole_dipole_matrix(rx, ry, rz, nu, nv, nw, n_atm, A,
                                             B, R)

        Qijm[i, j, :] = Q

        Qijm[j, i, :] = Qijm[i, j, :]

        Qijkl[:, :, 0, 0] = Qijm[:, :, 0]
        Qijkl[:, :, 1, 1] = Qijm[:, :, 1]
        Qijkl[:, :, 2, 2] = Qijm[:, :, 2]
        Qijkl[:, :, 1, 2] = Qijkl[:, :, 2, 1] = Qijm[:, :, 3]
        Qijkl[:, :, 0, 2] = Qijkl[:, :, 2, 0] = Qijm[:, :, 4]
        Qijkl[:, :, 0, 1] = Qijkl[:, :, 1, 0] = Qijm[:, :, 5]

        p0 = simulation.dipole_dipole_interaction_potential(Sx, Sy, Sz, Q)

        Sx, Sy, Sz = Sx.reshape(n, M), Sy.reshape(n, M), Sz.reshape(n, M)

        S = np.column_stack((Sx, Sy, Sz)).reshape(-1, 3, M)

        p = np.einsum('ijkl,jlm->ijklm', Qijkl, S).sum(axis=1)

        np.testing.assert_array_almost_equal(p, p0)
Пример #3
0
    def test_site(self):

        a = b = 10
        c = 13

        alpha = beta = np.pi/2
        gamma = 2*np.pi/3

        A = crystal.cartesian(a, b, c, alpha, beta, gamma)

        operators = [u'x,y,z',u'-y,x-y,z',u'-x+y,-x,z',
                     u'-x,-y,z',u'y,-x+y,z',u'x-y,x,z']

        coordinates = [0.35,0.65,0.1234]
        pg, mult, sp_pos = symmetry.site(operators, coordinates, A, tol=1e-1)
        self.assertEqual(pg, '1')
        self.assertEqual(mult, 6)
        self.assertEqual(sp_pos, 'x,y,z')

        coordinates = [0.5,0.0,0.1234]
        pg, mult, sp_pos = symmetry.site(operators, coordinates, A, tol=1e-1)
        self.assertEqual(pg, '2')
        self.assertEqual(mult, 3)
        self.assertEqual(sp_pos, '1/2,0,z')
        
        coordinates = [0.3333,0.6667,0.1234]
        pg, mult, sp_pos = symmetry.site(operators, coordinates, A, tol=1e-1)
        self.assertEqual(pg, '3')
        self.assertEqual(mult, 2)
        self.assertEqual(sp_pos, '1/3,2/3,z')

        coordinates = [0.0,0.0,0.1234]
        pg, mult, sp_pos = symmetry.site(operators, coordinates, A, tol=1e-1)
        self.assertEqual(pg, '6')
        self.assertEqual(mult, 1)
        self.assertEqual(sp_pos, '0,0,z')

        gamma = np.pi/2

        A = crystal.cartesian(a, b, c, alpha, beta, gamma)

        operators = [u'x,y,z',u'-x,-y,z',
                     u'-y+1/2,x+1/2,z',u'y+1/2,-x+1/2,z',
                     u'-x+1/2,y+1/2,-z',u'x+1/2,-y+1/2,-z',
                     u'y,x,-z',u'-y,-x,-z']

        coordinates = [0.2,0.2,0.5]
        pg, mult, sp_pos = symmetry.site(operators, coordinates, A, tol=1e-1)
        self.assertEqual(pg, '2')
        self.assertEqual(mult, 4)
        self.assertEqual(sp_pos, 'x/2+y/2,x/2+y/2,1/2')
Пример #4
0
    def crystal_reciprocal_matrices(self, a, b, c, alpha, beta, gamma):

        constants = a, b, c, alpha, beta, gamma

        inv_constants = crystal.reciprocal(*constants)

        a_, b_, c_, alpha_, beta_, gamma_ = inv_constants

        A_ = crystal.cartesian(*inv_constants)
        B_ = crystal.cartesian(*constants)
        R_ = crystal.cartesian_rotation(*inv_constants)

        C_ = crystal.cartesian_moment(*inv_constants)
        D_ = crystal.cartesian_displacement(*inv_constants)

        return A_, B_, R_, C_, D_
Пример #5
0
    def crystal_matrices(self, a, b, c, alpha, beta, gamma):

        constants = a, b, c, alpha, beta, gamma

        inv_constants = crystal.reciprocal(*constants)

        a_, b_, c_, alpha_, beta_, gamma_ = inv_constants

        A = crystal.cartesian(*constants)
        B = crystal.cartesian(*inv_constants)
        R = crystal.cartesian_rotation(*constants)

        C = crystal.cartesian_moment(*constants)
        D = crystal.cartesian_displacement(*constants)

        return A, B, R, C, D
Пример #6
0
    def test_cartesian_rotation(self):

        a, b, c, alpha, beta, gamma = 5, 6, 7, np.pi / 2, np.pi / 3, np.pi / 4

        A = crystal.cartesian(a, b, c, alpha, beta, gamma)

        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_)

        hkl = np.array([-3.3, 1.1, 2.5])
        uvw = np.array([4.2, -2.7, 1.8])

        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)

        self.assertAlmostEqual(hkl.dot(uvw), A.dot(uvw).dot(R.dot(B.dot(hkl))))
Пример #7
0
    def test_cartesian(self):

        a, b, c, alpha, beta, gamma = 5, 6, 7, np.pi / 2, np.pi / 3, np.pi / 4

        A = crystal.cartesian(a, b, c, alpha, beta, gamma)

        G = crystal.metric(a, b, c, alpha, beta, gamma)

        U = scipy.linalg.cholesky(G, lower=False)
        np.testing.assert_array_almost_equal(A, U)

        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_)

        G_ = crystal.metric(a_, b_, c_, alpha_, beta_, gamma_)

        U_ = scipy.linalg.cholesky(G_, lower=False)
        np.testing.assert_array_almost_equal(B, U_)
Пример #8
0
    def test_volume(self):

        a, b, c, alpha, beta, gamma = 5, 6, 7, np.pi / 2, np.pi / 3, np.pi / 4

        V = crystal.volume(a, b, c, alpha, beta, gamma)

        A = crystal.cartesian(a, b, c, alpha, beta, gamma)

        u, v, w = np.dot(A,
                         [1, 0, 0]), np.dot(A,
                                            [0, 1, 0]), np.dot(A, [0, 0, 1])

        self.assertAlmostEqual(V, np.dot(u, np.cross(v, w)))
Пример #9
0
    def test_reciprocal(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_)

        u, v, w = np.dot(A,
                         [1, 0, 0]), np.dot(A,
                                            [0, 1, 0]), np.dot(A, [0, 0, 1])

        V = np.dot(u, np.cross(v, w))

        self.assertAlmostEqual(a_, np.linalg.norm(np.cross(v, w) / V))
        self.assertAlmostEqual(b_, np.linalg.norm(np.cross(w, u) / V))
        self.assertAlmostEqual(c_, np.linalg.norm(np.cross(u, v) / V))

        u_, v_, w_ = np.dot(B, [1, 0, 0]), np.dot(B, [0, 1, 0]), np.dot(
            B, [0, 0, 1])

        self.assertAlmostEqual(
            alpha_,
            np.arccos(
                np.dot(v_, w_) / np.linalg.norm(v_) / np.linalg.norm(w_)))
        self.assertAlmostEqual(
            beta_,
            np.arccos(
                np.dot(w_, u_) / np.linalg.norm(w_) / np.linalg.norm(u_)))
        self.assertAlmostEqual(
            gamma_,
            np.arccos(
                np.dot(u_, v_) / np.linalg.norm(u_) / np.linalg.norm(v_)))
Пример #10
0
    def test_interplanar(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_)

        u_, v_, w_ = np.dot(B, [1, 0, 0]), np.dot(B, [0, 1, 0]), np.dot(
            B, [0, 0, 1])

        h0, k0, l0 = 1, 2, -3
        h1, k1, l1 = 2, -1, -4

        angle = crystal.interplanar(a, b, c, alpha, beta, gamma, \
                                    h0, k0, l0, h1, k1, l1)

        angle_ref = np.arccos(
            np.dot(h0 * u_ + k0 * v_ + l0 * w_, h1 * u_ + k1 * v_ + l1 * w_) /
            np.linalg.norm(h0 * u_ + k0 * v_ + l0 * w_) /
            np.linalg.norm(h1 * u_ + k1 * v_ + l1 * w_))

        self.assertAlmostEqual(angle, angle_ref)

        h0, k0, l0 = np.array([2, 3]), np.array([3, 2]), np.array([-4, 4])
        h1, k1, l1 = np.array([-3, 3]), np.array([2, 2]), np.array([-1, 4])

        angle = crystal.interplanar(a, b, c, alpha, beta, gamma, \
                                    h0, k0, l0, h1, k1, l1)

        angle_ref = np.zeros(2)

        for i in range(2):
            dot = np.dot(h0[i] * u_ + k0[i] * v_ + l0[i] * w_,
                         h1[i] * u_ + k1[i] * v_ + l1[i] * w_)

            norm0 = np.linalg.norm(h0[i] * u_ + k0[i] * v_ + l0[i] * w_)
            norm1 = np.linalg.norm(h1[i] * u_ + k1[i] * v_ + l1[i] * w_)
            if (np.isclose(norm0, 0) or np.isclose(norm1, 0)):
                angle_ref[i] = 0
            elif np.isclose(dot / norm0 / norm1, 1):
                angle_ref[i] = 0
            else:
                angle_ref[i] = np.arccos(dot / (norm0 * norm1))

        np.testing.assert_array_almost_equal(angle, angle_ref)
Пример #11
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)
Пример #12
0
    def test_d(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_)

        u_, v_, w_ = np.dot(B, [1, 0, 0]), np.dot(B, [0, 1, 0]), np.dot(
            B, [0, 0, 1])

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

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

        d_ref = 1 / np.sqrt(
            np.dot(h * u_ + k * v_ + l * w_, h * u_ + k * v_ + l * w_))

        self.assertAlmostEqual(d, d_ref)

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

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

        d_ref = np.zeros(2)

        for i in range(2):
            inv_d = np.sqrt(
                np.dot(h[i] * u_ + k[i] * v_ + l[i] * w_,
                       h[i] * u_ + k[i] * v_ + l[i] * w_))

            if np.isclose(inv_d, 0):
                d_ref[i] = np.nan
            else:
                d_ref[i] = 1 / inv_d

        np.testing.assert_array_almost_equal(d, d_ref)
Пример #13
0
    def test_disordered(self):

        folder = os.path.abspath(os.path.join(directory, '..', 'data'))

        uc_dict = crystal.unitcell(folder=folder,
                                   filename='CaTiOSiO4.cif',
                                   tol=1e-4)

        u = uc_dict['u']
        v = uc_dict['v']
        w = uc_dict['w']
        occ = uc_dict['occupancy']
        disp = uc_dict['displacement']
        mom = uc_dict['moment']
        atm = uc_dict['atom']
        n_atm = uc_dict['n_atom']

        nu, nv, nw = 2, 3, 4

        constants = crystal.parameters(folder=folder, filename='CaTiOSiO4.cif')

        A = crystal.cartesian(*constants)
        C = crystal.cartesian_moment(*constants)
        D = crystal.cartesian_displacement(*constants)

        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)

        U11, U22, U33, U23, U13, U12 = disp.T
        U = np.row_stack(displacive.cartesian(U11, U22, U33, U23, U13, U12, D))
        Ux, Uy, Uz = displacive.expansion(nu, nv, nw, n_atm, U)

        A_r = occupational.composition(nu, nv, nw, n_atm, occ)
        delta = (occ * (1 + A_r.reshape(nu, nv, nw, n_atm))).flatten()

        mu1, mu2, mu3 = mom.T
        mu = np.row_stack(magnetic.cartesian(mu1, mu2, mu3, C))
        Sx, Sy, Sz = magnetic.spin(nu, nv, nw, n_atm, mu)

        crystal.disordered(delta,
                           Ux,
                           Uy,
                           Uz,
                           Sx,
                           Sy,
                           Sz,
                           rx,
                           ry,
                           rz,
                           nu,
                           nv,
                           nw,
                           atm,
                           A,
                           folder + '/disordered_CaTiOSiO4.cif',
                           folder=folder,
                           filename='CaTiOSiO4.cif',
                           ulim=[0, nu],
                           vlim=[0, nv],
                           wlim=[0, nw])

        UC_dict = crystal.unitcell(folder=folder,
                                   filename='disordered_CaTiOSiO4.cif',
                                   tol=1e-4)

        Atm = UC_dict['atom']

        np.testing.assert_array_equal(atms == Atm, True)

        os.remove(folder + '/disordered_CaTiOSiO4.cif')

        uc_dict = crystal.unitcell(folder=folder,
                                   filename='CuMnO2.mcif',
                                   tol=1e-4)

        u = uc_dict['u']
        v = uc_dict['v']
        w = uc_dict['w']
        occ = uc_dict['occupancy']
        disp = uc_dict['displacement']
        mom = uc_dict['moment']
        atm = uc_dict['atom']
        n_atm = uc_dict['n_atom']

        nu, nv, nw = 2, 3, 4

        constants = crystal.parameters(folder=folder, filename='CuMnO2.mcif')

        A = crystal.cartesian(*constants)
        C = crystal.cartesian_moment(*constants)
        D = crystal.cartesian_displacement(*constants)

        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)

        Uiso = disp.flatten()
        Ux, Uy, Uz = displacive.expansion(nu, nv, nw, n_atm, Uiso)

        A_r = occupational.composition(nu, nv, nw, n_atm, occ)
        delta = (occ * (1 + A_r.reshape(nu, nv, nw, n_atm))).flatten()

        mu1, mu2, mu3 = mom.T
        mu = np.row_stack(magnetic.cartesian(mu1, mu2, mu3, C))
        Sx, Sy, Sz = magnetic.spin(nu, nv, nw, n_atm, mu)

        crystal.disordered(delta,
                           Ux,
                           Uy,
                           Uz,
                           Sx,
                           Sy,
                           Sz,
                           rx,
                           ry,
                           rz,
                           nu,
                           nv,
                           nw,
                           atm,
                           A,
                           folder + '/disordered_CuMnO2.mcif',
                           folder=folder,
                           filename='CuMnO2.mcif',
                           ulim=[0, nu],
                           vlim=[0, nv],
                           wlim=[0, nw])

        UC_dict = crystal.unitcell(folder=folder,
                                   filename='disordered_CuMnO2.mcif',
                                   tol=1e-4)

        Atm = UC_dict['atom']

        np.testing.assert_array_equal(atms == Atm, True)

        os.remove(folder + '/disordered_CuMnO2.mcif')
Пример #14
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)
Пример #15
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)
Пример #16
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)
Пример #17
0
    def test_heisenberg_cluster(self):

        np.random.seed(13)

        nu, nv, nw = 3, 4, 5

        n_atm = 2

        atm = np.array(['Fe3+', 'Fe3+'])

        u, v, w = np.array([0, 0.5]), np.array([0, 0.5]), np.array([0, 0.5])

        a, b, c, alpha, beta, gamma = 5, 5, 5, np.pi / 2, np.pi / 2, np.pi / 2

        A = crystal.cartesian(a, b, c, alpha, beta, gamma)

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

        pair_dict = crystal.pairs(u, v, w, atm, A, extend=True)

        img_ind_i, img_ind_j, img_ind_k, atm_ind = [], [], [], []

        du, dv, dw = [], [], []

        for i in pair_dict.keys():
            for pair in pair_dict[i].keys():
                pair_no, atm_j = pair
                ind_i, ind_j, ind_k, atm_a = [], [], [], []
                for j, img in zip(*pair_dict[i][pair]):
                    ind_i.append(img[0])
                    ind_j.append(img[1])
                    ind_k.append(img[2])
                    atm_a.append(j)
                    du.append(u[j] - u[i] + img[0])
                    dv.append(v[j] - v[i] + img[1])
                    dw.append(w[j] - w[i] + img[2])
                img_ind_i.append(ind_i)
                img_ind_j.append(ind_j)
                img_ind_k.append(ind_k)
                atm_ind.append(atm_a)

        img_ind_i = np.array(img_ind_i, dtype=np.int_)
        img_ind_j = np.array(img_ind_j, dtype=np.int_)
        img_ind_k = np.array(img_ind_k, dtype=np.int_)
        atm_ind = np.array(atm_ind, dtype=np.int_)

        du, dv, dw = np.array(du), np.array(dv), np.array(dw)

        dx, dy, dz = crystal.transform(du, dv, dw, A)

        dx = dx.reshape(atm_ind.shape)
        dy = dy.reshape(atm_ind.shape)
        dz = dz.reshape(atm_ind.shape)

        d = np.sqrt(dx**2 + dy**2 + dz**2)

        n_pair = atm_ind.shape[1]

        dist = np.round(d / 1e-2).astype(int)

        _, inv_ind = np.unique(dist, return_inverse=True)

        pair_ind = np.arange(n_pair + 1,
                             dtype=np.int_)[inv_ind].reshape(n_atm, n_pair)

        mask = d < 0.99 * np.sqrt(2 * a**2)

        n_pair = mask.sum() // n_atm

        dx = dx[mask].reshape(n_atm, n_pair)
        dy = dy[mask].reshape(n_atm, n_pair)
        dz = dz[mask].reshape(n_atm, n_pair)

        pair_ind = pair_ind[mask].reshape(n_atm, n_pair)

        img_ind_i = img_ind_i[mask].reshape(n_atm, n_pair)
        img_ind_j = img_ind_j[mask].reshape(n_atm, n_pair)
        img_ind_k = img_ind_k[mask].reshape(n_atm, n_pair)
        atm_ind = atm_ind[mask].reshape(n_atm, n_pair)

        d_xyz = np.stack((dx, dy, dz))

        inv_d_xyz = -d_xyz

        pair_inv = np.zeros((n_atm, n_pair), dtype=np.int_)

        for i in range(n_atm):
            for p in range(n_pair):
                for q in range(n_pair):
                    if (np.allclose(d_xyz[:, i, p], inv_d_xyz[:, atm_ind[i, p],
                                                              q])):
                        pair_inv[i, p] = q

        pair_ij = np.zeros((n_atm, n_pair), dtype=np.intc)

        J = np.zeros((n_pair, 3, 3))
        K = np.zeros((n_atm, 3, 3))
        g = np.zeros((n_atm, 3, 3))
        B = np.zeros(3)

        Jx, Jy, Jz = -3, -2, -1
        Kx, Ky, Kz = -1, -3, -2
        gx, gy, gz = 2, 3, 4
        Bx, By, Bz = 1, 2, 3

        J[:n_pair, :, :] = np.array([[Jx, 0, 0], [0, Jy, 0], [0, 0, Jz]],
                                    dtype=float)

        K[:n_atm, :, :] = np.array([[Kx, 0, 0], [0, Ky, 0], [0, 0, Kz]],
                                   dtype=float)

        g[:n_atm, :, :] = np.array([[gx, 0, 0], [0, gy, 0], [0, 0, gz]],
                                   dtype=float)

        B[:] = Bx, By, Bz

        n = nu * nv * nw * n_atm

        Q = np.random.random((n * (n + 1) // 2, 6)) * 0

        ix, iy, iz = space.cell(nu, nv, nw, A)

        rx, ry, rz, ion = space.real(ux, uy, uz, ix, iy, iz, atm)

        M, N = 2, 10

        T0, T1 = 0.01, 5

        T_range = np.logspace(np.log2(T0), np.log2(T1), M, base=2)

        kB = 0.08617

        theta = 2 * np.pi * np.random.rand(nu, nv, nw, n_atm, M)
        phi = np.arccos(1 - 2 * np.random.rand(nu, nv, nw, n_atm, M))

        Sx = np.sin(phi) * np.cos(theta)
        Sy = np.sin(phi) * np.sin(theta)
        Sz = np.cos(phi)

        E, T_range = simulation.heisenberg_cluster(Sx, Sy, Sz, J, K, g, B, Q,
                                                   atm_ind, img_ind_i,
                                                   img_ind_j, img_ind_k,
                                                   pair_ind, pair_inv, pair_ij,
                                                   T_range, kB, N)

        E_ref = simulation.magnetic_energy(Sx, Sy, Sz, J, K, g, B, atm_ind,
                                           img_ind_i, img_ind_j, img_ind_k,
                                           pair_ind, pair_ij)

        V_ref = simulation.dipole_dipole_interaction_energy(Sx, Sy, Sz, Q)

        E0 = E_ref.sum(axis=(0, 1, 2, 3, 4)) + V_ref.sum(axis=(0, 1, 2))

        np.testing.assert_array_almost_equal(E, E0)
Пример #18
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)
Пример #19
0
    def test_dipole_dipole_matrix(self):

        a = b = c = 4.04
        alpha = beta = gamma = np.pi / 2

        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)
        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)
        B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_)

        nu, nv, nw, n_atm = 8, 8, 16, 1

        n = nu * nv * nw * n_atm

        atm = np.array(['Ti'])

        u = np.array([0.5])
        v = np.array([0.5])
        w = np.array([0.5])

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

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

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

        px = np.zeros(n)
        py = np.zeros(n)
        pz = np.zeros(n)

        i, j = np.triu_indices(n)

        Qijm = np.zeros((n, n, 6))
        Qijkl = np.zeros((n, n, 3, 3))

        Qijm[i,
             j, :] = interaction.dipole_dipole_matrix(rx, ry, rz, nu, nv, nw,
                                                      n_atm, A, B, R)

        Qijm[j, i, :] = Qijm[i, j, :]

        Qijkl[:, :, 0, 0] = Qijm[:, :, 0]
        Qijkl[:, :, 1, 1] = Qijm[:, :, 1]
        Qijkl[:, :, 2, 2] = Qijm[:, :, 2]
        Qijkl[:, :, 1, 2] = Qijkl[:, :, 2, 1] = Qijm[:, :, 3]
        Qijkl[:, :, 0, 2] = Qijkl[:, :, 2, 0] = Qijm[:, :, 4]
        Qijkl[:, :, 0, 1] = Qijkl[:, :, 1, 0] = Qijm[:, :, 5]

        np.testing.assert_array_almost_equal(Qijkl, np.swapaxes(Qijkl, 0, 1))
        np.testing.assert_array_almost_equal(Qijkl, np.swapaxes(Qijkl, 2, 3))

        px.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        py.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        pz.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 1

        p = np.column_stack((px, py, pz))
        E = np.einsum('ijkl,jl->ik', Qijkl, p) * a**3 / 2
        np.testing.assert_array_almost_equal(E[..., 2], -2.09440, 2)

        px.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        py.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        pz.reshape(nu, nv, nw, n_atm)[:, :, 0::2, :] = +1
        pz.reshape(nu, nv, nw, n_atm)[:, :, 1::2, :] = -1

        p = np.column_stack((px, py, pz))
        E = np.einsum('ijkl,jl->ik', Qijkl, p)[..., 2] * a**3 / 2
        np.testing.assert_array_almost_equal(E[..., 0::2], +4.84372, 2)
        np.testing.assert_array_almost_equal(E[..., 1::2], -4.84372, 2)

        px.reshape(nu, nv, nw, n_atm)[:, :, 0::2, :] = +1
        px.reshape(nu, nv, nw, n_atm)[:, :, 1::2, :] = -1
        py.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        pz.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0

        p = np.column_stack((px, py, pz))
        E = np.einsum('ijkl,jl->ik', Qijkl, p)[..., 0] * a**3 / 2
        np.testing.assert_array_almost_equal(E[0::2], -2.42186, 2)
        np.testing.assert_array_almost_equal(E[1::2], +2.42186, 2)

        px.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        py.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        pz.reshape(nu, nv, nw, n_atm)[0::2, 0::2, :, :] = +1
        pz.reshape(nu, nv, nw, n_atm)[1::2, 1::2, :, :] = +1
        pz.reshape(nu, nv, nw, n_atm)[0::2, 1::2, :, :] = -1
        pz.reshape(nu, nv, nw, n_atm)[1::2, 0::2, :, :] = -1

        p = np.column_stack((px, py, pz))
        E = np.einsum('ijkl,jl->ik', Qijkl, p)[..., 2] * a**3 / 2
        E = E.reshape(nu, nv, nw, n_atm)
        np.testing.assert_array_almost_equal(E[0::2, 0::2, :, :], -2.67679, 2)
        np.testing.assert_array_almost_equal(E[1::2, 1::2, :, :], -2.67679, 2)
        np.testing.assert_array_almost_equal(E[0::2, 1::2, :, :], +2.67679, 2)
        np.testing.assert_array_almost_equal(E[1::2, 0::2, :, :], +2.67679, 2)

        px.reshape(nu, nv, nw, n_atm)[0::2, 0::2, :, :] = +1
        px.reshape(nu, nv, nw, n_atm)[1::2, 1::2, :, :] = +1
        px.reshape(nu, nv, nw, n_atm)[0::2, 1::2, :, :] = -1
        px.reshape(nu, nv, nw, n_atm)[1::2, 0::2, :, :] = -1
        py.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        pz.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0

        p = np.column_stack((px, py, pz))
        E = np.einsum('ijkl,jl->ik', Qijkl, p)[..., 0] * a**3 / 2
        E = E.reshape(nu, nv, nw, n_atm)
        np.testing.assert_array_almost_equal(E[0::2, 0::2, :, :], +1.33839, 2)
        np.testing.assert_array_almost_equal(E[1::2, 1::2, :, :], +1.33839, 2)
        np.testing.assert_array_almost_equal(E[0::2, 1::2, :, :], -1.33839, 2)
        np.testing.assert_array_almost_equal(E[1::2, 0::2, :, :], -1.33839, 2)

        px.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        py.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        pz.reshape(nu, nv, nw, n_atm)[0::2, 0::2, 0::2, :] = +1
        pz.reshape(nu, nv, nw, n_atm)[1::2, 1::2, 0::2, :] = +1
        pz.reshape(nu, nv, nw, n_atm)[0::2, 1::2, 1::2, :] = +1
        pz.reshape(nu, nv, nw, n_atm)[1::2, 0::2, 1::2, :] = +1
        pz.reshape(nu, nv, nw, n_atm)[1::2, 1::2, 1::2, :] = -1
        pz.reshape(nu, nv, nw, n_atm)[1::2, 0::2, 0::2, :] = -1
        pz.reshape(nu, nv, nw, n_atm)[0::2, 1::2, 0::2, :] = -1
        pz.reshape(nu, nv, nw, n_atm)[0::2, 0::2, 1::2, :] = -1

        p = np.column_stack((px, py, pz))
        E = np.einsum('ijkl,jl->ik', Qijkl, p) * a**3 / 2
        np.testing.assert_array_almost_equal(E, 0, decimal=2)

        a = c = 2 * 4.04
        b = 4.04
        alpha = beta = gamma = np.pi / 2

        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)
        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)
        B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_)

        nu, nv, nw, n_atm = 8, 8, 8, 2

        n = nu * nv * nw * n_atm

        atm = np.array(['Ti', 'Ti'])

        u = np.array([0.0, 0.5])
        v = np.array([0.0, 0.0])
        w = np.array([0.0, 0.5])

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

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

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

        px = np.zeros(n)
        py = np.zeros(n)
        pz = np.zeros(n)

        i, j = np.triu_indices(n)

        Qijm = np.zeros((n, n, 6))
        Qijkl = np.zeros((n, n, 3, 3))

        Qijm[i,
             j, :] = interaction.dipole_dipole_matrix(rx, ry, rz, nu, nv, nw,
                                                      n_atm, A, B, R)

        Qijm[j, i, :] = Qijm[i, j, :]

        Qijkl[:, :, 0, 0] = Qijm[:, :, 0]
        Qijkl[:, :, 1, 1] = Qijm[:, :, 1]
        Qijkl[:, :, 2, 2] = Qijm[:, :, 2]
        Qijkl[:, :, 1, 2] = Qijkl[:, :, 2, 1] = Qijm[:, :, 3]
        Qijkl[:, :, 0, 2] = Qijkl[:, :, 2, 0] = Qijm[:, :, 4]
        Qijkl[:, :, 0, 1] = Qijkl[:, :, 1, 0] = Qijm[:, :, 5]

        px.reshape(nu, nv, nw, n_atm)[0::2, :, 0::2, :] = -np.sqrt(2) / 2
        px.reshape(nu, nv, nw, n_atm)[1::2, :, 1::2, :] = -np.sqrt(2) / 2
        px.reshape(nu, nv, nw, n_atm)[0::2, :, 1::2, :] = +np.sqrt(2) / 2
        px.reshape(nu, nv, nw, n_atm)[1::2, :, 0::2, :] = +np.sqrt(2) / 2
        py.reshape(nu, nv, nw, n_atm)[:, :, :, :] = 0
        pz.reshape(nu, nv, nw, n_atm)[0::2, :, 0::2, :] = +np.sqrt(2) / 2
        pz.reshape(nu, nv, nw, n_atm)[1::2, :, 1::2, :] = +np.sqrt(2) / 2
        pz.reshape(nu, nv, nw, n_atm)[0::2, :, 1::2, :] = -np.sqrt(2) / 2
        pz.reshape(nu, nv, nw, n_atm)[1::2, :, 0::2, :] = -np.sqrt(2) / 2

        p = np.column_stack((px, py, pz))
        E = np.einsum('ijkl,jl->ik', Qijkl, p) * a**3 / 16
        E = np.sqrt(np.sum(E**2, axis=1))
        np.testing.assert_array_almost_equal(E, 2.93226, 1)
Пример #20
0
    def test_charge_dipole_matrix(self):

        a = b = c = 5.4187
        alpha = beta = gamma = np.pi / 2

        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)
        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)
        B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_)

        nu, nv, nw, n_atm = 5, 5, 5, 12

        n = nu * nv * nw * n_atm

        atm = np.array(
            ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'Fe', 'Fe', 'Fe', 'Fe'])

        x = 0.385

        u = np.array([
            x, 1 - x, 0.5 - x, 0.5 + x, x, 1 - x, 0.5 + x, 0.5 - x, 0.0, 0.0,
            0.5, 0.5
        ])
        v = np.array([
            x, 1 - x, 0.5 + x, 0.5 - x, 0.5 - x, 0.5 + x, x, 1 - x, 0.0, 0.5,
            0.0, 0.5
        ])
        w = np.array([
            x, 1 - x, x, 1 - x, 0.5 + x, 0.5 - x, 0.5 - x, 0.5 + x, 0.0, 0.5,
            0.5, 0.0
        ])

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

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

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

        z = np.zeros(n)

        px = np.zeros(n)
        py = np.zeros(n)
        pz = np.zeros(n)

        i, j = np.triu_indices(n)

        Qijk = np.zeros((n, n, 3))

        Qijk[i,
             j, :] = interaction.charge_dipole_matrix(rx, ry, rz, nu, nv, nw,
                                                      n_atm, A, B, R)

        Qijk[j, i, :] = Qijk[i, j, :]

        z[atms == 'S'] = -1
        z[atms == 'Fe'] = +2

        px.reshape(nu, nv, nw, n_atm)[:, :, :, [0, 3, 4, 6]] = +np.sqrt(3) / 3
        px.reshape(nu, nv, nw, n_atm)[:, :, :, [1, 2, 5, 7]] = -np.sqrt(3) / 3

        py.reshape(nu, nv, nw, n_atm)[:, :, :, [0, 2, 5, 6]] = +np.sqrt(3) / 3
        py.reshape(nu, nv, nw, n_atm)[:, :, :, [1, 3, 4, 7]] = -np.sqrt(3) / 3

        pz.reshape(nu, nv, nw, n_atm)[:, :, :, [0, 2, 4, 7]] = +np.sqrt(3) / 3
        pz.reshape(nu, nv, nw, n_atm)[:, :, :, [1, 3, 5, 6]] = -np.sqrt(3) / 3

        p = np.column_stack((px, py, pz))

        am = np.array([-1.957, -7.458])
        ad = np.array([-1.184, -2.898])
        bm = 2.632
        bd = -2.561

        np.testing.assert_array_almost_equal(Qijk, np.swapaxes(Qijk, 0, 1))

        E = -np.einsum('i,i->...', z, np.einsum('ijk,jk->i', Qijk, p)) / n
        self.assertAlmostEqual(E, -2 * (bm / a**2 + bd / a**3) / a, places=1)

        Qij = np.zeros((n, n))

        Qij[i, j] = interaction.charge_charge_matrix(rx, ry, rz, nu, nv, nw,
                                                     n_atm, A, B, R)

        Qij[j, i] = Qij[i, j]

        E = np.dot(z, np.dot(Qij, z)) / n
        self.assertAlmostEqual(E, (2 * am[0] + am[1]) / a * 2 / 3, places=2)

        Qijm = np.zeros((n, n, 6))
        Qijkl = np.zeros((n, n, 3, 3))

        Qijm[i,
             j, :] = interaction.dipole_dipole_matrix(rx, ry, rz, nu, nv, nw,
                                                      n_atm, A, B, R)

        Qijm[j, i, :] = Qijm[i, j, :]

        Qijkl[:, :, 0, 0] = Qijm[:, :, 0]
        Qijkl[:, :, 1, 1] = Qijm[:, :, 1]
        Qijkl[:, :, 2, 2] = Qijm[:, :, 2]
        Qijkl[:, :, 1, 2] = Qijkl[:, :, 2, 1] = Qijm[:, :, 3]
        Qijkl[:, :, 0, 2] = Qijkl[:, :, 2, 0] = Qijm[:, :, 4]
        Qijkl[:, :, 0, 1] = Qijkl[:, :, 1, 0] = Qijm[:, :, 5]

        E = np.einsum('ik,ik->...', p, np.einsum('ijkl,jl->ik', Qijkl, p)) / n
        self.assertAlmostEqual(E,
                               -(2 * ad[0] + ad[1]) / a**3 * 2 / 3,
                               places=2)
Пример #21
0
    def test_charge_charge_matrix(self):

        a = b = c = 4.1
        alpha = beta = gamma = np.pi / 2

        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)
        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)
        B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_)

        nu, nv, nw, n_atm = 4, 4, 4, 2

        n = nu * nv * nw * n_atm

        atm = np.array(['Cs', 'Cl'])

        u = np.array([0.0, 0.5])
        v = np.array([0.0, 0.5])
        w = np.array([0.0, 0.5])

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

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

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

        z = np.zeros(n)

        i, j = np.triu_indices(n)

        Qij = np.zeros((n, n))

        Qij[i, j] = interaction.charge_charge_matrix(rx, ry, rz, nu, nv, nw,
                                                     n_atm, A, B, R)

        Qij[j, i] = Qij[i, j]

        z[atms == 'Cs'] = +1
        z[atms == 'Cl'] = -1

        np.testing.assert_array_almost_equal(Qij, Qij.T)

        phi = np.dot(Qij, z) * a * np.sqrt(3) / 2
        np.testing.assert_array_almost_equal(phi[atms == 'Cs'], -1.762675, 2)
        np.testing.assert_array_almost_equal(phi[atms == 'Cl'], +1.762675, 2)

        a = b = c = 5.7
        alpha = beta = gamma = np.pi / 2

        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)
        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)
        B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_)

        nu, nv, nw, n_atm = 4, 4, 4, 8

        n = nu * nv * nw * n_atm

        atm = np.array(['Na', 'Na', 'Na', 'Na', 'Cl', 'Cl', 'Cl', 'Cl'])

        u = np.array([0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, 0.0])
        v = np.array([0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5])
        w = np.array([0.0, 0.5, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0])

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

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

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

        z = np.zeros(n)

        i, j = np.triu_indices(n)

        Qij = np.zeros((n, n))

        Qij[i, j] = interaction.charge_charge_matrix(rx, ry, rz, nu, nv, nw,
                                                     n_atm, A, B, R)

        Qij[j, i] = Qij[i, j]

        z[atms == 'Na'] = +1
        z[atms == 'Cl'] = -1

        phi = np.dot(Qij, z) * a / 2
        np.testing.assert_array_almost_equal(phi[atms == 'Na'], -1.747565, 2)
        np.testing.assert_array_almost_equal(phi[atms == 'Cl'], +1.747565, 2)

        a = b = 3.819
        c = 6.246
        alpha = beta = np.pi / 2
        gamma = 2 * np.pi / 3

        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)
        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)
        B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_)

        nu, nv, nw, n_atm = 6, 6, 6, 4

        n = nu * nv * nw * n_atm

        atm = np.array(['Zn', 'Zn', 'S', 'S'])

        u = np.array([2 / 3, 1 / 3, 2 / 3, 1 / 3])
        v = np.array([1 / 3, 2 / 3, 1 / 3, 2 / 3])
        w = np.array([0.0, 0.5, 0.625, 0.125])

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

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

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

        z = np.zeros(n)

        i, j = np.triu_indices(n)

        Qij = np.zeros((n, n))

        Qij[i, j] = interaction.charge_charge_matrix(rx, ry, rz, nu, nv, nw,
                                                     n_atm, A, B, R)

        Qij[j, i] = Qij[i, j]

        z[atms == 'Zn'] = +2
        z[atms == 'S'] = -2

        phi = np.dot(Qij, z) * c * 0.375
        np.testing.assert_array_almost_equal(phi[atms == 'Zn'], -3.28146, 2)
        np.testing.assert_array_almost_equal(phi[atms == 'S'], +3.28146, 2)

        a = b = c = 5.52
        alpha = beta = gamma = np.pi / 2

        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)
        R = crystal.cartesian_rotation(a, b, c, alpha, beta, gamma)
        B = crystal.cartesian(a_, b_, c_, alpha_, beta_, gamma_)

        nu, nv, nw, n_atm = 5, 5, 5, 12

        n = nu * nv * nw * n_atm

        atm = np.array(
            ['Ca', 'Ca', 'Ca', 'Ca', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'])

        u = np.array(
            [0, 0, 0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 0.75, 0.75, 0.75, 0.75])
        v = np.array(
            [0, 0.5, 0, 0.5, 0.75, 0.25, 0.25, 0.75, 0.75, 0.25, 0.25, 0.75])
        w = np.array(
            [0, 0.5, 0.5, 0, 0.75, 0.75, 0.25, 0.25, 0.25, 0.25, 0.75, 0.75])

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

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

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

        z = np.zeros(n)

        i, j = np.triu_indices(n)

        Qij = np.zeros((n, n))

        Qij[i, j] = interaction.charge_charge_matrix(rx, ry, rz, nu, nv, nw,
                                                     n_atm, A, B, R)

        Qij[j, i] = Qij[i, j]

        z[atms == 'Ca'] = +2
        z[atms == 'F'] = -1

        phi = np.dot(Qij, z) * a * 0.25 * np.sqrt(3)
        np.testing.assert_array_almost_equal(phi[atms == 'Ca'], -3.276110, 2)
        np.testing.assert_array_almost_equal(phi[atms == 'F'], +1.762675, 2)
Пример #22
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)
Пример #23
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)
Пример #24
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)
Пример #25
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)
Пример #26
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)
Пример #27
0
    def test_pairs(self):

        folder = os.path.abspath(os.path.join(directory, '..', 'data'))

        uc_dict = crystal.unitcell(folder=folder, filename='CaTiOSiO4.cif')

        u = uc_dict['u']
        v = uc_dict['v']
        w = uc_dict['w']
        atms = uc_dict['atom']

        constants = crystal.parameters(folder=folder, filename='CaTiOSiO4.cif')

        A = crystal.cartesian(*constants)

        pair_dict = crystal.pairs(u, v, w, atms, A)

        pairs = []
        coordination = []
        for i in pair_dict.keys():
            atm = atms[i]
            if (atm != 'O'):
                pair_num, pair_atm = list(pair_dict[i])[0]
                coord_num = len(pair_dict[i][(pair_num, pair_atm)][0])
            pairs.append('_'.join((atm, pair_atm)))
            coordination.append(coord_num)

        pairs = np.array(pairs)
        coordination = np.array(coordination)

        mask = pairs == 'Ca_O'
        np.testing.assert_array_equal(coordination[mask], 7)

        mask = pairs == 'Ti_O'
        np.testing.assert_array_equal(coordination[mask], 6)

        mask = pairs == 'Si_O'
        np.testing.assert_array_equal(coordination[mask], 4)

        uc_dict = crystal.unitcell(folder=folder, filename='Tb2Ir3Ga9.cif')

        u = uc_dict['u']
        v = uc_dict['v']
        w = uc_dict['w']
        atms = uc_dict['atom']

        constants = crystal.parameters(folder=folder, filename='Tb2Ir3Ga9.cif')

        A = crystal.cartesian(*constants)

        pair_dict = crystal.pairs(u, v, w, atms, A)

        pairs = []
        for i in pair_dict.keys():
            atm = atms[i]
            if (atm == 'Tb'):
                for pair in pair_dict[i].keys():
                    if pair[1] == 'Tb':
                        for ind in pair_dict[i][pair][0]:
                            pairs.append([i, ind])

        pairs = np.unique(pairs)

        self.assertEqual(pairs.size, (atms == 'Tb').sum())

        pair_dict = crystal.pairs(u, v, w, atms, A, extend=True)

        for i in pair_dict.keys():
            d_ref = 0
            for pair in pair_dict[i].keys():
                j, atm_j = pair
                for j, img in zip(*pair_dict[i][pair]):
                    du = u[j] - u[i] + img[0]
                    dv = v[j] - v[i] + img[1]
                    dw = w[j] - w[i] + img[2]
                    dx, dy, dz = crystal.transform(du, dv, dw, A)
                    d = np.sqrt(dx**2 + dy**2 + dz**2)
                    self.assertGreaterEqual(np.round(d, 6), np.round(d_ref, 6))
                    self.assertEqual(atms[j], atm_j)
                    d_ref = d
Пример #28
0
    def test_magnetic_energy(self):

        nu, nv, nw = 3, 4, 5

        n_atm = 2

        atm = np.array(['Fe3+', 'Fe3+'])

        u, v, w = np.array([0, 0.5]), np.array([0, 0.5]), np.array([0, 0.5])

        a, b, c, alpha, beta, gamma = 5, 5, 5, np.pi / 2, np.pi / 2, np.pi / 2

        A = crystal.cartesian(a, b, c, alpha, beta, gamma)

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

        pair_dict = crystal.pairs(u, v, w, atm, A, extend=True)

        img_ind_i, img_ind_j, img_ind_k, atm_ind = [], [], [], []

        du, dv, dw = [], [], []

        for i in pair_dict.keys():
            for pair in pair_dict[i].keys():
                pair_no, atm_j = pair
                ind_i, ind_j, ind_k, atm_a = [], [], [], []
                for j, img in zip(*pair_dict[i][pair]):
                    ind_i.append(img[0])
                    ind_j.append(img[1])
                    ind_k.append(img[2])
                    atm_a.append(j)
                    du.append(u[j] - u[i] + img[0])
                    dv.append(v[j] - v[i] + img[1])
                    dw.append(w[j] - w[i] + img[2])
                img_ind_i.append(ind_i)
                img_ind_j.append(ind_j)
                img_ind_k.append(ind_k)
                atm_ind.append(atm_a)

        img_ind_i = np.array(img_ind_i, dtype=np.int_)
        img_ind_j = np.array(img_ind_j, dtype=np.int_)
        img_ind_k = np.array(img_ind_k, dtype=np.int_)
        atm_ind = np.array(atm_ind, dtype=np.int_)

        du, dv, dw = np.array(du), np.array(dv), np.array(dw)

        dx, dy, dz = crystal.transform(du, dv, dw, A)

        dx = dx.reshape(atm_ind.shape)
        dy = dy.reshape(atm_ind.shape)
        dz = dz.reshape(atm_ind.shape)

        d = np.sqrt(dx**2 + dy**2 + dz**2)

        n_pair = atm_ind.shape[1]

        dist = np.round(d / 1e-2).astype(int)

        _, inv_ind = np.unique(dist, return_inverse=True)

        pair_ind = np.arange(n_pair + 1,
                             dtype=np.int_)[inv_ind].reshape(n_atm, n_pair)

        mask = d < 0.99 * np.sqrt(2 * a**2)

        n_pair = mask.sum() // n_atm

        dx = dx[mask].reshape(n_atm, n_pair)
        dy = dy[mask].reshape(n_atm, n_pair)
        dz = dz[mask].reshape(n_atm, n_pair)

        pair_ind = pair_ind[mask].reshape(n_atm, n_pair)

        img_ind_i = img_ind_i[mask].reshape(n_atm, n_pair)
        img_ind_j = img_ind_j[mask].reshape(n_atm, n_pair)
        img_ind_k = img_ind_k[mask].reshape(n_atm, n_pair)
        atm_ind = atm_ind[mask].reshape(n_atm, n_pair)

        d_xyz = np.stack((dx, dy, dz))

        inv_d_xyz = -d_xyz

        pair_inv = np.zeros((n_atm, n_pair), dtype=np.int_)

        for i in range(n_atm):
            for p in range(n_pair):
                for q in range(n_pair):
                    if (np.allclose(d_xyz[:, i, p], inv_d_xyz[:, atm_ind[i, p],
                                                              q])):
                        pair_inv[i, p] = q

        pair_ij = np.zeros((n_atm, n_pair), dtype=np.intc)

        J = np.zeros((n_pair, 3, 3))
        K = np.zeros((n_atm, 3, 3))
        g = np.zeros((n_atm, 3, 3))
        B = np.zeros(3)

        Jx, Jy, Jz = -3, -2, -1
        Kx, Ky, Kz = -1, -3, -2
        gx, gy, gz = 2, 3, 4
        Bx, By, Bz = 1, 2, 3

        J[:n_pair, :, :] = np.array([[Jx, 0, 0], [0, Jy, 0], [0, 0, Jz]],
                                    dtype=float)

        K[:n_atm, :, :] = np.array([[Kx, 0, 0], [0, Ky, 0], [0, 0, Kz]],
                                   dtype=float)

        g[:n_atm, :, :] = np.array([[gx, 0, 0], [0, gy, 0], [0, 0, gz]],
                                   dtype=float)

        B[:] = Bx, By, Bz

        ix, iy, iz = space.cell(nu, nv, nw, A)

        rx, ry, rz, ion = space.real(ux, uy, uz, ix, iy, iz, atm)

        n = nu * nv * nw * n_atm

        M = 3

        Sx = np.zeros((nu, nv, nw, n_atm, M))
        Sy = np.zeros((nu, nv, nw, n_atm, M))
        Sz = np.zeros((nu, nv, nw, n_atm, M))

        Sx[..., 0], Sy[..., 0], Sz[..., 0] = 1, 0, 0
        Sx[..., 1], Sy[..., 1], Sz[..., 1] = 0, 1, 0
        Sx[..., 2], Sy[..., 2], Sz[..., 2] = 0, 0, 1

        E = simulation.magnetic_energy(Sx, Sy, Sz, J, K, g, B, atm_ind,
                                       img_ind_i, img_ind_j, img_ind_k,
                                       pair_ind, pair_ij)

        self.assertAlmostEqual(E[..., 0].sum(),
                               -(0.5 * Jx * n_pair + Kx + Bx * gx) * n)
        self.assertAlmostEqual(E[..., 1].sum(),
                               -(0.5 * Jy * n_pair + Ky + By * gy) * n)
        self.assertAlmostEqual(E[..., 2].sum(),
                               -(0.5 * Jz * n_pair + Kz + Bz * gz) * n)