from typing import Any
import numpy as np
from ase.units import Ha
from gpaw.external import NoExternalPotential
from gpaw.old.density import Density
from gpaw.old.pw.hamiltonian import ReciprocalSpaceHamiltonian
from gpaw.typing import Array1D, Array2D, ArrayLike1D
[docs]
class BField(NoExternalPotential):
def __init__(self, field: ArrayLike1D):
"""Constant magnetic field.
field:
B-field vector in units of eV/bohr-magnoton.
"""
self.name = 'BField'
self.field_v = np.array(field) / Ha
assert self.field_v.shape == (3,)
def get_potential(self, gd):
raise NotImplementedError('BField can only be used in PW-mode!')
def update_potential_pw(self,
ham: ReciprocalSpaceHamiltonian,
dens: Density) -> float:
magmom_v, _ = dens.estimate_magnetic_moments()
eext = -self.field_v.dot(magmom_v)
if dens.collinear:
ham.vt_sG[:] = ham.pd2.ifft(ham.vt_Q)
ham.vt_sG[0] -= self.field_v[2]
ham.vt_sG[1] += self.field_v[2]
else:
ham.vt_xG[0] = ham.pd2.ifft(ham.vt_Q)
ham.vt_xG[1:] = -self.field_v.reshape((3, 1, 1, 1))
return eext
def paw_correction(self, Delta_p: Array1D, dH_sp: Array2D) -> None:
if len(dH_sp) == 2:
c = (4 * np.pi)**0.5 * self.field_v[2]
dH_sp[0] -= c * Delta_p
dH_sp[1] += c * Delta_p
else:
c_vp = (4 * np.pi)**0.5 * self.field_v[:, np.newaxis]
dH_sp[1:] -= c_vp * Delta_p
def todict(self) -> dict[str, Any]:
return {'name': self.name,
'field': tuple(self.field_v * Ha)}