Skip to content

Commit

Permalink
Implement Woods-Saxon confinement
Browse files Browse the repository at this point in the history
  • Loading branch information
vanderhe authored and aradi committed Nov 22, 2024
1 parent d3a1484 commit df9b95c
Show file tree
Hide file tree
Showing 10 changed files with 864 additions and 128 deletions.
75 changes: 57 additions & 18 deletions sktools/src/sktools/calculators/slateratom.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
import sktools.hsd.converter as conv
import sktools.common as sc
from sktools.taggedfile import TaggedFile
import sktools.compressions
import sktools.compressions as skcomp
import sktools.radial_grid as oc
import sktools.xcfunctionals as xc


LOGGER = logging.getLogger('slateratom')
Expand Down Expand Up @@ -134,7 +135,7 @@ class SlateratomInput:
functional : str
DFT functional type ('lda', 'pbe', 'blyp', 'lcpbe', 'lcbnl')
compressions : list
List of PowerCompression objects. Either empty (no compression applied)
List of Compression objects. Either empty (no compression applied)
or has a compression object for every angular momentum of the atom.
settings : SlaterAtom
Further detailed settings of the program.
Expand Down Expand Up @@ -193,16 +194,26 @@ def __init__(self, settings, atomconfig, functional, compressions):
if compressions is None:
compressions = []
for comp in compressions:
if not isinstance(comp, sktools.compressions.PowerCompression):
msg = "Invalid compressiont type {} for slateratom".format(
if not isinstance(comp, (skcomp.PowerCompression,
skcomp.WoodsSaxonCompression)):
msg = "Invalid compression type {} for slateratom".format(
comp.__class__.__name__)
raise sc.SkgenException(msg)
maxang = atomconfig.maxang
ncompr = len(compressions)
if ncompr and ncompr != maxang + 1:
if ncompr > 0 and ncompr != maxang + 1:
msg = "Invalid number of compressions" \
"(expected {:d}, got {:d})".format(maxang + 1, ncompr)
raise sc.SkgenException(msg)

# block different compression types of different shells for now
if ncompr > 0:
compids = [comp.compid for comp in compressions]
if not len(set(compids)) == 1:
msg = "At the moment, shells may only be compressed by the " \
+ "same type of potential."
raise sc.SkgenException(msg)

self._compressions = compressions
myrelativistics = sc.RELATIVISTICS_NONE, sc.RELATIVISTICS_ZORA
if atomconfig.relativistics not in myrelativistics:
Expand All @@ -213,7 +224,7 @@ def __init__(self, settings, atomconfig, functional, compressions):
def isXCFunctionalSupported(self, functional):
'''Checks if the given xc-functional is supported by the calculator,
in particular: checks if AVAILABLE_FUNCTIONALS intersect with
sktools.xcfunctionals.XCFUNCTIONALS
xc.XCFUNCTIONALS
Args:
functional: xc-functional, defined in xcfunctionals.py
Expand All @@ -224,8 +235,8 @@ def isXCFunctionalSupported(self, functional):

tmp = []
for xx in SUPPORTED_FUNCTIONALS:
if xx in sktools.xcfunctionals.XCFUNCTIONALS:
tmp.append(sktools.xcfunctionals.XCFUNCTIONALS[xx])
if xx in xc.XCFUNCTIONALS:
tmp.append(xc.XCFUNCTIONALS[xx])

return bool(functional.__class__ in tmp)

Expand Down Expand Up @@ -297,14 +308,42 @@ def write(self, workdir):

# Compressions
if len(self._compressions) == 0:
out += ["{:g} {:d} \t\t{:s} Compr. radius and power ({:s})".format(
1e30, 0, self._COMMENT, sc.ANGMOM_TO_SHELL[ll])
# no compression for all shells
out += ["{:d} \t\t\t{:s} Compression ID".format(
skcomp.SUPPORTED_COMPRESSIONS['nocompression'],
self._COMMENT) + " ({:s})".format(sc.ANGMOM_TO_SHELL[ll])
for ll in range(maxang + 1)]
else:
out += ["{:g} {:g} \t\t{:s} Compr. radius and power ({:s})".format(
compr.radius, compr.power, self._COMMENT,
sc.ANGMOM_TO_SHELL[ll])
for ll, compr in enumerate(self._compressions)]
# define the type of compression for each shell
for ll, compr in enumerate(self._compressions):
if compr.compid == \
skcomp.SUPPORTED_COMPRESSIONS['powercompression']:
out += ["{:d} \t\t{:s} Compression ID".format(
skcomp.SUPPORTED_COMPRESSIONS['powercompression'],
self._COMMENT) \
+ " ({:s})".format(sc.ANGMOM_TO_SHELL[ll])]
elif compr.compid == \
skcomp.SUPPORTED_COMPRESSIONS['woodssaxoncompression']:
out += ["{:d} \t\t{:s} Compression ID".format(
skcomp.SUPPORTED_COMPRESSIONS['woodssaxoncompression'],
self._COMMENT) \
+ " ({:s})".format(sc.ANGMOM_TO_SHELL[ll])]
else:
msg = 'Invalid compression type.'
raise sc.SkgenException(msg)
# provide the compression parametrization for each shell
for ll, compr in enumerate(self._compressions):
if compr.compid == \
skcomp.SUPPORTED_COMPRESSIONS['powercompression']:
out += ["{:g} {:g} \t\t{:s} Compr. radius and power ({:s})"
.format(compr.radius, compr.power, self._COMMENT,
sc.ANGMOM_TO_SHELL[ll])]
elif compr.compid == \
skcomp.SUPPORTED_COMPRESSIONS['woodssaxoncompression']:
out += ["{:g} {:g} {:g} \t\t{:s}".format(
compr.onset, compr.cutoff, compr.vmax, self._COMMENT) \
+ " Compr. onset, cutoff and vmax ({:s})"
.format(sc.ANGMOM_TO_SHELL[ll])]

out += ["{:d} \t\t\t{:s} nr. of occupied shells ({:s})".format(
len(occ), self._COMMENT, sc.ANGMOM_TO_SHELL[ll])
Expand All @@ -313,9 +352,9 @@ def write(self, workdir):
# STO powers and exponents
exponents = self._settings.exponents
maxpowers = self._settings.maxpowers
out += ["{:d} {:d} \t\t\t{:s} nr. of exponents, max. power ({:s})".format(
len(exponents[ll]), maxpowers[ll], self._COMMENT,
sc.ANGMOM_TO_SHELL[ll])
out += ["{:d} {:d} \t\t\t{:s} nr. of exponents, max. power ({:s})"
.format(len(exponents[ll]), maxpowers[ll], self._COMMENT,
sc.ANGMOM_TO_SHELL[ll])
for ll in range(maxang + 1)]
out.append("{:s} \t\t{:s} automatic exponent generation".format(
self._LOGICALSTRS[False], self._COMMENT))
Expand All @@ -326,7 +365,7 @@ def write(self, workdir):

out.append("{:s} \t\t{:s} write eigenvectors".format(
self._LOGICALSTRS[False], self._COMMENT))
out.append("{} {:g} \t\t{:s} broyden mixer, mixing factor".format(
out.append("{} {:g} \t\t\t{:s} broyden mixer, mixing factor".format(
2, 0.1, self._COMMENT))

# Occupations
Expand Down
2 changes: 2 additions & 0 deletions sktools/src/sktools/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ def is_shelf_file_matching(shelf_file, mydict):
db = shelve.open(shelf_file, 'r')
except dbm.error:
return False
if not type(db) is type(mydict):
return False
match = True
for key in mydict:
match = key in db and db[key] == mydict[key]
Expand Down
73 changes: 73 additions & 0 deletions sktools/src/sktools/compressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def fromhsd(cls, root, query):
node=child)

myself = cls()
myself.compid = SUPPORTED_COMPRESSIONS[
myself.__class__.__name__.lower()]
myself.power = power
myself.radius = radius

Expand All @@ -62,9 +64,80 @@ def __eq__(self, other):
return power_ok and radius_ok


class WoodsSaxonCompression(sc.ClassDict):
'''Compression by the Woods Saxon potential.
Attributes
----------
onset : float
Onset radius of the compression
cutoff : float
Cutoff radius of the compression
vmax : float
Potential well depth/height
'''

@classmethod
def fromhsd(cls, root, query):
'''Creates instance from a HSD-node and with given query object.'''

onset, child = query.getvalue(root, 'onset', conv.float0,
returnchild=True)
if onset < 0.0:
msg = 'Invalid onset radius {:f}'.format(onset)
raise hsd.HSDInvalidTagValueException(msg=msg, node=child)

cutoff, child = query.getvalue(root, 'cutoff', conv.float0,
returnchild=True)
if cutoff <= onset:
msg = 'Invalid cutoff radius {:f}'.format(cutoff)
raise hsd.HSDInvalidTagValueException(msg=msg, node=child)

vmax, child = query.getvalue(
root, 'vmax', conv.float0, defvalue=100.0, returnchild=True)
if vmax <= 0.0:
msg = 'Invalid potential well height {:f}'.format(vmax)
raise hsd.HSDInvalidTagValueException(msg=msg, node=child)

myself = cls()
myself.compid = SUPPORTED_COMPRESSIONS[
myself.__class__.__name__.lower()]
myself.onset = onset
myself.cutoff = cutoff
myself.vmax = vmax

return myself


def tohsd(self, root, query, parentname=None):
''''''

if parentname is None:
mynode = root
else:
mynode = query.setchild(root, 'WoodsSaxonCompression')

query.setchildvalue(mynode, 'onset', conv.float0, self.onset)
query.setchildvalue(mynode, 'cutoff', conv.float0, self.cutoff)
query.setchildvalue(mynode, 'vmax', conv.float0, self.vmax)


def __eq__(self, other):
onset_ok = abs(self.onset - other.onset) < 1e-8
cutoff_ok = abs(self.cutoff - other.cutoff) < 1e-8
vmax_ok = abs(self.vmax - other.vmax) < 1e-8
return onset_ok and cutoff_ok and vmax_ok


# Registered compressions with corresponding hsd name as key
COMPRESSIONS = {
'powercompression': PowerCompression,
'woodssaxoncompression': WoodsSaxonCompression,
}
SUPPORTED_COMPRESSIONS = {
'nocompression': 0,
'powercompression': 1,
'woodssaxoncompression': 2,
}


Expand Down
1 change: 1 addition & 0 deletions slateratom/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ set(sources-f90
set(sources-fpp
blasroutines.F90
broydenmixer.F90
confinement.F90
lapackroutines.F90
simplemixer.F90)

Expand Down
Loading

0 comments on commit df9b95c

Please sign in to comment.