[docs]
def calc2eigs(calc, soc=True,
return_spin=False,
theta=0, phi=0, symmetry_tolerance=1e-7,
width=None):
from gpaw.spinorbit import soc_eigenstates
from gpaw.occupations import create_occ_calc
from ase.parallel import broadcast
import numpy as np
from .symmetry import restrict_spin_projection_2d
from .calculator_utils import get_eigenvalues
from .symmetry import _atoms2symmetry_gpaw
dct = None
bands = range(calc.get_number_of_bands())
eps_nosoc_skn = get_eigenvalues(calc)[..., bands]
efermi_nosoc = calc.get_fermi_level()
dct = {'eps_nosoc_skn': eps_nosoc_skn,
'efermi_nosoc': efermi_nosoc}
if soc:
occcalc = create_occ_calc({'width': 0.0})
soc = soc_eigenstates(calc,
n1=bands[0],
n2=bands[-1] + 1,
theta=theta,
phi=phi,
occcalc=occcalc)
eps_km = soc.eigenvalues()
s_kvm = soc.spin_projections().transpose((0, 2, 1))
efermi = soc.fermi_level
symmetry = _atoms2symmetry_gpaw(calc.atoms,
tolerance=symmetry_tolerance)
# For magnetic systems we know some more about the spin
# projections
if calc.get_number_of_spins() == 1:
# Inversion + time reversal symmetry forces degenerates spins
if symmetry.has_inversion:
s_kvm[:] = 0.0
else:
# For 2D we try to find materials where
# spins are restricted to inplane spins
if np.sum(calc.atoms.pbc).astype(int) == 2:
bzk_kc = calc.get_bz_k_points()
for k, kpt in enumerate(bzk_kc):
s_vm = restrict_spin_projection_2d(kpt,
symmetry.op_scc,
s_kvm[k])
s_kvm[k] = s_vm
dct.update({'eps_km': eps_km,
'efermi': efermi,
's_kvm': s_kvm})
dct = broadcast(dct, root=0, comm=calc.world)
if soc is None:
raise NotImplementedError('soc=None is not implemented')
if soc:
out = (dct['eps_km'], dct['efermi'], dct['s_kvm'])
if not return_spin:
out = out[:2]
return out
else:
if not return_spin:
return dct['eps_nosoc_skn'], dct['efermi_nosoc']
return dct['eps_nosoc_skn'], dct['efermi_nosoc'], dct['s_kvm']
[docs]
def gpw2eigs(gpw, soc=True, return_spin=False,
theta=0, phi=0, symmetry_tolerance=1e-7):
"""Give the eigenvalues w or w/o spinorbit coupling and the corresponding fermi energy.
Parameters
----------
gpw (str): gpw filename
soc : None, bool
use spinorbit coupling if None it returns both w and w/o
bands : slice, list of ints or None
None gives parameters.convergence.bands if possible else all bands
Returns
-------
dict or e_skn, efermi
containg eigenvalues and fermi levels w and w/o spinorbit coupling
"""
from gpaw import GPAW
from gpaw import mpi
calc = GPAW(gpw, txt=None, communicator=mpi.serial_comm)
return calc2eigs(calc, soc=soc, return_spin=return_spin,
theta=theta, phi=phi,
symmetry_tolerance=symmetry_tolerance)