Beispiel #1
0
    def __init__(self, name=None, calc=None, M=None, spinorbit=None):

        self.name = name
        self.calc = GPAW(calc, txt=None, communicator=mpi.serial_comm)
        self.M = np.array(M, dtype=float)
        self.spinorbit = spinorbit

        self.gd = self.calc.wfs.gd.new_descriptor()

        self.kd = self.calc.wfs.kd
        if self.calc.wfs.mode is 'pw':
            self.pd = self.calc.wfs.pd
        else:
            self.pd = PWDescriptor(ecut=None,
                                   gd=self.gd,
                                   kd=self.kd,
                                   dtype=complex)

        self.acell_cv = self.gd.cell_cv
        self.bcell_cv = 2 * np.pi * self.gd.icell_cv
        self.vol = self.gd.volume
        self.BZvol = (2 * np.pi)**3 / self.vol

        self.nb = self.calc.get_number_of_bands()

        self.v_Knm = None
        if spinorbit:
            if mpi.world.rank == 0:
                print('Calculating spinorbit Corrections')
            self.nb = 2 * self.calc.get_number_of_bands()
            self.e_mK, self.v_Knm = get_spinorbit_eigenvalues(self.calc,
                                                              return_wfs=True)
            if mpi.world.rank == 0:
                print('Done with the spinorbit Corrections')
Beispiel #2
0
    def get_spinorbit_corrections(self, return_spin=True, return_wfs=False,
                                  bands=None, gwqeh_file=None, dft=False,
                                  eig_file=None):
        """Gets the spinorbit corrections to the eigenvalues"""
        calc = self.calc
        bandrange = self.bandrange

        if not dft:
            try:
                e_kn = self.gw_file['qp'][0]
            except:
                e_kn = self.gw_file[b'qp'][0]
        else:
            if eig_file is not None:
                e_kn = pickle.load(open(eig_file))[0]
            else:
                e_kn = self.get_dft_eigenvalues()[:,bandrange[0]:bandrange[-1]]

        eSO_nk, s_nk, v_knm = get_spinorbit_eigenvalues(
            calc,
            return_spin=return_spin, return_wfs=return_wfs,
            bands=range(bandrange[0], bandrange[-1]+1),
            gw_kn=e_kn)

        e_kn = eSO_nk.T
        return e_kn, v_knm
Beispiel #3
0
    def get_spinorbit_corrections(self, return_spin=True, return_wfs=False,
                                  bands=None, gwqeh_file=None, dft=False,
                                  eig_file=None):
        """Gets the spinorbit corrections to the eigenvalues"""
        calc = self.calc
        bandrange = self.bandrange
        print(bandrange[0])
        if not dft:
            e_kn = self.gw_file['qp'][0]
            print('Shape')
            print(e_kn[:, bandrange[0]:bandrange[-1]].shape)
        else:
            if eig_file is not None:
                e_kn = pickle.load(open(eig_file))[0]
            else:
                e_kn = self.get_dft_eigenvalues()

        eSO_nk, s_nk, v_knm = get_spinorbit_eigenvalues(
            calc,
            return_spin=return_spin, return_wfs=return_wfs,
            bands=range(bandrange[0], bandrange[-1]),
            gw_kn=e_kn[:, :bandrange[-1] - bandrange[0]])

        # eSO_kn = np.sort(e_skn,axis=2)
        e_kn = eSO_nk.T
        return e_kn, v_knm
Beispiel #4
0
def raw_spinorbit_orbital_LDOS(paw, a, spin, angular='spdf', theta=0, phi=0):
    """Like former, but with spinorbit coupling."""

    from gpaw.spinorbit import get_spinorbit_eigenvalues
    from gpaw.spinorbit import get_spinorbit_projections

    e_mk, v_knm = get_spinorbit_eigenvalues(paw,
                                            return_wfs=True,
                                            theta=theta,
                                            phi=phi)
    e_mk /= Hartree
    ns = paw.wfs.nspins
    w_k = paw.wfs.kd.weight_k
    nk = len(w_k)
    nb = len(e_mk)

    if a < 0:
        # Allow list-style negative indices; we'll need the positive a for the
        # dictionary lookup later
        a = len(paw.wfs.setups) + a

    setup = paw.wfs.setups[a]
    energies = np.empty(nb * nk)
    weights_xi = np.empty((nb * nk, setup.ni))
    x = 0
    for k, w in enumerate(w_k):
        energies[x:x + nb] = e_mk[:, k]
        P_ami = get_spinorbit_projections(paw, k, v_knm[k])
        if ns == 2:
            weights_xi[x:x + nb, :] = w * np.absolute(P_ami[a][:, spin::2])**2
        else:
            weights_xi[x:x + nb, :] = w * np.absolute(P_ami[a][:, 0::2])**2 / 2
            weights_xi[x:x +
                       nb, :] += w * np.absolute(P_ami[a][:, 1::2])**2 / 2
        x += nb

    if angular is None:
        return energies, weights_xi
    elif isinstance(angular, int):
        return energies, weights_xi[:, angular]
    else:
        projectors = get_angular_projectors(setup, angular, type='bound')
        weights = np.sum(np.take(weights_xi, indices=projectors, axis=1),
                         axis=1)
        return energies, weights
# No spin-orbit

ef = calc2.get_fermi_level()
e_kn = np.array([
    calc1.get_eigenvalues(kpt=k) for k in range(len(calc1.get_ibz_k_points()))
])
e_nk = e_kn.T
e_nk -= ef

for e_k in e_nk:
    plt.plot(x, e_k, '--', c='0.5')

# Spin-orbit calculation

e_nk = get_spinorbit_eigenvalues(calc2)
set_calculator(calc2, e_nk.T)
ef = calc2.get_fermi_level()
e_nk = get_spinorbit_eigenvalues(calc1, scale=1.0)
e_nk -= ef

plt.xticks(X, [r'$\Gamma$', 'Z', 'F', r'$\Gamma$', 'L'], size=24)
plt.yticks(size=20)
for i in range(len(X))[1:-1]:
    plt.plot(2 * [X[i]], [1.1 * np.min(e_nk), 1.1 * np.max(e_nk)],
             c='0.5',
             linewidth=0.5)
for e_k in e_nk:
    plt.plot(x, e_k, c='b')
plt.ylabel(r'$\varepsilon_n(k)$ [eV]', size=24)
plt.axis([0, x[-1], -1.7, 1.7])
Beispiel #6
0
#plt.rc('text', usetex=True)

calc = GPAW('WS2_bands.gpw', txt=None)

x = np.loadtxt('WS2_kpath.dat')
X = np.loadtxt('WS2_highsym.dat')
e_kn = np.array([
    calc.get_eigenvalues(kpt=k)[:20]
    for k in range(len(calc.get_ibz_k_points()))
])
e_nk = e_kn.T
e_nk -= calc.get_fermi_level()
for e_k in e_nk:
    plt.plot(x, e_k, '--', c='0.5')

e_nk, s_nk = get_spinorbit_eigenvalues(calc, return_spin=True, bands=range(20))
e_nk -= calc.get_fermi_level()
s_nk = (s_nk + 1.0) / 2.0

plt.xticks(X, ['M', 'K', r'$\Gamma$', '-K', '-M'], size=20)
plt.yticks(size=20)
for i in range(len(X))[1:-1]:
    plt.plot(2 * [X[i]], [1.1 * np.min(e_nk), 1.1 * np.max(e_nk)],
             c='0.5',
             linewidth=0.5)

plt.scatter(np.tile(x, len(e_nk)),
            e_nk.reshape(-1),
            c=s_nk.reshape(-1),
            edgecolor=plt.get_cmap('jet')(s_nk.reshape(-1)),
            s=2,
Beispiel #7
0
from ase import Atoms
from gpaw import GPAW
from gpaw.spinorbit import get_spinorbit_eigenvalues
from gpaw.test import equal

a = Atoms('Kr')
a.center(vacuum=3.0)

calc = GPAW(mode='pw', xc='LDA')

a.calc = calc
a.get_potential_energy()

e_n = calc.get_eigenvalues()
e_m = get_spinorbit_eigenvalues(calc)

equal(e_n[0] - e_m[0], 0.0, 1.0e-3)
equal(e_n[1] - e_m[2], 0.452, 1.0e-3)
equal(e_n[2] - e_m[4], -0.226, 1.0e-3)
Beispiel #8
0
    calc.get_eigenvalues(kpt=k, spin=s)
    for k in range(len(calc.get_ibz_k_points()))
] for s in range(2)])
e_kn = np.reshape(np.swapaxes(e_skn, 0, 1),
                  (len(e_skn[0]), 2 * len(e_skn[0, 0])))
e_kn = np.sort(e_kn, 1)
f_skn = np.array([[
    calc.get_occupation_numbers(kpt=k, spin=s)
    for k in range(len(calc.get_ibz_k_points()))
] for s in range(2)])
f_kn = np.reshape(np.swapaxes(f_skn, 0, 1),
                  (len(f_skn[0]), 2 * len(f_skn[0, 0])))
f_kn = np.sort(f_kn, 1)[:, ::-1]
E = np.sum(e_kn * f_kn)

# Spinorbit
theta_i = [i * np.pi / 20 for i in range(21)]
for theta in theta_i:
    calc = GPAW('gs_Co.gpw', txt=None)
    e_mk = get_spinorbit_eigenvalues(calc, theta=theta, phi=0.0)
    set_calculator(calc, e_mk.T)
    f_km = np.array([
        calc.get_occupation_numbers(kpt=k)
        for k in range(len(calc.get_ibz_k_points()))
    ])

    E_so = np.sum(e_mk.T * f_km)

    with open('anisotropy.dat', 'a') as f:
        print(theta, E, E_so, file=f)
Beispiel #9
0
def parallel_transport(calc,
                       direction=0,
                       spinors=True,
                       name=None,
                       scale=1.0,
                       bands=None,
                       theta=0.0,
                       phi=0.0):

    if isinstance(calc, str):
        calc = GPAW(calc, txt=None, communicator=serial_comm)

    if bands is None:
        nv = int(calc.get_number_of_electrons())
        bands = range(nv)

    cell_cv = calc.wfs.gd.cell_cv
    icell_cv = (2 * np.pi) * np.linalg.inv(cell_cv).T
    r_g = calc.wfs.gd.get_grid_point_coordinates()
    Ng = np.prod(np.shape(r_g)[1:]) * (spinors + 1)

    dO_aii = []
    for ia in calc.wfs.kpt_u[0].P_ani.keys():
        dO_ii = calc.wfs.setups[ia].dO_ii
        if spinors:
            # Spinor projections require doubling of the (identical) orbitals
            dO_jj = np.zeros((2 * len(dO_ii), 2 * len(dO_ii)), complex)
            dO_jj[::2, ::2] = dO_ii
            dO_jj[1::2, 1::2] = dO_ii
            dO_aii.append(dO_jj)
        else:
            dO_aii.append(dO_ii)

    N_c = calc.wfs.kd.N_c
    assert 1 in np.delete(N_c, direction)
    Nkx = N_c[0]
    Nky = N_c[1]
    Nkz = N_c[2]

    Nk = Nkx * Nky * Nkz
    Nloc = N_c[direction]
    Npar = Nk // Nloc

    # Parallelization stuff
    myKsize = -(-Npar // (world.size))
    myKrange = range(rank * myKsize, min((rank + 1) * myKsize, Npar))
    myKsize = len(myKrange)

    # Get array of k-point indices of the path. q index is loc direction
    kpts_kq = []
    for k in range(Npar):
        if direction == 0:
            kpts_kq.append(list(range(k, Nkx * Nky, Nky)))
        if direction == 1:
            if Nkz == 1:
                kpts_kq.append(list(range(k * Nky, (k + 1) * Nky)))
            else:
                kpts_kq.append(list(range(k, Nkz * Nky, Nkz)))
        if direction == 2:
            kpts_kq.append(list(range(k * Nloc, (k + 1) * Nloc)))

    G_c = np.array([0, 0, 0])
    G_c[direction] = 1
    G_v = np.dot(G_c, icell_cv)

    kpts_kc = calc.get_bz_k_points()
    kpts_kv = np.dot(kpts_kc, icell_cv)
    if Nloc > 1:
        b_c = kpts_kc[kpts_kq[0][1]] - kpts_kc[kpts_kq[0][0]]
        b_v = np.dot(b_c, icell_cv)
    else:
        b_v = G_v

    e_mk, v_knm = get_spinorbit_eigenvalues(calc,
                                            return_wfs=True,
                                            scale=scale,
                                            theta=theta,
                                            phi=phi)

    phi_km = np.zeros((Npar, len(bands)), float)
    S_km = np.zeros((Npar, len(bands)), float)
    # Loop over the direction parallel components
    for k in myKrange:
        U_qmm = [np.eye(len(bands))]
        print(k)
        qpts_q = kpts_kq[k]
        # Loop over kpoints in the phase direction
        for q in range(Nloc - 1):
            iq1 = qpts_q[q]
            iq2 = qpts_q[q + 1]
            # print(kpts_kc[iq1], kpts_kc[iq2])
            if q == 0:
                u1_nsG = get_spinorbit_wavefunctions(calc, iq1,
                                                     v_knm[iq1])[bands]
                # Transform from psi-like to u-like
                u1_nsG[:] *= np.exp(-1.0j *
                                    gemmdot(kpts_kv[iq1], r_g, beta=0.0))
                P1_ani = get_spinorbit_projections(calc, iq1, v_knm[iq1])

            u2_nsG = get_spinorbit_wavefunctions(calc, iq2, v_knm[iq2])[bands]
            u2_nsG[:] *= np.exp(-1.0j * gemmdot(kpts_kv[iq2], r_g, beta=0.0))
            P2_ani = get_spinorbit_projections(calc, iq2, v_knm[iq2])

            M_mm = get_overlap(calc, bands,
                               np.reshape(u1_nsG, (len(u1_nsG), Ng)),
                               np.reshape(u2_nsG, (len(u2_nsG), Ng)), P1_ani,
                               P2_ani, dO_aii, b_v)
            V_mm, sing_m, W_mm = np.linalg.svd(M_mm)
            U_mm = np.dot(V_mm, W_mm).conj()
            u_nysxz = np.dot(U_mm, np.swapaxes(u2_nsG, 0, 3))
            u_nxsyz = np.swapaxes(u_nysxz, 1, 3)
            u_nsxyz = np.swapaxes(u_nxsyz, 1, 2)
            u2_nsG = u_nsxyz
            for a in range(len(calc.atoms)):
                P2_ni = P2_ani[a][bands]
                P2_ni = np.dot(U_mm, P2_ni)
                P2_ani[a][bands] = P2_ni
            U_qmm.append(U_mm)
            u1_nsG = u2_nsG
            P1_ani = P2_ani
        U_qmm = np.array(U_qmm)

        # Fix phases for last point
        iq0 = qpts_q[0]
        if Nloc == 1:
            u1_nsG = get_spinorbit_wavefunctions(calc, iq0, v_knm[iq0])[bands]
            u1_nsG[:] *= np.exp(-1.0j * gemmdot(kpts_kv[iq0], r_g, beta=0.0))
            P1_ani = get_spinorbit_projections(calc, iq0, v_knm[iq0])
        u2_nsG = get_spinorbit_wavefunctions(calc, iq0, v_knm[iq0])[bands]
        u2_nsG[:] *= np.exp(-1.0j * gemmdot(kpts_kv[iq0], r_g, beta=0.0))
        u2_nsG[:] *= np.exp(-1.0j * gemmdot(G_v, r_g, beta=0.0))
        P2_ani = get_spinorbit_projections(calc, iq0, v_knm[iq0])
        for a in range(len(calc.atoms)):
            P2_ni = P2_ani[a][bands]
            # P2_ni *= np.exp(-1.0j * np.dot(G_v, r_av[a]))
            P2_ani[a][bands] = P2_ni
        M_mm = get_overlap(calc, bands, np.reshape(u1_nsG, (len(u1_nsG), Ng)),
                           np.reshape(u2_nsG, (len(u2_nsG), Ng)), P1_ani,
                           P2_ani, dO_aii, b_v)
        V_mm, sing_m, W_mm = np.linalg.svd(M_mm)
        U_mm = np.dot(V_mm, W_mm).conj()
        u_nysxz = np.dot(U_mm, np.swapaxes(u2_nsG, 0, 3))
        u_nxsyz = np.swapaxes(u_nysxz, 1, 3)
        u_nsxyz = np.swapaxes(u_nxsyz, 1, 2)
        u2_nsG = u_nsxyz
        for a in range(len(calc.atoms)):
            P2_ni = P2_ani[a][bands]
            P2_ni = np.dot(U_mm, P2_ni)
            P2_ani[a][bands] = P2_ni

        # Get overlap between first kpts and its smoothly translated image
        u2_nsG[:] *= np.exp(1.0j * gemmdot(G_v, r_g, beta=0.0))
        for a in range(len(calc.atoms)):
            P2_ni = P2_ani[a][bands]
            # P2_ni *= np.exp(1.0j * np.dot(G_v, r_av[a]))
            P2_ani[a][bands] = P2_ni
        u1_nsG = get_spinorbit_wavefunctions(calc, iq0, v_knm[iq0])[bands]
        u1_nsG[:] *= np.exp(-1.0j * gemmdot(kpts_kv[iq0], r_g, beta=0.0))
        P1_ani = get_spinorbit_projections(calc, iq0, v_knm[iq0])
        M_mm = get_overlap(calc, bands, np.reshape(u1_nsG, (len(u1_nsG), Ng)),
                           np.reshape(u2_nsG, (len(u2_nsG), Ng)), P1_ani,
                           P2_ani, dO_aii, np.array([0.0, 0.0, 0.0]))
        l_m, l_mm = np.linalg.eig(M_mm)
        phi_km[k] = np.angle(l_m)
        print(phi_km[k] / 2 / np.pi)

        A_mm = np.zeros_like(l_mm, complex)
        for q in range(Nloc):
            iq = qpts_q[q]
            U_mm = U_qmm[q]
            v_nm = U_mm.dot(v_knm[iq][:, bands].T).T
            A_mm += np.dot(v_nm[::2].T.conj(), v_nm[::2])
            A_mm -= np.dot(v_nm[1::2].T.conj(), v_nm[1::2])
        A_mm /= Nloc
        S_km[k] = np.diag(l_mm.T.conj().dot(A_mm).dot(l_mm)).real

    world.sum(phi_km)
    world.sum(S_km)

    np.savez('phases_%s.npz' % name, phi_km=phi_km, S_km=S_km)
Beispiel #10
0
    def calculate(self, optical=True, ac=1.0):

        if self.spinors:
            """Calculate spinors. Here m is index of eigenvalues with SOC
            and n is the basis of eigenstates withour SOC. Below m is used
            for unoccupied states and n is used for occupied states so be
            careful!"""

            print('Diagonalizing spin-orbit Hamiltonian', file=self.fd)
            param = self.calc.parameters
            if not param['symmetry'] == 'off':
                print('Calculating KS wavefunctions without symmetry ' +
                      'for spin-orbit', file=self.fd)
                if not op.isfile('gs_nosym.gpw'):
                    calc_so = GPAW(**param)
                    calc_so.set(symmetry='off',
                                fixdensity=True,
                                txt='gs_nosym.txt')
                    calc_so.atoms = self.calc.atoms
                    calc_so.density = self.calc.density
                    calc_so.get_potential_energy()
                    calc_so.write('gs_nosym.gpw')
                calc_so = GPAW('gs_nosym.gpw', txt=None,
                               communicator=serial_comm)
                e_mk, v_knm = get_spinorbit_eigenvalues(calc_so,
                                                        return_wfs=True,
                                                        scale=self.scale)
                del calc_so
            else:
                e_mk, v_knm = get_spinorbit_eigenvalues(self.calc,
                                                        return_wfs=True,
                                                        scale=self.scale)
            e_mk /= Hartree

        # Parallelization stuff
        nK = self.kd.nbzkpts
        myKrange, myKsize, mySsize = self.parallelisation_sizes()

        # Calculate exchange interaction
        qd0 = KPointDescriptor([self.q_c])
        pd0 = PWDescriptor(self.ecut, self.calc.wfs.gd, complex, qd0)
        ikq_k = self.kd.find_k_plus_q(self.q_c)
        v_G = get_coulomb_kernel(pd0, self.kd.N_c, truncation=self.truncation,
                                 wstc=self.wstc)
        if optical:
            v_G[0] = 0.0

        self.pair = PairDensity(self.calc, self.ecut, world=serial_comm,
                                txt='pair.txt')

        # Calculate direct (screened) interaction and PAW corrections
        if self.mode == 'RPA':
            Q_aGii = self.pair.initialize_paw_corrections(pd0)
        else:
            self.get_screened_potential(ac=ac)
            if (self.qd.ibzk_kc - self.q_c < 1.0e-6).all():
                iq0 = self.qd.bz2ibz_k[self.kd.where_is_q(self.q_c,
                                                          self.qd.bzk_kc)]
                Q_aGii = self.Q_qaGii[iq0]
            else:
                Q_aGii = self.pair.initialize_paw_corrections(pd0)

        # Calculate pair densities, eigenvalues and occupations
        so = self.spinors + 1
        Nv, Nc = so * self.nv, so * self.nc
        Ns = self.spins
        rhoex_KsmnG = np.zeros((nK, Ns, Nv, Nc, len(v_G)), complex)
        # rhoG0_Ksmn = np.zeros((nK, Ns, Nv, Nc), complex)
        df_Ksmn = np.zeros((nK, Ns, Nv, Nc), float) # -(ev - ec)
        deps_ksmn = np.zeros((myKsize, Ns, Nv, Nc), float) # -(fv - fc)
        if np.allclose(self.q_c, 0.0):
            optical_limit = True
        else:
            optical_limit = False
        get_pair = self.pair.get_kpoint_pair
        get_rho = self.pair.get_pair_density
        if self.spinors:
            # Get all pair densities to allow for SOC mixing
            # Use twice as many no-SOC states as BSE bands to allow mixing
            vi_s = [2 * self.val_sn[0, 0] - self.val_sn[0, -1] - 1]
            vf_s = [2 * self.con_sn[0, -1] - self.con_sn[0, 0] + 2]
            if vi_s[0] < 0:
                vi_s[0] = 0
            ci_s, cf_s = vi_s, vf_s
            ni, nf = vi_s[0], vf_s[0]
            mvi = 2 * self.val_sn[0, 0]
            mvf = 2 * (self.val_sn[0, -1] + 1)
            mci = 2 * self.con_sn[0, 0]
            mcf = 2 * (self.con_sn[0, -1] + 1)
        else:
            vi_s, vf_s = self.val_sn[:, 0], self.val_sn[:, -1] + 1
            ci_s, cf_s = self.con_sn[:, 0], self.con_sn[:, -1] + 1
        for ik, iK in enumerate(myKrange):
            for s in range(Ns):
                pair = get_pair(pd0, s, iK,
                                vi_s[s], vf_s[s], ci_s[s], cf_s[s])
                m_m = np.arange(vi_s[s], vf_s[s])
                n_n = np.arange(ci_s[s], cf_s[s])
                if self.gw_skn is not None:
                    iKq = self.calc.wfs.kd.find_k_plus_q(self.q_c, [iK])[0]
                    epsv_m = self.gw_skn[s, iK, :self.nv]
                    epsc_n = self.gw_skn[s, iKq, self.nv:]
                    deps_ksmn[ik] = -(epsv_m[:, np.newaxis] - epsc_n)
                elif self.spinors:
                    iKq = self.calc.wfs.kd.find_k_plus_q(self.q_c, [iK])[0]
                    epsv_m = e_mk[mvi:mvf, iK]
                    epsc_n = e_mk[mci:mcf, iKq]
                    deps_ksmn[ik, s] = -(epsv_m[:, np.newaxis] - epsc_n)
                else:
                    deps_ksmn[ik, s] = -pair.get_transition_energies(m_m, n_n)

                df_mn = pair.get_occupation_differences(self.val_sn[s],
                                                        self.con_sn[s])
                rho_mnG = get_rho(pd0, pair,
                                  m_m, n_n,
                                  optical_limit=optical_limit,
                                  direction=self.direction,
                                  Q_aGii=Q_aGii,
                                  extend_head=False)
                if self.spinors:
                    if optical_limit:
                        deps0_mn = -pair.get_transition_energies(m_m, n_n)
                        rho_mnG[:, :, 0] *= deps0_mn
                    df_Ksmn[iK, s, ::2, ::2] = df_mn
                    df_Ksmn[iK, s, ::2, 1::2] = df_mn
                    df_Ksmn[iK, s, 1::2, ::2] = df_mn
                    df_Ksmn[iK, s, 1::2, 1::2] = df_mn
                    vecv0_nm = v_knm[iK][::2][ni:nf, mvi:mvf]
                    vecc0_nm = v_knm[iKq][::2][ni:nf, mci:mcf]
                    rho_0mnG = np.dot(vecv0_nm.T.conj(),
                                      np.dot(vecc0_nm.T, rho_mnG))
                    vecv1_nm = v_knm[iK][1::2][ni:nf, mvi:mvf]
                    vecc1_nm = v_knm[iKq][1::2][ni:nf, mci:mcf]
                    rho_1mnG = np.dot(vecv1_nm.T.conj(),
                                      np.dot(vecc1_nm.T, rho_mnG))
                    rhoex_KsmnG[iK, s] = rho_0mnG + rho_1mnG
                    if optical_limit:
                        rhoex_KsmnG[iK, s, :, :, 0] /= deps_ksmn[ik, s]
                else:
                    df_Ksmn[iK, s] = pair.get_occupation_differences(m_m, n_n)
                    rhoex_KsmnG[iK, s] = rho_mnG

        if self.eshift is not None:
            deps_ksmn[np.where(df_Ksmn[myKrange] > 1.0e-3)] += self.eshift
            deps_ksmn[np.where(df_Ksmn[myKrange] < -1.0e-3)] -= self.eshift

        world.sum(df_Ksmn)
        world.sum(rhoex_KsmnG)

        self.rhoG0_S = np.reshape(rhoex_KsmnG[:, :, :, :, 0], -1)

        if hasattr(self, 'H_sS'):
            return

        # Calculate Hamiltonian
        t0 = time()
        print('Calculating %s matrix elements at q_c = %s'
              % (self.mode, self.q_c), file=self.fd)
        H_ksmnKsmn = np.zeros((myKsize, Ns, Nv, Nc, nK, Ns, Nv, Nc), complex)
        for ik1, iK1 in enumerate(myKrange):
            for s1 in range(Ns):
                kptv1 = self.pair.get_k_point(s1, iK1, vi_s[s1], vf_s[s1])
                kptc1 = self.pair.get_k_point(s1, ikq_k[iK1], ci_s[s1],
                                              cf_s[s1])
                rho1_mnG = rhoex_KsmnG[iK1, s1]

                #rhoG0_Ksmn[iK1, s1] = rho1_mnG[:, :, 0]
                rho1ccV_mnG = rho1_mnG.conj()[:, :] * v_G
                for s2 in range(Ns):
                    for Q_c in self.qd.bzk_kc:
                        iK2 = self.kd.find_k_plus_q(Q_c, [kptv1.K])[0]
                        rho2_mnG = rhoex_KsmnG[iK2, s2]
                        rho2_mGn = np.swapaxes(rho2_mnG, 1, 2)
                        H_ksmnKsmn[ik1, s1, :, :, iK2, s2, :, :] += (
                            np.dot(rho1ccV_mnG, rho2_mGn))
                        if not self.mode == 'RPA' and s1 == s2:
                            ikq = ikq_k[iK2]
                            kptv2 = self.pair.get_k_point(s1, iK2, vi_s[s1],
                                                          vf_s[s1])
                            kptc2 = self.pair.get_k_point(s1, ikq, ci_s[s1],
                                                          cf_s[s1])
                            rho3_mmG, iq = self.get_density_matrix(kptv1,
                                                                   kptv2)
                            rho4_nnG, iq = self.get_density_matrix(kptc1,
                                                                   kptc2)
                            if self.spinors:
                                vec0_nm = v_knm[iK1][::2][ni:nf, mvi:mvf]
                                vec1_nm = v_knm[iK1][1::2][ni:nf, mvi:mvf]
                                vec2_nm = v_knm[iK2][::2][ni:nf, mvi:mvf]
                                vec3_nm = v_knm[iK2][1::2][ni:nf, mvi:mvf]
                                rho_0mnG = np.dot(vec0_nm.T.conj(),
                                                  np.dot(vec2_nm.T, rho3_mmG))
                                rho_1mnG = np.dot(vec1_nm.T.conj(),
                                                  np.dot(vec3_nm.T, rho3_mmG))
                                rho3_mmG = rho_0mnG + rho_1mnG
                                vec0_nm = v_knm[ikq_k[iK1]][::2][ni:nf, mci:mcf]
                                vec1_nm = v_knm[ikq_k[iK1]][1::2][ni:nf,mci:mcf]
                                vec2_nm = v_knm[ikq][::2][ni:nf, mci:mcf]
                                vec3_nm = v_knm[ikq][1::2][ni:nf, mci:mcf]
                                rho_0mnG = np.dot(vec0_nm.T.conj(),
                                                  np.dot(vec2_nm.T, rho4_nnG))
                                rho_1mnG = np.dot(vec1_nm.T.conj(),
                                                  np.dot(vec3_nm.T, rho4_nnG))
                                rho4_nnG = rho_0mnG + rho_1mnG

                            rho3ccW_mmG = np.dot(rho3_mmG.conj(),
                                                 self.W_qGG[iq])
                            W_mmnn = np.dot(rho3ccW_mmG,
                                            np.swapaxes(rho4_nnG, 1, 2))
                            W_mnmn = np.swapaxes(W_mmnn, 1, 2) * Ns * so
                            H_ksmnKsmn[ik1, s1, :, :, iK2, s1] -= 0.5 * W_mnmn
            if iK1 % (myKsize // 5 + 1) == 0:
                dt = time() - t0
                tleft = dt * myKsize / (iK1 + 1) - dt
                print('  Finished %s pair orbitals in %s - Estimated %s left' %
                      ((iK1 + 1) * Nv * Nc * Ns * world.size,
                       timedelta(seconds=round(dt)),
                       timedelta(seconds=round(tleft))), file=self.fd)

        #if self.mode == 'BSE':
        #    del self.Q_qaGii, self.W_qGG, self.pd_q

        H_ksmnKsmn /= self.vol

        mySsize = myKsize * Nv * Nc * Ns
        if myKsize > 0:
            iS0 = myKrange[0] *  Nv * Nc * Ns

        #world.sum(rhoG0_Ksmn)
        #self.rhoG0_S = np.reshape(rhoG0_Ksmn, -1)
        self.df_S = np.reshape(df_Ksmn, -1)
        if not self.td:
            self.excludef_S = np.where(np.abs(self.df_S) < 0.001)[0]
        # multiply by 2 when spin-paired and no SOC
        self.df_S *= 2.0 / nK / Ns / so
        self.deps_s = np.reshape(deps_ksmn, -1)
        H_sS = np.reshape(H_ksmnKsmn, (mySsize, self.nS))
        for iS in range(mySsize):
            # Multiply by occupations and adiabatic coupling
            H_sS[iS] *= self.df_S[iS0 + iS] * ac
            # add bare transition energies
            H_sS[iS, iS0 + iS] += self.deps_s[iS]

        self.H_sS = H_sS

        if self.write_h:
            self.par_save('H_SS.ulm', 'H_SS', self.H_sS)
Beispiel #11
0
from gpaw import GPAW
from gpaw.spinorbit import get_spinorbit_eigenvalues
#plt.rc('text', usetex=True)

calc = GPAW('WS2_bands.gpw', txt=None)

x = np.loadtxt('WS2_kpath.dat')
X = np.loadtxt('WS2_highsym.dat')
e_kn = np.array(
    [calc.get_eigenvalues(kpt=k) for k in range(len(calc.get_ibz_k_points()))])
e_nk = e_kn.T
e_nk -= calc.get_fermi_level()
for e_k in e_nk:
    plt.plot(x, e_k, '--', c='0.5')

e_nk, s_kvn = get_spinorbit_eigenvalues(calc, return_spin=True)
e_nk -= calc.get_fermi_level()
s_nk = (s_kvn[:, 2].T + 1.0) / 2.0

plt.xticks(X, [
    r'$\mathrm{M}$', r'$\mathrm{K}$', r'$\Gamma$', r'$\mathrm{-K}$',
    r'$\mathrm{-M}$'
],
           size=20)
plt.yticks(size=20)
for i in range(len(X))[1:-1]:
    plt.plot(2 * [X[i]], [1.1 * np.min(e_nk), 1.1 * np.max(e_nk)],
             c='0.5',
             linewidth=0.5)

plt.scatter(np.tile(x, len(e_nk)),
Beispiel #12
0
import os 
import gpaw.wannier90 as w90
from gpaw import GPAW
from gpaw.spinorbit import get_spinorbit_eigenvalues

seed = 'Fe'

calc = GPAW('Fe.gpw', txt=None)

e_mk, v_knm = get_spinorbit_eigenvalues(calc, return_wfs=True)

w90.write_input(calc,
                bands=range(30),
                spinors=True,
                num_iter=200,
                dis_num_iter=500,
                dis_mix_ratio=1.0,
                dis_froz_max=15.0,
                seed=seed)

os.system('wannier90.x -pp ' + seed)

w90.write_projections(calc,
                      v_knm=v_knm,
                      seed=seed)
w90.write_eigenvalues(calc, e_km=e_mk.T, seed=seed)
w90.write_overlaps(calc, v_knm=v_knm, seed=seed)

os.system('wannier90.x ' + seed)
Beispiel #13
0
params = dict(mode='pw', kpts={'size': (3, 3, 1), 'gamma': True})

# Selfconsistent:
a.calc = GPAW(experimental={
    'magmoms': np.zeros((3, 3)),
    'soc': True
},
              convergence={'bands': 28},
              **params)
a.get_potential_energy()
E1 = a.calc.get_eigenvalues(kpt=2)

# Non-selfconsistent:
a.calc = GPAW(convergence={'bands': 14}, **params)
a.get_potential_energy()
E2 = get_spinorbit_eigenvalues(a.calc, bands=np.arange(14))[:, 2]


def test(E, hsplit, lsplit):
    print(E)
    h1, h2, l1, l2 = E[24:28]  # H**O-1, H**O, LUMO, LUMP+1
    print(h2 - h1)
    print(l2 - l1)
    assert abs(h2 - h1 - hsplit) < 0.01
    assert abs(l2 - l1 - lsplit) < 0.002


equal(E1[:28], E2, tolerance=1e-1)
test(E1, 0.15, 0.002)
test(E2, 0.15, 0.007)