3
0
mirror of https://github.com/triqs/dft_tools synced 2024-08-29 15:23:41 +02:00

Merge ../bare_plovasp into dev

Conflicts:
	python/converters/vasp/python/main.py
	python/converters/vasp/python/plotools.py
Merged old version of output with the new one
This commit is contained in:
Michel Ferrero 2015-10-11 14:00:35 +02:00
commit dd33621e7c
78 changed files with 237 additions and 71 deletions

View File

@ -72,7 +72,7 @@ Consistency with parameters
Selecting projector subsets Selecting projector subsets
--------------------------- ===========================
The first step of PLO processing is to select subsets of projectors The first step of PLO processing is to select subsets of projectors
corresponding to PLO groups. Each group contains a set of shells. corresponding to PLO groups. Each group contains a set of shells.
@ -117,7 +117,7 @@ The class is using a helper function `select_bands()` for selecting a subset of
.. _ortho: .. _ortho:
Orthogonalization Orthogonalization
================= -----------------
At the second stage the selected projectors are orthogonalized (orthonormalized). At the second stage the selected projectors are orthogonalized (orthonormalized).
Orthogonalization can be performed in different ways if projection is made Orthogonalization can be performed in different ways if projection is made
@ -138,3 +138,54 @@ The way the normalization of a PLO group is done is controlled by two group para
(False by default) (False by default)
Storing generated projectors
****************************
After the PLOs are generated they are stored to text files which can be subsequently
converted to TRIQS h5-files (using the converter). The general format of the file
is a JSON-header containing all necessary parameters followed by a set of arrays.
There is always one (control) file containing general information (`k`-kpoints, lattice vectors etc.)
and `at least` one file containing correlated groups (one file for each group).
Control file format
===================
Filename '<namebase>.ctrl'. Contains the data shared between all shells.
The JSON-header consists of the following elements:
* *nk*: number of `k`-points
* *ns*: number of spin channels
* *nc_flag*: collinear/noncollinear case (False/True)
* *ng*: number of projector groups
* Symmetry information (list of symmetry operations)
* *efermi*: Fermi level (optional)
* Lattice information
Projector-group file format
===========================
Projector-group files have names '<namebase>.plog<Ng>'.
They essentially contain serialized objects of class 'ProjectorGroup'.
The JSON-header has, thus, the following elements:
* *shells*: list of shells
* each shell is a dictionary:
- *lshell*: orbital number `l`
- *nion*: number of ions
- *ndim*: number of orbitals/ion
- *nbmax*: maxmimum number of bands (needed for array allocations)
* *emin*, *emax*: energy window

View File

@ -68,6 +68,9 @@ class ConfigParameters:
'normalize' : ('normalize', self.parse_string_logical, True), 'normalize' : ('normalize', self.parse_string_logical, True),
'normion' : ('normion', self.parse_string_logical, False)} 'normion' : ('normion', self.parse_string_logical, False)}
self.gen_optional = {
'basename' : ('basename', str, 'vasp'),
'efermi' : ('efermi', float)}
# #
# Special parsers # Special parsers
@ -177,7 +180,7 @@ class ConfigParameters:
key = param_set[par][0] key = param_set[par][0]
try: try:
par_str = self.cp.get(section, par) par_str = self.cp.get(section, par)
except ConfigParser.NoOptionError: except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
if exception: if exception:
message = "Required parameter '%s' not found in section [%s]"%(par, section) message = "Required parameter '%s' not found in section [%s]"%(par, section)
raise Exception(message) raise Exception(message)
@ -438,8 +441,18 @@ class ConfigParameters:
""" """
Parses [General] section. Parses [General] section.
""" """
# TODO: write the parser self.general = {}
pass sections = self.cp.sections()
gen_section = filter(lambda s: s.lower() == 'general', sections)
# If no [General] section is found parse a dummy section name to the parser
# to reset parameters to their default values
if len(gen_section) > 1:
raise Exception("More than one section [General] is found")
if len(gen_section) == 0:
gen_section = 'general'
gen_section = gen_section[0]
parsed = self.parse_parameter_set(gen_section, self.gen_optional, exception=False)
self.general.update(parsed)
################################################################################ ################################################################################
# #

View File

@ -3,7 +3,7 @@ import sys
import vaspio import vaspio
from inpconf import ConfigParameters from inpconf import ConfigParameters
from elstruct import ElectronicStructure from elstruct import ElectronicStructure
from plotools import generate_plo, plo_output, kpoints_output from plotools import generate_ortho_plos, output_as_text
if __name__ == '__main__': if __name__ == '__main__':
narg = len(sys.argv) narg = len(sys.argv)
@ -23,11 +23,5 @@ if __name__ == '__main__':
pars.parse_input() pars.parse_input()
vasp_data = vaspio.VaspData(vasp_dir) vasp_data = vaspio.VaspData(vasp_dir)
el_struct = ElectronicStructure(vasp_data) el_struct = ElectronicStructure(vasp_data)
pshells, pgroups = generate_plo(pars, el_struct) pshells, pgroups = generate_ortho_plos(pars, el_struct)
for gr in pgroups: output_as_text(pars, el_struct, pshells, pgroups)
gr.orthogonalize()
# TODO: add BASENAME to config parameters
basename = 'vasp'
kpoints_output(basename, el_struct)
plo_output(basename, pshells, pgroups, el_struct)

View File

@ -2,6 +2,9 @@
import itertools as it import itertools as it
import numpy as np import numpy as np
# 'simplejson' is supposed to be faster than 'json' in stdlib.
import simplejson as json
class Projector: class Projector:
""" """
Class describing a local-orbital projector. Class describing a local-orbital projector.
@ -277,6 +280,12 @@ class ProjectorShell:
self.lm2 = (self.lorb+1)**2 self.lm2 = (self.lorb+1)**2
self.ndim = self.lm2 - self.lm1 self.ndim = self.lm2 - self.lm1
if self.tmatrix is None:
self.ndim = self.lm2 - self.lm1 + 1
else:
# TODO: generalize this to a tmatrix for every ion
self.ndim = self.tmatrix.shape[0]
# Pre-select a subset of projectors (this should be an array view => no memory is wasted) # Pre-select a subset of projectors (this should be an array view => no memory is wasted)
# !!! This sucks but I have to change the order of 'ib' and 'ilm' indices here # !!! This sucks but I have to change the order of 'ib' and 'ilm' indices here
# This should perhaps be done right after the projector array is read from PLOCAR # This should perhaps be done right after the projector array is read from PLOCAR
@ -424,12 +433,49 @@ def kpoints_output(basename, el_struct):
################################################################################
#
# ctrl_output
#
################################################################################
def ctrl_output(conf_pars, el_struct, ng):
"""
Outputs a ctrl-file.
"""
ctrl_fname = conf_pars.general['basename'] + '.ctrl'
head_dict = {}
# TODO: Add output of tetrahedra
# Construct the header dictionary
head_dict['ngroups'] = ng
head_dict['nk'] = el_struct.kmesh['nktot']
head_dict['ns'] = el_struct.nspin
head_dict['nc_flag'] = 1 if el_struct.nc_flag else 0
# head_dict['efermi'] = conf_pars.general['efermi'] # We probably don't need Efermi
header = json.dumps(head_dict, indent=4, separators=(',', ': '))
print " Storing ctrl-file..."
with open(ctrl_fname, 'wt') as f:
f.write(header + "\n")
f.write("#END OF HEADER\n")
f.write("# k-points and weights\n")
labels = ['kx', 'ky', 'kz', 'kweight']
out = "".join(map(lambda s: s.center(15), labels))
f.write("#" + out + "\n")
for ik, kp in enumerate(el_struct.kmesh['kpoints']):
tmp1 = "".join(map("{0:15.10f}".format, kp))
out = tmp1 + "{0:16.10f}".format(el_struct.kmesh['kweights'][ik])
f.write(out + "\n")
################################################################################ ################################################################################
# #
# plo_output # plo_output
# #
################################################################################ ################################################################################
def plo_output(basename, pshells, pgroups, el_struct): def plo_output(conf_pars, el_struct, pshells, pgroups):
""" """
Outputs PLO groups into text files. Outputs PLO groups into text files.
@ -455,55 +501,91 @@ def plo_output(basename, pshells, pgroups, el_struct):
# Projected shells # Projected shells
Nshells Nshells
# Shells: <shell indices> # Shells: <shell indices>
# Shell <1>
Shell 1 Shell 1
ndim ndim
# complex arrays: plo(ns, nion, ndim, nb) # complex arrays: plo(ns, nion, ndim, nb)
... ...
# Shells: <shell indices> # Shells: <shell indices>
# Shell <2>
Shell 2 Shell 2
... ...
""" """
for ig, gr in enumerate(pgroups): for ig, pgroup in enumerate(pgroups):
fname = basename + '.plog%i'%(ig+1) plo_fname = conf_pars.general['basename'] + '.pg%i'%(ig + 1)
with open(fname, 'wt') as f: print " Storing PLO-group file '%s'..."%(plo_fname)
f.write("# Energy window: emin, emax\n") head_dict = {}
f.write("%i %i\n"%(gr.emin, gr.emax))
f.write("# Number of electrons within the window\n")
nelect = gr.nelect_window(el_struct)
f.write("%s\n"%(round(nelect, 5)))
f.write("# Eigenvalues: is, ik, ib1, ib2 then list of values\n")
nk, ns_band, _ = gr.ib_win.shape head_dict['ewindow'] = (pgroup.emin, pgroup.emax)
head_dict['nb_max'] = pgroup.nb_max
head_shells = []
for ish in pgroup.ishells:
shell = pgroup.shells[ish]
sh_dict = {}
sh_dict['shell_index'] = ish
sh_dict['lorb'] = shell.lorb
sh_dict['ndim'] = shell.ndim
# Convert ion indices from the internal representation (starting from 0)
# to conventional VASP representation (starting from 1)
ion_output = [io + 1 for io in shell.ion_list]
sh_dict['ion_list'] = ion_output
# TODO: add the output of transformation matrices
head_shells.append(sh_dict)
head_dict['shells'] = head_shells
header = json.dumps(head_dict, indent=4, separators=(',', ': '))
with open(plo_fname, 'wt') as f:
f.write(header + "\n")
f.write("#END OF HEADER\n")
# Eigenvalues within the window
f.write("# Eigenvalues within the energy window: %s, %s\n"%(pgroup.emin, pgroup.emax))
nk, nband, ns_band = el_struct.eigvals.shape
for isp in xrange(ns_band): for isp in xrange(ns_band):
f.write("# is = %i\n"%(isp + 1))
for ik in xrange(nk): for ik in xrange(nk):
ib1 = gr.ib_win[ik, isp, 0] ib1, ib2 = pgroup.ib_win[ik, isp, 0], pgroup.ib_win[ik, isp, 1]
ib2 = gr.ib_win[ik, isp, 1] f.write(" %i %i\n"%(ib1, ib2))
f.write("%i %i %i %i\n"%(isp+1, ik+1, ib1+1, ib2+1)) for ib in xrange(ib1, ib2 + 1):
for ib in xrange(ib1, ib2+1): f.write("%15.7f\n"%(el_struct.eigvals[ik, ib, isp]))
f.write("%s\n"%(el_struct.eigvals[ik, ib, isp]))
f.write("\nProjected shells: nshells\n") # Projected shells
f.write("%i\n"%(len(gr.ishells))) f.write("# Projected shells\n")
f.write("Shells: <shell indices>\n") f.write("# Shells: %s\n"%(pgroup.ishells))
f.write(' '.join(map(lambda ish: "{0:d}".format(pshells[ish].user_index), gr.ishells)) + '\n') for ish in pgroup.ishells:
for ish in gr.ishells: shell = pgroup.shells[ish]
shell = pshells[ish] f.write("# Shell %i\n"%(ish))
f.write("Orbital dimension: ndim\n")
f.write("%i\n"%(shell.ndim))
nion, ns, nk, ndim, _ = shell.proj_win.shape nion, ns, nk, nlm, nb = shell.proj_win.shape
f.write("# Blocks [isp, ion, ndim, nb], 'nb' fastest index\n") for isp in xrange(ns):
for ik in xrange(nk): f.write("# is = %i\n"%(isp + 1))
for isp in xrange(ns): for ik in xrange(nk):
# TODO: fix this for non-collinear case (ns != ns_band) f.write("# ik = %i\n"%(ik + 1))
ib1 = gr.ib_win[ik, isp, 0] - gr.nb_min
ib2 = gr.ib_win[ik, isp, 1] - gr.nb_min
for ion in xrange(nion): for ion in xrange(nion):
f.write("# ik = %i, is = %i, ion = %i\n"%(ik+1, isp+1, ion+1)) for ilm in xrange(nlm):
for iorb in xrange(ndim): ib1, ib2 = pgroup.ib_win[ik, isp, 0], pgroup.ib_win[ik, isp, 1]
for ib in xrange(ib1, ib2+1): ib1_win = ib1 - shell.nb_min
plo = shell.proj_win[ion, isp, ik, iorb, ib] ib2_win = ib2 - shell.nb_min
f.write("%20.10f %20.10f\n"%(plo.real, plo.imag)) for ib in xrange(ib1_win, ib2_win + 1):
p = shell.proj_win[ion, isp, ik, ilm, ib]
f.write("{0:16.10f}{1:16.10f}\n".format(p.real, p.imag))
f.write("\n") f.write("\n")
################################################################################
#
# output_as_text
#
################################################################################
def output_as_text(pars, el_struct, pshells, pgroups):
"""
Output all information necessary for the converter as text files.
"""
ctrl_output(pars, el_struct, len(pgroups))
plo_output(pars, el_struct, pshells, pgroups)

View File

@ -0,0 +1 @@
*.pyc

View File

@ -1,4 +1,6 @@
[General] [General]
BASENAME = test_base
EFERMI = 0.1
[Group 1] [Group 1]
SHELLS = 1 2 SHELLS = 1 2

View File

@ -0,0 +1,32 @@
r"""
Tests of 'parse_general()' defined in ConfigParameters class
"""
import arraytest
import numpy as np
from inpconf import ConfigParameters
################################################################################
#
# TestParseGeneral
#
################################################################################
class TestParseGeneral(arraytest.ArrayTestCase):
"""
Function:
def parse_general(self)
Scenarios:
- **if** a correct [General] section is defined **return** a dictionary
"""
# Scenario 1
def test_example(self):
conf_pars = ConfigParameters('example.cfg')
conf_pars.parse_general()
res = conf_pars.general
expected = {'basename': 'test_base', 'efermi': 0.1}
self.assertDictEqual(res, expected)

View File

@ -1,20 +0,0 @@
[General]
EFERMI = -0.6
[Group 1]
SHELLS = 1 2
EMIN = -7.6
EMAX = 2.7
[Shell 1]
# Ni shell
IONS = 5 6 7 8
LSHELL = 2
RTRANSFORM =
0.0 0.0 0.0 0.0 1.0
0.0 0.0 1.0 0.0 0.0
[Shell 2]
# Oxygen shell
IONS = 9..20
LSHELL = 1

View File

@ -0,0 +1 @@
PYTHONPATH=$HOME/Codes/vasp/vasp5.3/plo_vasp/plovasp/python:$HOME/Codes/vasp/vasp5.3/plo_vasp/plovasp/c:$PYTHONPATH python test_all.py

View File

@ -0,0 +1,10 @@
r"""
Searches and runs all available test suites.
"""
import unittest
if __name__ == '__main__':
suite = unittest.TestLoader().discover('./')
unittest.TextTestRunner(verbosity=2, buffer=True).run(suite)
# unittest.TextTestRunner(verbosity=2, buffer=False).run(suite)