Commit 2e230878 authored by Jens Jørgen Mortensen's avatar Jens Jørgen Mortensen

Merge branch 'marzari-vanderbilt' into 'master'

Implement Marzari-Vanderbilt occupations

See merge request !532
parents 92b87739 9af9e828
Pipeline #100497203 passed with stage
in 3 minutes and 23 seconds
......@@ -43,6 +43,7 @@ __all__ = ['GPAW',
'CG', 'Davidson', 'RMMDIIS', 'DirectLCAO',
'PoissonSolver',
'FermiDirac', 'MethfesselPaxton',
'MarzariVanderbilt',
'PW', 'LCAO', 'restart', 'FD']
......@@ -258,7 +259,8 @@ with broadcast_imports:
from gpaw.mixer import Mixer, MixerSum, MixerDif, MixerSum2
from gpaw.eigensolvers import Davidson, RMMDIIS, CG, DirectLCAO
from gpaw.poisson import PoissonSolver
from gpaw.occupations import FermiDirac, MethfesselPaxton
from gpaw.occupations import (FermiDirac, MethfesselPaxton,
MarzariVanderbilt)
from gpaw.wavefunctions.lcao import LCAO
from gpaw.wavefunctions.pw import PW
from gpaw.wavefunctions.fd import FD
......
......@@ -2,7 +2,8 @@ from ase.cli.run import Runner, str2dict, CLICommand as ASECLICommand
from gpaw import GPAW
from gpaw.mixer import Mixer, MixerSum
from gpaw.occupations import FermiDirac, MethfesselPaxton
from gpaw.occupations import (FermiDirac, MethfesselPaxton,
MarzariVanderbilt)
from gpaw.wavefunctions.pw import PW
......@@ -20,6 +21,7 @@ class GPAWRunner(Runner):
'PW': PW,
'FermiDirac': FermiDirac,
'MethfesselPaxton': MethfesselPaxton,
'MarzariVanderbilt': MarzariVanderbilt,
'Mixer': Mixer,
'MixerSum': MixerSum}
parameters = str2dict(self.args.parameters, parameter_namespace)
......
......@@ -18,6 +18,8 @@ def create_occupation_number_object(name, **kwargs):
return FermiDirac(**kwargs)
if name == 'methfessel-paxton':
return MethfesselPaxton(**kwargs)
if name == 'marzari-vanderbilt':
return MarzariVanderbilt(**kwargs)
if name == 'orbital-free':
return TFOccupations()
raise ValueError('Unknown occupation number object name: ' + name)
......@@ -625,6 +627,46 @@ class MethfesselPaxton(SmoothDistribution):
return E - self.e_entropy / (self.order + 2)
class MarzariVanderbilt(SmoothDistribution):
def __init__(self, width, fixmagmom=False):
SmoothDistribution.__init__(self, width, fixmagmom)
def todict(self):
dct = SmoothDistribution.todict(self)
dct['name'] = 'marzari-vanderbilt'
return dct
def __str__(self):
s = ' Marzari-Vanderbilt: width={0:.4f} eV\n'.format(
self.width * Hartree)
return SmoothDistribution.__str__(self) + s
def distribution(self, kpt, fermilevel):
x = (kpt.eps_n - fermilevel) / self.width
x = x.clip(-100, 100)
expterm = np.exp(-(x + (1 / np.sqrt(2)))**2)
z = expterm / np.sqrt(2 * np.pi) + 0.5 * (1 - erf(1. / np.sqrt(2) + x))
kpt.f_n[:] = kpt.weight * z
n = kpt.f_n.sum()
dnde = expterm * (2 + np.sqrt(2) * x) / np.sqrt(np.pi)
dnde = dnde.sum() * kpt.weight / self.width
s = expterm * (1 + np.sqrt(2) * x) / (2 * np.sqrt(np.pi))
e_entropy = -kpt.weight * s.sum() * self.width
sign = 1 - kpt.s * 2
return np.array([n, dnde, n * sign, e_entropy])
def extrapolate_energy_to_zero_width(self, E):
# According to Nicola Marzari, one should not extrapolate M-V energies
# https://lists.quantum-espresso.org/pipermail/users/2005-October/003170.html
return E
class FixedOccupations(ZeroKelvin):
def __init__(self, occupation):
self.occupation = np.array(occupation)
......
from __future__ import print_function
import numpy as np
from ase.units import Hartree
from gpaw.occupations import FermiDirac, MethfesselPaxton, occupation_numbers
from gpaw.occupations import (FermiDirac, MethfesselPaxton,
MarzariVanderbilt, occupation_numbers)
class KPoint:
......@@ -39,6 +40,7 @@ for w in [0.1, 0.5]:
test(FermiDirac(w))
for n in range(4):
test(MethfesselPaxton(w, n))
test(MarzariVanderbilt(w))
occ = {'name': 'fermi-dirac', 'width': 0.1}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment