Skip to content

Commit f82fad5

Browse files
committed
[vasp] add feat to read dft_bands_input for VASP calculations
see TRIQS/dftkit#3 for more information. - add test for spaghettis for vasp - add documentation for new vasp bands converter feature
1 parent 3c4e312 commit f82fad5

5 files changed

Lines changed: 140 additions & 13 deletions

File tree

doc/guide/analysis.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ This spectral function is calculated by typing::
125125

126126
The figure above shows the DFT SrVO\ :sub:`3`\ spaghetti plot (generated using V t\ :sub:`2g`\ Wannier projectors generated within a correlated energy window of [-13.6, 13.6] eV). As before, the broadening input has been set to the temperature (i.e., 1/Beta). The left panel shows the total A(k, :math:`\omega`) whereas the right gives the Wannier A(k, :math:`\omega`), both generated from this SK.spaghettis().
127127

128+
For VASP inputs containing band projectors, e.g. data converted from a VASP ``KPOINTS_OPT``/``LOCPROJ_OPT`` calculation, orbital-projected spaghetti plots are available with ``proj_type='vasp'``.
129+
128130

129131
Energy contours of the k-resolved Spectral function
130132
---------------------------------------------------
@@ -161,4 +163,3 @@ which calculates the partial charges using the self energy, double counting, and
161163
defined in the list `SK.shells`. This list is constructed by the Wien2k converter routines and stored automatically
162164
in the hdf5 archive. For the structure of `dm`, see also :meth:`partial charges <dft.sumk_dft_tools.SumkDFTTools.partial_charges>`.
163165

164-

doc/guide/conv_vasp.rst

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Here, we will present a guide how the interface `can` be used to create input fo
2727

2828
For VASP version older than 6.5.0 there are a few limitation of the interface as it was not officially supported and only text file based. See `Remarks for VASP older than 6.5.0`_ for details.
2929

30-
Generation of projectors for k-point lines (option `Lines` in KPOINTS) needed for Bloch spectral function calculations is not possible at the moment.
30+
For VASP versions that write ``LOCPROJ_OPT`` data for ``KPOINTS_OPT``, projectors for a separate k-point path or grid can be converted for Bloch spectral function calculations. This workflow uses the HDF5 output in ``vaspout.h5`` and requires VASP to be compiled with HDF5 support enabled.
3131

3232
VASP: generating raw projectors
3333
===============================
@@ -188,6 +188,36 @@ in :class:`SumkDFT <dft.sumk_dft.SumkDFT>`, e.g.::
188188

189189
However, this should only be done after a careful study of the density matrix and the projected DOS in the localized basis. For the complete process for SrVO3 see the tutorial for the VASP interface `here <../tutorials/svo_vasp/svo_notebook.html>`_.
190190

191+
When VASP band projectors are available in the HDF5 archive, for example from a ``KPOINTS_OPT``/``LOCPROJ_OPT`` bands conversion, :meth:`SumkDFTTools.spaghettis <dft.sumk_dft_tools.SumkDFTTools.spaghettis>` supports VASP orbital-projected spectral functions with ``proj_type='vasp'``.
192+
193+
Data for post-processing - Spectral functions
194+
=============================================
195+
196+
For momentum-resolved spectral functions along a separate VASP k-point path or grid, use ``KPOINTS_OPT`` together with ``LOCPROJ`` in the VASP calculation. Recent VASP versions write the corresponding optional-k-point projector output to:
197+
198+
* ``LOCPROJ_OPT`` and ``PROJCAR_OPT`` for text output.
199+
* ``vaspout.h5:/results/locproj_opt`` for HDF5 output.
200+
201+
The HDF5 route is used by the converter. The same calculation also provides the optional-k-point eigenvalues and weights under ``vaspout.h5:/results/electron_eigenvalues_kpoints_opt``. The relevant datasets are:
202+
203+
* ``results/electron_eigenvalues_kpoints_opt/eigenvalues``
204+
* ``results/electron_eigenvalues_kpoints_opt/fermiweights``
205+
* ``results/electron_eigenvalues_kpoints_opt/kpoint_coords``
206+
* ``results/electron_eigenvalues_kpoints_opt/kpoints_symmetry_weight``
207+
* ``results/locproj_opt/data``
208+
* ``results/locproj_opt/format``
209+
* ``results/locproj_opt/parameters/*``
210+
211+
The normal converter workflow will automatically detect the optional-k-point bands data into ``dft_bands_input``::
212+
213+
Converter.convert_dft_input()
214+
215+
and will internally call the bands converter with the same config::
216+
217+
Converter.convert_bands_input()
218+
219+
After this conversion, :meth:`SumkDFTTools.spaghettis <dft.sumk_dft_tools.SumkDFTTools.spaghettis>` can calculate total and VASP orbital-projected spectral functions. Use ``proj_type='vasp'`` for orbital-projected VASP spaghetti plots.
220+
191221
PLOVASP detailed guide
192222
======================
193223

python/triqs_dft_tools/sumk_dft_tools.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -676,14 +676,15 @@ def spaghettis(self, mu=None, broadening=None, mesh=None, plot_shift=0.0, plot_r
676676
with_dc : boolean, optional
677677
If True the double counting correction is used.
678678
proj_type : string, optional
679-
The type of projection used for the orbital-projected DOS.
679+
The type of projection used for the orbital-projected spectral function.
680680
These projected spectral functions will be determined alongside the total spectral function.
681-
By default, no projected DOS type will be calculated (the corresponding projected arrays will be empty).
681+
By default, no projected spectral function will be calculated (the corresponding projected arrays will be empty).
682682
The following options are:
683683
684-
'None' - Only total DOS calculated
685-
'wann' - Wannier DOS calculated from the Wannier projectors
686-
'wien2k' - Wien2k orbital-projected DOS from the wien2k theta projectors
684+
'None' - Only total A(k,w) calculated
685+
'wann' - Wannier A(k,w) calculated from the Wannier projectors
686+
'vasp' - Vasp orbital-projected A(k,w) from Vasp inputs
687+
'wien2k' - Wien2k orbital-projected A(k,w) from the wien2k theta projectors
687688
save_to_file : boolean, optional
688689
If True, text files with the calculated data will be created.
689690
@@ -705,7 +706,7 @@ def spaghettis(self, mu=None, broadening=None, mesh=None, plot_shift=0.0, plot_r
705706

706707
# initialisation
707708
if (proj_type != None):
708-
assert proj_type in ('wann', 'wien2k'), "'proj_type' must be either 'wann', 'wien2k'"
709+
assert proj_type in ('wann', 'vasp', 'wien2k'), "'proj_type' must be either 'wann', 'vasp', 'wien2k'"
709710
if (proj_type != 'wann'):
710711
assert proj_type == self.dft_code, "proj_type must be from the corresponding dft inputs."
711712
things_to_read = ['n_k', 'n_orbitals', 'proj_mat', 'hopping']
@@ -825,6 +826,7 @@ def gen_Akw(self, mu, broadening, mesh, plot_shift, plot_range, shell_list, with
825826
proj_type : string
826827
Output the orbital-projected A(k,w) type from the following:
827828
'wann' - Wannier A(k,w) calculated from the Wannier projectors
829+
'vasp' - Vasp orbital-projected A(k,w) from Vasp inputs
828830
'wien2k' - Wien2k orbital-projected A(k,w) from the wien2k theta projectors
829831
830832
Returns
@@ -863,6 +865,11 @@ def gen_Akw(self, mu, broadening, mesh, plot_shift, plot_range, shell_list, with
863865
gf_struct = self.gf_struct_sumk.copy()
864866
dims = [self.corr_shells[ish]['dim'] for ish in range(n_shells)]
865867
shells_type = 'corr'
868+
elif (proj_type == 'vasp'):
869+
n_shells = self.n_corr_shells
870+
gf_struct = self.gf_struct_sumk.copy()
871+
dims = [self.corr_shells[ish]['dim'] for ish in range(n_shells)]
872+
shells_type = 'corr'
866873
elif (proj_type == 'wien2k'):
867874
n_shells = self.n_shells
868875
gf_struct = [[(sp, self.shells[ish]['dim']) for sp in spn]
@@ -914,10 +921,11 @@ def gen_Akw(self, mu, broadening, mesh, plot_shift, plot_range, shell_list, with
914921
G_loc[ish].zero()
915922
tmp = G_loc[ish].copy()
916923
tmp.zero()
917-
tmp << self.proj_type_G_loc(G_latt_w, tmp, ik, ish, proj_type)
924+
downfold_proj_type = 'wann' if proj_type == 'vasp' else proj_type
925+
tmp << self.proj_type_G_loc(G_latt_w, tmp, ik, ish, downfold_proj_type)
918926
G_loc[ish] += tmp
919927
# Rotate to local frame
920-
if (self.use_rotations):
928+
if ((proj_type != 'vasp') and self.use_rotations):
921929
for ish in range(n_shells):
922930
jsh=shell_list[ish]
923931
for bname, gf in G_loc[ish]:
@@ -928,7 +936,7 @@ def gen_Akw(self, mu, broadening, mesh, plot_shift, plot_range, shell_list, with
928936
pAkw_orb[ish][bname][ik,:,:,:] = -gf.data[numpy.where((mesh_val > om_minplot) &
929937
(mesh_val < om_maxplot)),:,:].imag/numpy.pi
930938
# shift pAkw_orb for plotting stacked k-resolved eps(k) curves
931-
pAkw_orb[ish][sp][ik] += ik * plot_shift
939+
pAkw_orb[ish][bname][ik] += ik * plot_shift
932940

933941
# Collect data from mpi
934942
mpi.barrier()
@@ -1057,5 +1065,3 @@ def print_hamiltonian(self):
10571065
(ik, self.hopping[ik, 0, i, i].real))
10581066
f.write('\n')
10591067
f.close()
1060-
1061-

test/python/svo_vasp_bands.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import numpy as np
2+
3+
from h5 import HDFArchive
4+
from triqs.gf import BlockGf, Gf
5+
from triqs.utility.comparison_tests import assert_arrays_are_close
6+
7+
from triqs_dft_tools.sumk_dft_tools import SumkDFTTools
8+
9+
10+
def assert_spectral_data_is_valid(Akw, pAkw, pAkw_orb, n_k, n_om, dim):
11+
for sp in ('up', 'down'):
12+
assert Akw[sp].shape == (n_k, n_om)
13+
assert pAkw[0][sp].shape == (n_k, n_om)
14+
assert pAkw_orb[0][sp].shape == (n_k, n_om, dim, dim)
15+
16+
assert np.all(np.isfinite(Akw[sp]))
17+
assert np.all(np.isfinite(pAkw[0][sp]))
18+
assert np.all(np.isfinite(pAkw_orb[0][sp]))
19+
assert np.min(Akw[sp]) > -1.0e-12
20+
assert np.min(pAkw[0][sp]) > -1.0e-12
21+
22+
assert_arrays_are_close(
23+
pAkw[0][sp],
24+
pAkw_orb[0][sp].trace(axis1=2, axis2=3),
25+
precision=1.0e-12,
26+
)
27+
28+
29+
def make_diagonal_sigma_from_srvo3():
30+
with HDFArchive('SrVO3_Sigma.h5', 'r') as ar:
31+
sigma_srvo3 = ar['dmft_transp_input']['Sigma_w']
32+
33+
block_list = [
34+
Gf(mesh=sigma_srvo3.mesh, target_shape=(3, 3)),
35+
Gf(mesh=sigma_srvo3.mesh, target_shape=(3, 3)),
36+
]
37+
sigma = BlockGf(name_list=['up', 'down'], block_list=block_list, make_copies=False)
38+
sigma.zero()
39+
40+
for sp in ('up', 'down'):
41+
for orb in range(3):
42+
sigma[sp].data[:, orb, orb] = sigma_srvo3[f'{sp}_{orb}'].data[:, 0, 0]
43+
44+
return sigma
45+
46+
47+
Sigma = make_diagonal_sigma_from_srvo3()
48+
n_om = len(Sigma.mesh)
49+
50+
SK = SumkDFTTools(hdf_file='svo_vasp_bands.test.h5', mesh=Sigma.mesh)
51+
52+
Akw_vasp, pAkw_vasp, pAkw_orb_vasp = SK.spaghettis(
53+
broadening=0.05,
54+
mesh=Sigma.mesh,
55+
with_Sigma=False,
56+
with_dc=False,
57+
proj_type='vasp',
58+
save_to_file=False,
59+
)
60+
61+
Akw_wann, pAkw_wann, pAkw_orb_wann = SK.spaghettis(
62+
broadening=0.05,
63+
mesh=Sigma.mesh,
64+
with_Sigma=False,
65+
with_dc=False,
66+
proj_type='wann',
67+
save_to_file=False,
68+
)
69+
70+
assert_spectral_data_is_valid(Akw_vasp, pAkw_vasp, pAkw_orb_vasp, SK.n_k, n_om, 3)
71+
72+
for sp in ('up', 'down'):
73+
assert_arrays_are_close(Akw_vasp[sp], Akw_wann[sp], precision=1.0e-12)
74+
assert_arrays_are_close(pAkw_vasp[0][sp], pAkw_wann[0][sp], precision=1.0e-12)
75+
assert_arrays_are_close(pAkw_orb_vasp[0][sp], pAkw_orb_wann[0][sp], precision=1.0e-12)
76+
77+
SK.set_Sigma([Sigma], transform_to_sumk_blocks=False)
78+
79+
Akw_sigma, pAkw_sigma, pAkw_orb_sigma = SK.spaghettis(
80+
with_Sigma=True,
81+
with_dc=False,
82+
proj_type='vasp',
83+
save_to_file=False,
84+
)
85+
86+
assert_spectral_data_is_valid(Akw_sigma, pAkw_sigma, pAkw_orb_sigma, SK.n_k, n_om, 3)
87+
88+
for sp in ('up', 'down'):
89+
assert np.max(np.abs(Akw_sigma[sp] - Akw_vasp[sp])) > 1.0e-6
90+
assert np.max(np.abs(pAkw_sigma[0][sp] - pAkw_vasp[0][sp])) > 1.0e-6

test/python/svo_vasp_bands.test.h5

450 KB
Binary file not shown.

0 commit comments

Comments
 (0)