mirror of
https://github.com/triqs/dft_tools
synced 2024-08-29 07:22:01 +02:00
Merge branch 'master' into vasp
Conflicts: CMakeLists.txt python/CMakeLists.txt python/converters/__init__.py test/CMakeLists.txt
This commit is contained in:
commit
f142db96fb
@ -14,14 +14,19 @@ enable_testing()
|
||||
# Load TRIQS, including all predefined variables from TRIQS installation
|
||||
find_package(TRIQS REQUIRED)
|
||||
|
||||
if (NOT ${TRIQS_WITH_PYTHON_SUPPORT})
|
||||
MESSAGE(FATAL_ERROR "dft_tools require Python support in TRIQS")
|
||||
endif()
|
||||
|
||||
# Check that versions are compatible
|
||||
if(NOT DFT_TOOLS_VERSION EQUAL TRIQS_VERSION)
|
||||
message(FATAL_ERROR "The application version is not compatible with the TRIQS library (TRIQS library version: ${TRIQS_VERSION} while this application version: ${DFT_TOOLS_VERSION})")
|
||||
endif()
|
||||
if (NOT ${TRIQS_WITH_PYTHON_SUPPORT})
|
||||
MESSAGE(FATAL_ERROR "dft_tools require Python support in TRIQS")
|
||||
endif()
|
||||
|
||||
# Get hash
|
||||
triqs_get_git_hash(${CMAKE_SOURCE_DIR} "DFT_TOOLS")
|
||||
if(${GIT_RESULT} EQUAL 0)
|
||||
message(STATUS "Hash: ${DFT_TOOLS_GIT_HASH}")
|
||||
endif(${GIT_RESULT} EQUAL 0)
|
||||
|
||||
# We want to be installed in the TRIQS tree
|
||||
set(CMAKE_INSTALL_PREFIX ${TRIQS_PATH})
|
||||
|
8
cmake/sitecustomize.py
Normal file
8
cmake/sitecustomize.py
Normal file
@ -0,0 +1,8 @@
|
||||
def application_pytriqs_import(name,*args,**kwargs):
|
||||
if name.startswith('@package_name@'):
|
||||
name = name[len('@package_name@')+1:]
|
||||
return builtin_import(name,*args,**kwargs)
|
||||
|
||||
import __builtin__
|
||||
__builtin__.__import__, builtin_import = application_pytriqs_import, __builtin__.__import__
|
||||
|
@ -77,7 +77,7 @@ for iteration_number in range(1,loops+1):
|
||||
if mpi.is_master_node(): print "Iteration = ", iteration_number
|
||||
|
||||
SK.symm_deg_gf(S.Sigma_iw,orb=0) # symmetrise Sigma
|
||||
SK.put_Sigma(Sigma_imp = [ S.Sigma_iw ]) # put Sigma into the SumK class
|
||||
SK.set_Sigma([ S.Sigma_iw ]) # set Sigma into the SumK class
|
||||
chemical_potential = SK.calc_mu( precision = prec_mu ) # find the chemical potential for given density
|
||||
S.G_iw << SK.extract_G_loc()[0] # calc the local Green function
|
||||
mpi.report("Total charge of Gloc : %.6f"%S.G_iw.total_density())
|
||||
|
@ -2,6 +2,9 @@
|
||||
#
|
||||
# TRIQS documentation build configuration file
|
||||
|
||||
import sys
|
||||
sys.path.insert(0, "@TRIQS_SPHINXEXT_PATH@/numpydoc")
|
||||
|
||||
extensions = ['sphinx.ext.autodoc',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.intersphinx',
|
||||
|
@ -3,13 +3,14 @@ Frequently-Asked Questions
|
||||
|
||||
wien2k: FERMI ERROR when running `x lapw2 -almd -band`
|
||||
------------------------------------------------------
|
||||
|
||||
In some versions of Wien2k, there is a problem in running `x lapw2 -almd -band`.
|
||||
|
||||
A hack solution is as follows:
|
||||
1) `x lapw1 -band`
|
||||
2) edit in2 file: replace 'TOT' with 'QTL', 'TETRA' with 'ROOT'
|
||||
3) `x lapw2 -almd -band`
|
||||
4) `dmftproj -band` (add the fermi energy to file, it can be found by running `grep :FER *.scf`)
|
||||
4) `dmftproj -band` (add the Fermi energy to file, it can be found by running `grep :FER *.scf`)
|
||||
|
||||
How do I plot the output of `spaghettis`?
|
||||
-----------------------------------------
|
||||
@ -20,6 +21,20 @@ the parameters as desired.
|
||||
|
||||
.. literalinclude:: plotting_spaghettis.py
|
||||
|
||||
x optic does not write a case.pmat file
|
||||
---------------------------------------
|
||||
|
||||
Make sure that you set line 6 to "ON" and put a "1" to the following line.
|
||||
The "1" is undocumented in Wien2k, but needed to have `case.pmat` written.
|
||||
However, we are working on reading directly the `case.mommat2` file.
|
||||
|
||||
No module named pytriqs.*** error when running a script
|
||||
-------------------------------------------------------
|
||||
|
||||
Make sure that have properly build, tested and installed TRIQS and DFTTools
|
||||
using, make, make test and make install. Additionally, you should always
|
||||
use pytriqs to call your scripts, e.g. pytriqs yourscript.py
|
||||
|
||||
Why is my calculation not working?
|
||||
----------------------------------
|
||||
|
||||
|
@ -64,9 +64,9 @@ where:
|
||||
It is important that each data file has to contain three columns: the real frequency mesh, the real part and the imaginary part
|
||||
of the self energy - exactly in this order! The mesh should be the same for all files read in and non-uniform meshes are not supported.
|
||||
|
||||
Finally, we put the self energy into the `SK` object::
|
||||
Finally, we set the self energy into the `SK` object::
|
||||
|
||||
SK.put_Sigma(Sigma_imp = [SigmaReFreq])
|
||||
SK.set_Sigma([SigmaReFreq])
|
||||
|
||||
and additionally set the chemical potential and the double counting correction from the DMFT calculation::
|
||||
|
||||
@ -96,7 +96,7 @@ the output is printed into the files
|
||||
* `DOS_wannier_(sp)_proj(i)_(m)_(n).dat`: As above, but printed as orbitally-resolved matrix in indices
|
||||
`(m)` and `(n)`. For `d` orbitals, it gives the DOS separately for, e.g., :math:`d_{xy}`, :math:`d_{x^2-y^2}`, and so on,
|
||||
|
||||
otherwise, the ouptput is returned by the function for a further usage in :program:`python`.
|
||||
otherwise, the output is returned by the function for a further usage in :program:`python`.
|
||||
|
||||
Partial charges
|
||||
---------------
|
||||
@ -104,7 +104,7 @@ Partial charges
|
||||
Since we can calculate the partial charges directly from the Matsubara Green's functions, we also do not need a
|
||||
real frequency self energy for this purpose. The calculation is done by::
|
||||
|
||||
SK.put_Sigma(Sigma_imp = SigmaImFreq)
|
||||
SK.set_Sigma(SigmaImFreq)
|
||||
dm = SK.partial_charges(beta=40.0, with_Sigma=True, with_dc=True)
|
||||
|
||||
which calculates the partial charges using the self energy, double counting, and chemical potential as set in the
|
||||
|
@ -15,7 +15,7 @@ Interface with Wien2k
|
||||
|
||||
We assume that the user has obtained a self-consistent solution of the
|
||||
Kohn-Sham equations. We further have to require that the user is
|
||||
familiar with the main inout/output files of Wien2k, and how to run
|
||||
familiar with the main in/output files of Wien2k, and how to run
|
||||
the DFT code.
|
||||
|
||||
Conversion for the DMFT self-consistency cycle
|
||||
@ -31,7 +31,7 @@ We note that any other flag for lapw2, such as -c or -so (for
|
||||
spin-orbit coupling) has to be added also to this line. This creates
|
||||
some files that we need for the Wannier orbital construction.
|
||||
|
||||
The orbital construction itself is done by the fortran program
|
||||
The orbital construction itself is done by the Fortran program
|
||||
:program:`dmftproj`. For an extensive manual to this program see
|
||||
:download:`TutorialDmftproj.pdf <images_scripts/TutorialDmftproj.pdf>`.
|
||||
Here we will only describe only the basic steps.
|
||||
@ -79,7 +79,7 @@ following 3 to 5 lines:
|
||||
|
||||
These lines have to be repeated for each inequivalent atom.
|
||||
|
||||
The last line gives the energy window, relativ to the Fermi energy,
|
||||
The last line gives the energy window, relative to the Fermi energy,
|
||||
that is used for the projective Wannier functions. Note that, in
|
||||
accordance with Wien2k, we give energies in Rydberg units!
|
||||
|
||||
@ -207,7 +207,7 @@ The lines of this header define
|
||||
2 3. Thiw would mean, 2 irreps (eg and t2g), of dimension 2 and 3,
|
||||
resp.
|
||||
|
||||
After these header lines, the file has to contain the hamiltonian
|
||||
After these header lines, the file has to contain the Hamiltonian
|
||||
matrix in orbital space. The standard convention is that you give for
|
||||
each
|
||||
:math:`\mathbf{k}`-point first the matrix of the real part, then the
|
||||
@ -227,6 +227,116 @@ with the
|
||||
For more options of this converter, have a look at the
|
||||
:ref:`refconverters` section of the reference manual.
|
||||
|
||||
|
||||
Wannier90 Converter
|
||||
-------------------
|
||||
|
||||
Using this converter it is possible to convert the output of
|
||||
:program:`Wannier90` (http://wannier.org) calculations of
|
||||
Maximally Localized Wannier Functions (MLWF) and create a HDF5 archive
|
||||
suitable for one-shot DMFT calculations with the
|
||||
:class:`SumkDFT <pytriqs.applications.dft.sumk_dft.SumkDFT>` class.
|
||||
|
||||
The user must supply two files in order to run the Wannier90 Converter:
|
||||
|
||||
#. The file :file:`seedname_hr.dat`, which contains the DFT Hamiltonian
|
||||
in the MLWF basis calculated through :program:`wannier90` with ``hr_plot = true``
|
||||
(please refer to the :program:`wannier90` documentation).
|
||||
#. A file named :file:`seedname.inp`, which contains the required
|
||||
information about the :math:`\mathbf{k}`-point mesh, the electron density,
|
||||
the correlated shell structure, ... (see below).
|
||||
|
||||
Here and in the following, the keyword ``seedname`` should always be intended
|
||||
as a placeholder for the actual prefix chosen by the user when creating the
|
||||
input for :program:`wannier90`.
|
||||
Once these two files are available, one can use the converter as follows::
|
||||
|
||||
from pytriqs.applications.dft.converters import Wannier90Converter
|
||||
Converter = Wannier90Converter(seedname='seedname')
|
||||
Converter.convert_dft_input()
|
||||
|
||||
The converter input :file:`seedname.inp` is a simple text file with
|
||||
the following format:
|
||||
|
||||
.. literalinclude:: images_scripts/LaVO3_w90.inp
|
||||
|
||||
The example shows the input for the perovskite crystal of LaVO\ :sub:`3`
|
||||
in the room-temperature `Pnma` symmetry. The unit cell contains four
|
||||
symmetry-equivalent correlated sites (the V atoms) and the total number
|
||||
of electrons per unit cell is 8 (see second line).
|
||||
The first line specifies how to generate the :math:`\mathbf{k}`-point
|
||||
mesh that will be used to obtain :math:`H(\mathbf{k})`
|
||||
by Fourier transforming :math:`H(\mathbf{R})`.
|
||||
Currently implemented options are:
|
||||
|
||||
* :math:`\Gamma`-centered uniform grid with dimensions
|
||||
:math:`n_{k_x} \times n_{k_y} \times n_{k_z}`;
|
||||
specify ``0`` followed by the three grid dimensions,
|
||||
like in the example above
|
||||
* :math:`\Gamma`-centered uniform grid with dimensions
|
||||
automatically determined by the converter (from the number of
|
||||
:math:`\mathbf{R}` vectors found in :file:`seedname_hr.dat`);
|
||||
just specify ``-1``
|
||||
|
||||
Inside :file:`seedname.inp`, it is crucial to correctly specify the
|
||||
correlated shell structure, which depends on the contents of the
|
||||
:program:`wannier90` output :file:`seedname_hr.dat` and on the order
|
||||
of the MLWFs contained in it.
|
||||
|
||||
The number of MLWFs must be equal to, or greater than the total number
|
||||
of correlated orbitals (i.e., the sum of all ``dim`` in :file:`seedname.inp`).
|
||||
If the converter finds fewer MLWFs inside :file:`seedname_hr.dat`, then it
|
||||
stops with an error; if it finds more MLWFs, then it assumes that the
|
||||
additional MLWFs correspond to uncorrelated orbitals (e.g., the O-\ `2p` shells).
|
||||
When reading the hoppings :math:`\langle w_i | H(\mathbf{R}) | w_j \rangle`
|
||||
(where :math:`w_i` is the :math:`i`-th MLWF), the converter also assumes that
|
||||
the first indices correspond to the correlated shells (in our example,
|
||||
the V-t\ :sub:`2g` shells). Therefore, the MLWFs corresponding to the
|
||||
uncorrelated shells (if present) must be listed **after** those of the
|
||||
correlated shells.
|
||||
With the :program:`wannier90` code, this can be achieved this by listing the
|
||||
projections for the uncorrelated shells after those for the correlated shells.
|
||||
In our `Pnma`-LaVO\ :sub:`3` example, for instance, we could use::
|
||||
|
||||
Begin Projections
|
||||
V:l=2,mr=2,3,5:z=0,0,1:x=-1,1,0
|
||||
O:l=1:mr=1,2,3:z=0,0,1:x=-1,1,0
|
||||
End Projections
|
||||
|
||||
where the ``x=-1,1,0`` option indicates that the V--O bonds in the octahedra are
|
||||
rotated by (approximatively) 45 degrees with respect to the axes of the `Pbnm` cell.
|
||||
|
||||
The converter will analyse the matrix elements of the local hamiltonian
|
||||
to find the symmetry matrices `rot_mat` needed for the global-to-local
|
||||
transformation of the basis set for correlated orbitals
|
||||
(see section :ref:`hdfstructure`).
|
||||
The matrices are obtained by finding the unitary transformations that diagonalize
|
||||
:math:`\langle w_i | H_I(\mathbf{R}=0,0,0) | w_j \rangle`, where :math:`I` runs
|
||||
over the correlated shells and `i,j` belong to the same shell (more details elsewhere...).
|
||||
If two correlated shells are defined as equivalent in :file:`seedname.inp`,
|
||||
then the corresponding eigenvalues have to match within a threshold of 10\ :sup:`-5`,
|
||||
otherwise the converter will produce an error/warning.
|
||||
If this happens, please carefully check your data in :file:`seedname_hr.dat`.
|
||||
This method might fail in non-trivial cases (i.e., more than one correlated
|
||||
shell is present) when there are some degenerate eigenvalues:
|
||||
so far tests have not shown any issue, but one must be careful in those cases
|
||||
(the converter will print a warning message).
|
||||
|
||||
The current implementation of the Wannier90 Converter has some limitations:
|
||||
|
||||
* Since :program:`wannier90` does not make use of symmetries (symmetry-reduction
|
||||
of the :math:`\mathbf{k}`-point grid is not possible), the converter always
|
||||
sets ``symm_op=0`` (see the :ref:`hdfstructure` section).
|
||||
* No charge self-consistency possible at the moment.
|
||||
* Calculations with spin-orbit (``SO=1``) are not supported.
|
||||
* The spin-polarized case (``SP=1``) is not yet tested.
|
||||
* The post-processing routines in the module
|
||||
:class:`SumkDFTTools <pytriqs.applications.dft.sumk_dft_tools.SumkDFTTools>`
|
||||
were not tested with this converter.
|
||||
* ``proj_mat_all`` are not used, so there are no projectors onto the
|
||||
uncorrelated orbitals for now.
|
||||
|
||||
|
||||
MPI issues
|
||||
----------
|
||||
|
||||
|
@ -41,7 +41,7 @@ These steps are not necessary, but can help to reduce fluctuations in the total
|
||||
Now we calculate the modified charge density::
|
||||
|
||||
# find exact chemical potential
|
||||
SK.put_Sigma(Sigma_imp = [ S.Sigma_iw ])
|
||||
SK.set_Sigma([ S.Sigma_iw ])
|
||||
chemical_potential = SK.calc_mu( precision = 0.000001 )
|
||||
dN, d = SK.calc_density_correction(filename = dft_filename+'.qdmft')
|
||||
SK.save(['chemical_potential','dc_imp','dc_energ'])
|
||||
@ -56,10 +56,10 @@ We need also the correlation energy, which we evaluate by the Migdal formula::
|
||||
correnerg = 0.5 * (S.G_iw * S.Sigma_iw).total_density()
|
||||
|
||||
Other ways of calculating the correlation energy are possible, for
|
||||
instance a direct measurment of the expectation value of the
|
||||
interacting hamiltonian. However, the Migdal formula works always,
|
||||
instance a direct measurement of the expectation value of the
|
||||
interacting Hamiltonian. However, the Migdal formula works always,
|
||||
independent of the solver that is used to solve the impurity problem.
|
||||
From this value, we substract the double counting energy::
|
||||
From this value, we subtract the double counting energy::
|
||||
|
||||
correnerg -= SK.dc_energ[0]
|
||||
|
||||
@ -104,13 +104,13 @@ number of nodes to be used:
|
||||
|
||||
In that case, you will run on 64 computing cores. As standard setting,
|
||||
we use `mpirun` as the proper MPI execution statement. If you happen
|
||||
to have a differnet, non-standard MPI setup, you have to give the
|
||||
to have a different, non-standard MPI setup, you have to give the
|
||||
proper MPI execution statement, in the `run_lapw` script (see the
|
||||
corresponding :program:`Wien2k` documentation).
|
||||
|
||||
In many cases it is advisable to start from a converged one-shot
|
||||
calculation. For practical purposes, you keep the number of DMFT loops
|
||||
within one DFT cycle low, or even to `loops=1`. If you encouter
|
||||
within one DFT cycle low, or even to `loops=1`. If you encounter
|
||||
unstable convergence, you have to adjust the parameters such as
|
||||
the number of DMFT loops, or some mixing of the self energy to improve
|
||||
the convergence.
|
||||
|
@ -50,7 +50,7 @@ iterations and the self-consistency condition::
|
||||
n_loops = 5
|
||||
for iteration_number in range(n_loops) : # start the DMFT loop
|
||||
|
||||
SK.put_Sigma(Sigma_imp = [ S.Sigma ]) # Put self energy to the SumK class
|
||||
SK.set_Sigma([ S.Sigma ]) # Put self energy to the SumK class
|
||||
chemical_potential = SK.calc_mu() # calculate the chemical potential for the given density
|
||||
S.G_iw << SK.extract_G_loc()[0] # extract the local Green function
|
||||
S.G0_iw << inverse(S.Sigma_iw + inverse(S.G_iw)) # finally get G0, the input for the Solver
|
||||
@ -107,7 +107,7 @@ execution. For the convenience of the user, we provide also two
|
||||
working python scripts in this documentation. One for a calculation
|
||||
using Kanamori definitions (:download:`dft_dmft_cthyb.py
|
||||
<images_scripts/dft_dmft_cthyb.py>`) and one with a
|
||||
rotational-invariant Slater interaction hamiltonian (:download:`dft_dmft_cthyb_slater.py
|
||||
rotational-invariant Slater interaction Hamiltonian (:download:`dft_dmft_cthyb_slater.py
|
||||
<images_scripts/dft_dmft_cthyb.py>`). The user has to adapt these
|
||||
scripts to his own needs.
|
||||
|
||||
@ -145,7 +145,7 @@ Most of these parameters are self-explanatory. The first,
|
||||
details on the solver parameters, we refer the user to
|
||||
the :ref:`CTHYB solver <triqscthyb:welcome>` documentation.
|
||||
|
||||
We assume that the conversion to the hdf5 archive is alreadz done. We
|
||||
We assume that the conversion to the hdf5 archive is already done. We
|
||||
can check now in this archive, if previous runs are present, or if we have to start
|
||||
from scratch::
|
||||
|
||||
@ -165,7 +165,7 @@ from scratch::
|
||||
previous_present = mpi.bcast(previous_present)
|
||||
|
||||
|
||||
You can see in this code snipet, that all results of this calculation
|
||||
You can see in this code snippet, that all results of this calculation
|
||||
will be stored in a separate subgroup in the hdf5 file, called
|
||||
`dmft_output`. Removing this subgroup allows you to reset your
|
||||
calculation to the starting point easily.
|
||||
@ -178,7 +178,7 @@ The next step is to initialise the :class:`Solver <pytriqs.applications.impurit
|
||||
of two steps
|
||||
|
||||
#. Calculating the multi-band interaction matrix, and setting up the
|
||||
interaction hamiltonian
|
||||
interaction Hamiltonian
|
||||
#. Setting up the solver class
|
||||
|
||||
The first step is done using methods of
|
||||
@ -199,13 +199,13 @@ other choices (Slater interaction matrix for instance), and other
|
||||
parameters, we refer to the reference manual
|
||||
of the :ref:`TRIQS <triqslibs:welcome>` library.
|
||||
|
||||
Next, we construct the hamiltonian and the solver::
|
||||
Next, we construct the Hamiltonian and the solver::
|
||||
|
||||
h_int = h_int_density(spin_names, orb_names, map_operator_structure=SK.sumk_to_solver[0], U=Umat, Uprime=Upmat)
|
||||
S = Solver(beta=beta, gf_struct=gf_struct)
|
||||
|
||||
As you see, we take only density-density interactions into
|
||||
account. Other choices for the hamiltonian are
|
||||
account. Other choices for the Hamiltonian are
|
||||
|
||||
* h_int_kanamori
|
||||
* h_int_slater
|
||||
@ -239,7 +239,7 @@ refinements::
|
||||
if mpi.is_master_node(): print "Iteration = ", iteration_number
|
||||
|
||||
SK.symm_deg_gf(S.Sigma_iw,orb=0) # symmetrise Sigma
|
||||
SK.put_Sigma(Sigma_imp = [ S.Sigma_iw ]) # put Sigma into the SumK class
|
||||
SK.set_Sigma([ S.Sigma_iw ]) # put Sigma into the SumK class
|
||||
chemical_potential = SK.calc_mu( precision = prec_mu ) # find the chemical potential for given density
|
||||
S.G_iw << SK.extract_G_loc()[0] # calc the local Green function
|
||||
mpi.report("Total charge of Gloc : %.6f"%S.G_iw.total_density())
|
||||
|
@ -73,7 +73,7 @@ This program produces the following files:
|
||||
|
||||
* :file:`Ce-gamma.ctqmcout` and :file:`Ce-gamma.symqmc` containing projector operators and symmetry operations for orthonormalized Wannier orbitals, respectively.
|
||||
* :file:`Ce-gamma.parproj` and :file:`Ce-gamma.sympar` containing projector operators and symmetry operations for uncorrelated states, respectively. These files are needed for projected density-of-states or spectral-function calculations.
|
||||
* :file:`Ce-gamma.oubwin` needed for the charge desity recalculation in the case of fully self-consistent DFT+DMFT run (see below).
|
||||
* :file:`Ce-gamma.oubwin` needed for the charge density recalculation in the case of fully self-consistent DFT+DMFT run (see below).
|
||||
|
||||
Now we have all necessary input from :program:`Wien2k` for running DMFT calculations.
|
||||
|
||||
@ -101,9 +101,9 @@ The Hubbard-I initialization `Solver` has also optional parameters one may use:
|
||||
|
||||
* `n_msb`: the number of Matsubara frequencies used. The default is `n_msb=1025`.
|
||||
* `use_spin_orbit`: if set 'True' the solver is run with spin-orbit coupling included. To perform actual DFT+DMFT calculations with spin-orbit one should also run :program:`Wien2k` and :program:`dmftproj` in spin-polarized mode and with spin-orbit included. By default, `use_spin_orbit=False`.
|
||||
* `Nmoments`: the number of moments used to describe high-ferquency tails of the Hubbard-I Green's function and self-energy. By default `Nmoments = 5`
|
||||
* `Nmoments`: the number of moments used to describe high-frequency tails of the Hubbard-I Green's function and self-energy. By default `Nmoments = 5`
|
||||
|
||||
The `Solver.solve(U_int, J_hund)` statement has two necessary parameters, the Hubbard U parameter `U_int` and Hund's rule coupling `J_hund`. Notice that the solver constructs the full 4-index `U`-matrix by default, and the `U_int` parameter is in fact the Slatter `F0` integral. Other optional parameters are:
|
||||
The `Solver.solve(U_int, J_hund)` statement has two necessary parameters, the Hubbard U parameter `U_int` and Hund's rule coupling `J_hund`. Notice that the solver constructs the full 4-index `U`-matrix by default, and the `U_int` parameter is in fact the Slater `F0` integral. Other optional parameters are:
|
||||
|
||||
* `T`: matrix that transforms the interaction matrix from complex spherical harmonics to a symmetry adapted basis. By default, the complex spherical harmonics basis is used and `T=None`.
|
||||
* `verbosity`: tunes output from the solver. If `verbosity=0` only basic information is printed, if `verbosity=1` the ground state atomic occupancy and its energy are printed, if `verbosity=2` additional information is printed for all occupancies that were diagonalized. By default, `verbosity=0`.
|
||||
|
@ -2,7 +2,6 @@ from pytriqs.applications.dft.sumk_dft import *
|
||||
from pytriqs.applications.dft.converters.wien2k_converter import *
|
||||
from pytriqs.applications.impurity_solvers.hubbard_I.hubbard_solver import Solver
|
||||
|
||||
|
||||
import os
|
||||
dft_filename = os.getcwd().rpartition('/')[2]
|
||||
|
||||
@ -10,14 +9,12 @@ beta = 40
|
||||
U_int = 6.00
|
||||
J_hund = 0.70
|
||||
Loops = 5 # Number of DMFT sc-loops
|
||||
Mix = 0.7 # Mixing factor in QMC
|
||||
mixing = 0.7 # Mixing factor
|
||||
DC_type = 0 # 0...FLL, 1...Held, 2... AMF, 3...Lichtenstein
|
||||
chemical_potential_init=0.0 # initial chemical potential
|
||||
|
||||
HDFfilename = dft_filename+'.h5'
|
||||
|
||||
# Convert DMFT input:
|
||||
Converter = Wien2kConverter(filename=filename)
|
||||
Converter = Wien2kConverter(filename=dft_filename)
|
||||
Converter.convert_dft_input()
|
||||
mpi.barrier()
|
||||
|
||||
@ -25,7 +22,7 @@ mpi.barrier()
|
||||
previous_runs = 0
|
||||
previous_present = False
|
||||
if mpi.is_master_node():
|
||||
f = HDFArchive(filename+'.h5','a')
|
||||
f = HDFArchive(dft_filename+'.h5','a')
|
||||
if 'dmft_output' in f:
|
||||
ar = f['dmft_output']
|
||||
if 'iterations' in ar:
|
||||
@ -53,11 +50,11 @@ if previous_present:
|
||||
ar = HDFArchive(dft_filename+'.h5','a')
|
||||
S.Sigma << ar['dmft_output']['Sigma']
|
||||
del ar
|
||||
chemical_potential,dc_imp,dc_energ = SK.load(['chemical_potential','dc_imp','dc_energ'])
|
||||
SK.chemical_potential,SK.dc_imp,SK.dc_energ = SK.load(['chemical_potential','dc_imp','dc_energ'])
|
||||
S.Sigma << mpi.bcast(S.Sigma)
|
||||
SK.set_mu(chemical_potential)
|
||||
SK.set_dc(dc_imp,dc_energ)
|
||||
|
||||
SK.chemical_potential = mpi.bcast(SK.chemical_potential)
|
||||
SK.dc_imp = mpi.bcast(SK.dc_imp)
|
||||
SK.dc_energ = mpi.bcast(SK.dc_energ)
|
||||
|
||||
# DMFT loop:
|
||||
for iteration_number in range(1,Loops+1):
|
||||
@ -65,7 +62,7 @@ for iteration_number in range(1,Loops+1):
|
||||
itn = iteration_number + previous_runs
|
||||
|
||||
# put Sigma into the SumK class:
|
||||
SK.put_Sigma(Sigma_imp = [ S.Sigma ])
|
||||
SK.set_Sigma([ S.Sigma ])
|
||||
|
||||
# Compute the SumK, possibly fixing mu by dichotomy
|
||||
chemical_potential = SK.calc_mu( precision = 0.000001 )
|
||||
@ -89,11 +86,11 @@ for iteration_number in range(1,Loops+1):
|
||||
|
||||
# Now mix Sigma and G with factor Mix, if wanted:
|
||||
if (iteration_number>1 or previous_present):
|
||||
if (mpi.is_master_node() and (sigma_mix<1.0)):
|
||||
if (mpi.is_master_node() and (mixing<1.0)):
|
||||
ar = HDFArchive(dft_filename+'.h5','a')
|
||||
mpi.report("Mixing Sigma and G with factor %s"%sigma_mix)
|
||||
S.Sigma << sigma_mix * S.Sigma + (1.0-sigma_mix) * ar['dmft_output']['Sigma']
|
||||
S.G << sigma_mix * S.G + (1.0-sigma_mix) * ar['dmft_output']['G']
|
||||
mpi.report("Mixing Sigma and G with factor %s"%mixing)
|
||||
S.Sigma << mixing * S.Sigma + (1.0-mixing) * ar['dmft_output']['Sigma']
|
||||
S.G << mixing * S.G + (1.0-mixing) * ar['dmft_output']['G']
|
||||
del ar
|
||||
S.G << mpi.bcast(S.G)
|
||||
S.Sigma << mpi.bcast(S.Sigma)
|
||||
@ -104,8 +101,8 @@ for iteration_number in range(1,Loops+1):
|
||||
SK.calc_dc( dm, U_interact = U_int, J_hund = J_hund, orb = 0, use_dc_formula = DC_type )
|
||||
|
||||
# correlation energy calculations:
|
||||
correnerg = 0.5 * (S.G * S.Sigma).total_density()
|
||||
mpi.report("Corr. energy = %s"%correnerg)
|
||||
SK.correnerg = 0.5 * (S.G * S.Sigma).total_density()
|
||||
mpi.report("Corr. energy = %s"%SK.correnerg)
|
||||
|
||||
# store the impurity self-energy, GF as well as correlation energy in h5
|
||||
if mpi.is_master_node():
|
||||
@ -145,7 +142,7 @@ mpi.report("Trace of Density Matrix: %s"%d)
|
||||
|
||||
# store correlation energy contribution to be read by Wien2ki and then included to DFT+DMFT total energy
|
||||
if (mpi.is_master_node()):
|
||||
correnerg -= DCenerg[0]
|
||||
SK.correnerg -= SK.dc_energ[0]
|
||||
f=open(dft_filename+'.qdmft','a')
|
||||
f.write("%.16f\n"%correnerg)
|
||||
f.write("%.16f\n"%SK.correnerg)
|
||||
f.close()
|
||||
|
@ -14,23 +14,21 @@ ommax=6.0
|
||||
N_om=2001
|
||||
broadening = 0.02
|
||||
|
||||
HDFfilename = dft_filename+'.h5'
|
||||
|
||||
# Convert DMFT input:
|
||||
Converter = Wien2kConverter(filename=dft_filename,repacking=True)
|
||||
Converter.convert_dft_input()
|
||||
Converter.convert_parproj_input()
|
||||
|
||||
|
||||
|
||||
# Init the SumK class
|
||||
SK = SumkDFTTools(hdf_file=dft_filename+'.h5',use_dft_blocks=False)
|
||||
|
||||
# load old chemical potential and DC
|
||||
if mpi.is_master_node():
|
||||
chemical_potential,dc_imp,dc_energ = SK.load(['chemical_potential','dc_imp','dc_energ'])
|
||||
SK.set_mu(chemical_potential)
|
||||
SK.set_dc(dc_imp,dc_energ)
|
||||
SK.chemical_potential,SK.dc_imp,SK.dc_energ = SK.load(['chemical_potential','dc_imp','dc_energ'])
|
||||
|
||||
SK.chemical_potential = mpi.bcast(SK.chemical_potential)
|
||||
SK.dc_imp = mpi.bcast(SK.dc_imp)
|
||||
SK.dc_energ = mpi.bcast(SK.dc_energ)
|
||||
|
||||
if (mpi.is_master_node()):
|
||||
print 'DC after reading SK: ',SK.dc_imp[0]
|
||||
@ -47,7 +45,7 @@ S.set_atomic_levels( eal = eal )
|
||||
|
||||
# Run the solver to get GF and self-energy on the real axis
|
||||
S.GF_realomega(ommin=ommin, ommax = ommax, N_om=N_om,U_int=U_int,J_hund=J_hund)
|
||||
SK.put_Sigma(Sigma_imp = [S.Sigma])
|
||||
SK.set_Sigma([S.Sigma])
|
||||
|
||||
# compute DOS
|
||||
SK.dos_parproj_basis(broadening=broadening)
|
||||
|
7
doc/guide/images_scripts/LaVO3_w90.inp
Normal file
7
doc/guide/images_scripts/LaVO3_w90.inp
Normal file
@ -0,0 +1,7 @@
|
||||
0 6 4 6
|
||||
8.0
|
||||
4
|
||||
0 0 2 3 0 0
|
||||
1 0 2 3 0 0
|
||||
2 0 2 3 0 0
|
||||
3 0 2 3 0 0
|
@ -82,7 +82,7 @@ for iteration_number in range(1,loops+1):
|
||||
if mpi.is_master_node(): print "Iteration = ", iteration_number
|
||||
|
||||
SK.symm_deg_gf(S.Sigma_iw,orb=0) # symmetrise Sigma
|
||||
SK.put_Sigma(Sigma_imp = [ S.Sigma_iw ]) # put Sigma into the SumK class
|
||||
SK.set_Sigma([ S.Sigma_iw ]) # set Sigma into the SumK class
|
||||
chemical_potential = SK.calc_mu( precision = prec_mu ) # find the chemical potential for given density
|
||||
S.G_iw << SK.extract_G_loc()[0] # calc the local Green function
|
||||
mpi.report("Total charge of Gloc : %.6f"%S.G_iw.total_density())
|
||||
|
@ -83,7 +83,7 @@ for iteration_number in range(1,loops+1):
|
||||
if mpi.is_master_node(): print "Iteration = ", iteration_number
|
||||
|
||||
SK.symm_deg_gf(S.Sigma_iw,orb=0) # symmetrise Sigma
|
||||
SK.put_Sigma(Sigma_imp = [ S.Sigma_iw ]) # put Sigma into the SumK class
|
||||
SK.set_Sigma([ S.Sigma_iw ]) # set Sigma into the SumK class
|
||||
chemical_potential = SK.calc_mu( precision = prec_mu ) # find the chemical potential for given density
|
||||
S.G_iw << SK.extract_G_loc()[0] # calc the local Green function
|
||||
mpi.report("Total charge of Gloc : %.6f"%S.G_iw.total_density())
|
||||
|
@ -1,6 +1,6 @@
|
||||
.. _Transport:
|
||||
|
||||
Transport calculations
|
||||
Transport calculations test
|
||||
======================
|
||||
|
||||
Formalism
|
||||
@ -65,7 +65,10 @@ The basics steps to calculate the matrix elements of the momentum operator with
|
||||
6) Run `x optic`.
|
||||
|
||||
Additionally the input file :file:`case.inop` is required. A detail description on how to setup this file can be found in the Wien2k user guide [#userguide]_ on page 166.
|
||||
Here the energy window can be chosen according to the window used for :program:`dmftproj`. However, keep in mind that energies have to be specified in absolute values! Furthermore it is important to set line 6 to ON for printing the matrix elements to the :file:`.pmat` file.
|
||||
The optics energy window should be chosen according to the window used for :program:`dmftproj`. Note that the current version of the transport code uses only the smaller
|
||||
of those two windows. However, keep in mind that the optics energy window has to be specified in absolute values and NOT relative to the Fermi energy!
|
||||
You can read off the Fermi energy from the :file:`case.scf2` file. Please do not set the optional parameter NBvalMAX in :file:`case.inop`.
|
||||
Furthermore it is necessary to set line 6 to "ON" and put a "1" in the following line to enable the printing of the matrix elements to :file:`case.pmat`.
|
||||
|
||||
|
||||
Using the transport code
|
||||
@ -86,7 +89,7 @@ reads the required data of the Wien2k output and stores it in the `dft_transp_in
|
||||
Additionally we need to read and set the self energy, the chemical potential and the double counting::
|
||||
|
||||
ar = HDFArchive('case.h5', 'a')
|
||||
SK.put_Sigma(Sigma_imp = [ar['dmft_output']['Sigma_w']])
|
||||
SK.set_Sigma([ar['dmft_output']['Sigma_w']])
|
||||
chemical_potential,dc_imp,dc_energ = SK.load(['chemical_potential','dc_imp','dc_energ'])
|
||||
SK.set_mu(chemical_potential)
|
||||
SK.set_dc(dc_imp,dc_energ)
|
||||
|
@ -5,19 +5,25 @@ Converters
|
||||
|
||||
Wien2k Converter
|
||||
----------------
|
||||
.. autoclass:: pytriqs.applications.dft.converters.wien2k_converter.Wien2kConverter
|
||||
.. autoclass:: dft.converters.wien2k_converter.Wien2kConverter
|
||||
:members:
|
||||
:special-members:
|
||||
:show-inheritance:
|
||||
|
||||
H(k) Converter
|
||||
--------------
|
||||
.. autoclass:: pytriqs.applications.dft.converters.hk_converter.HkConverter
|
||||
.. autoclass:: dft.converters.hk_converter.HkConverter
|
||||
:members:
|
||||
:special-members:
|
||||
|
||||
Wannier90 Converter
|
||||
--------------
|
||||
.. autoclass:: dft.converters.wannier90_converter.Wannier90Converter
|
||||
:members:
|
||||
:special-members:
|
||||
|
||||
Converter Tools
|
||||
---------------
|
||||
.. autoclass:: pytriqs.applications.dft.converters.converter_tools.ConverterTools
|
||||
.. autoclass:: dft.converters.converter_tools.ConverterTools
|
||||
:members:
|
||||
:special-members:
|
||||
|
@ -2,7 +2,7 @@ SumK DFT
|
||||
========
|
||||
|
||||
|
||||
.. autoclass:: pytriqs.applications.dft.sumk_dft.SumkDFT
|
||||
.. autoclass:: sumk_dft.SumkDFT
|
||||
:members:
|
||||
:special-members:
|
||||
:show-inheritance:
|
||||
|
@ -2,7 +2,7 @@ SumK DFT Tools
|
||||
==============
|
||||
|
||||
|
||||
.. autoclass:: pytriqs.applications.dft.sumk_dft_tools.SumkDFTTools
|
||||
.. autoclass:: sumk_dft_tools.SumkDFTTools
|
||||
:members:
|
||||
:special-members:
|
||||
:show-inheritance:
|
||||
|
@ -1,6 +1,6 @@
|
||||
Symmetry
|
||||
========
|
||||
|
||||
.. autoclass:: pytriqs.applications.dft.Symmetry
|
||||
.. autoclass:: Symmetry
|
||||
:members:
|
||||
:special-members:
|
||||
|
@ -1,6 +1,6 @@
|
||||
TransBasis
|
||||
==========
|
||||
|
||||
.. autoclass:: pytriqs.applications.dft.trans_basis.TransBasis
|
||||
.. autoclass:: trans_basis.TransBasis
|
||||
:members:
|
||||
:special-members:
|
||||
|
@ -1,8 +1,11 @@
|
||||
# where will the python end up in triqs?
|
||||
set(python_destination applications/dft)
|
||||
set(python_destination pytriqs/applications/dft)
|
||||
|
||||
# site_customize for build
|
||||
set(package_name "pytriqs.applications")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/sitecustomize.py ${CMAKE_CURRENT_BINARY_DIR}/sitecustomize.py @ONLY)
|
||||
|
||||
# make a local pytriqs copy
|
||||
#triqs_prepare_local_pytriqs_merged_with_my_python(${python_destination})
|
||||
triqs_prepare_local_pytriqs(${python_destination})
|
||||
|
||||
# to be able to run from toplevel
|
||||
|
@ -23,7 +23,8 @@
|
||||
from wien2k_converter import Wien2kConverter
|
||||
from hk_converter import HkConverter
|
||||
from vasp_converter import VaspConverter
|
||||
from wannier90_converter import Wannier90Converter
|
||||
|
||||
__all__ =['Wien2kConverter','HkConverter','VaspConverter']
|
||||
__all__ =['Wien2kConverter','HkConverter','Wannier90Converter','VaspConverter']
|
||||
|
||||
|
||||
|
578
python/converters/wannier90_converter.py
Normal file
578
python/converters/wannier90_converter.py
Normal file
@ -0,0 +1,578 @@
|
||||
|
||||
##########################################################################
|
||||
#
|
||||
# TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
#
|
||||
# Copyright (C) 2011 by M. Aichhorn, L. Pourovskii, V. Vildosola
|
||||
#
|
||||
# TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
###
|
||||
# Wannier90 to HDF5 converter for the SumkDFT class of dfttools/TRIQS;
|
||||
#
|
||||
# written by Gabriele Sclauzero (Materials Theory, ETH Zurich), Dec 2015 -- Jan 2016,
|
||||
# under the supervision of Claude Ederer (Materials Theory).
|
||||
# Partially based on previous work by K. Dymkovski and the DFT_tools/TRIQS team.
|
||||
#
|
||||
# Limitations of the current implementation:
|
||||
# - the case with SO=1 is not considered at the moment
|
||||
# - the T rotation matrices are not used in this implementation
|
||||
# - projectors for uncorrelated shells (proj_mat_all) cannot be set
|
||||
#
|
||||
# Things to be improved/checked:
|
||||
# - the case with SP=1 might work, but was never tested (do we need to define
|
||||
# rot_mat_time_inv also if symm_op = 0?)
|
||||
# - the calculation of rot_mat in find_rot_mat() relies on the eigenvalues of H(0);
|
||||
# this might fail in presence of degenerate eigenvalues (now just prints warning)
|
||||
# - the FFT is always done in serial mode (because all converters run serially);
|
||||
# this can become very slow with a large number of R-vectors/k-points
|
||||
# - make the code more MPI safe (error handling): if we run with more than one process
|
||||
# and an error occurs on the masternode, the calculation does not abort
|
||||
###
|
||||
|
||||
|
||||
from types import *
|
||||
import numpy
|
||||
import math
|
||||
from pytriqs.archive import *
|
||||
from converter_tools import *
|
||||
from itertools import product
|
||||
import os.path
|
||||
|
||||
|
||||
class Wannier90Converter(ConverterTools):
|
||||
"""
|
||||
Conversion from Wannier90 output to an hdf5 file that can be used as input for the SumkDFT class.
|
||||
"""
|
||||
|
||||
def __init__(self, seedname, hdf_filename=None, dft_subgrp='dft_input',
|
||||
symmcorr_subgrp='dft_symmcorr_input', repacking=False):
|
||||
"""
|
||||
Initialise the class.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
seedname : string
|
||||
Base name of Wannier90 files
|
||||
hdf_filename : string, optional
|
||||
Name of hdf5 archive to be created
|
||||
dft_subgrp : string, optional
|
||||
Name of subgroup storing necessary DFT data
|
||||
symmcorr_subgrp : string, optional
|
||||
Name of subgroup storing correlated-shell symmetry data
|
||||
repacking : boolean, optional
|
||||
Does the hdf5 archive need to be repacked to save space?
|
||||
|
||||
"""
|
||||
|
||||
self._name = "Wannier90Converter"
|
||||
assert type(seedname) == StringType, self._name + \
|
||||
": Please provide the DFT files' base name as a string."
|
||||
if hdf_filename is None:
|
||||
hdf_filename = seedname + '.h5'
|
||||
self.hdf_file = hdf_filename
|
||||
# if the w90 output is seedname_hr.dat, the input file for the
|
||||
# converter must be called seedname.inp
|
||||
self.inp_file = seedname + '.inp'
|
||||
self.w90_seed = seedname
|
||||
self.dft_subgrp = dft_subgrp
|
||||
self.symmcorr_subgrp = symmcorr_subgrp
|
||||
self.fortran_to_replace = {'D': 'E'}
|
||||
# threshold below which matrix elements from wannier90 should be considered equal
|
||||
self._w90zero = 2.e-6
|
||||
|
||||
# Checks if h5 file is there and repacks it if wanted:
|
||||
if (os.path.exists(self.hdf_file) and repacking):
|
||||
ConverterTools.repack(self)
|
||||
|
||||
def convert_dft_input(self):
|
||||
"""
|
||||
Reads the appropriate files and stores the data for the
|
||||
|
||||
- dft_subgrp
|
||||
- symmcorr_subgrp
|
||||
|
||||
in the hdf5 archive.
|
||||
|
||||
"""
|
||||
|
||||
# Read and write only on the master node
|
||||
if not (mpi.is_master_node()):
|
||||
return
|
||||
mpi.report("Reading input from %s..." % self.inp_file)
|
||||
|
||||
# R is a generator : each R.Next() will return the next number in the file
|
||||
R = ConverterTools.read_fortran_file(
|
||||
self, self.inp_file, self.fortran_to_replace)
|
||||
shell_entries = ['atom', 'sort', 'l', 'dim']
|
||||
corr_shell_entries = ['atom', 'sort', 'l', 'dim', 'SO', 'irep']
|
||||
# First, let's read the input file with the parameters needed for the conversion
|
||||
try:
|
||||
# read k - point mesh generation option
|
||||
kmesh_mode = int(R.next())
|
||||
if kmesh_mode >= 0:
|
||||
# read k-point mesh size from input
|
||||
nki = [int(R.next()) for idir in range(3)]
|
||||
else:
|
||||
# some default grid, if everything else fails...
|
||||
nki = [8, 8, 8]
|
||||
# read the total number of electrons per cell
|
||||
density_required = float(R.next())
|
||||
# we do not read shells, because we have no additional shells beyond correlated ones,
|
||||
# and the data will be copied from corr_shells into shells (see below)
|
||||
# number of corr. shells (e.g. Fe d, Ce f) in the unit cell,
|
||||
n_corr_shells = int(R.next())
|
||||
# now read the information about the correlated shells (atom, sort, l, dim, SO flag, irep):
|
||||
corr_shells = [{name: int(val) for name, val in zip(
|
||||
corr_shell_entries, R)} for icrsh in range(n_corr_shells)]
|
||||
except StopIteration: # a more explicit error if the file is corrupted.
|
||||
mpi.report(self._name + ": reading input file %s failed!" %
|
||||
self.inp_file)
|
||||
# close the input file
|
||||
R.close()
|
||||
|
||||
# Set or derive some quantities
|
||||
# Wannier90 does not use symmetries to reduce the k-points
|
||||
# the following might change in future versions
|
||||
symm_op = 0
|
||||
# copy corr_shells into shells (see above)
|
||||
n_shells = n_corr_shells
|
||||
shells = []
|
||||
for ish in range(n_shells):
|
||||
shells.append({key: corr_shells[ish].get(
|
||||
key, None) for key in shell_entries})
|
||||
###
|
||||
SP = 0 # NO spin-polarised calculations for now
|
||||
SO = 0 # NO spin-orbit calculation for now
|
||||
charge_below = 0 # total charge below energy window NOT used for now
|
||||
energy_unit = 1.0 # should be understood as eV units
|
||||
###
|
||||
# this is more general
|
||||
n_spin = SP + 1 - SO
|
||||
dim_corr_shells = sum([sh['dim'] for sh in corr_shells])
|
||||
mpi.report(
|
||||
"Total number of WFs expected in the correlated shells: %d" % dim_corr_shells)
|
||||
|
||||
# determine the number of inequivalent correlated shells and maps, needed for further processing
|
||||
n_inequiv_shells, corr_to_inequiv, inequiv_to_corr = ConverterTools.det_shell_equivalence(
|
||||
self, corr_shells)
|
||||
mpi.report("Number of inequivalent shells: %d" % n_inequiv_shells)
|
||||
mpi.report("Shell representatives: " + format(inequiv_to_corr))
|
||||
shells_map = [inequiv_to_corr[corr_to_inequiv[ish]]
|
||||
for ish in range(n_corr_shells)]
|
||||
mpi.report("Mapping: " + format(shells_map))
|
||||
|
||||
# build the k-point mesh, if its size was given on input (kmesh_mode >= 0),
|
||||
# otherwise it is built according to the data in the hr file (see below)
|
||||
if kmesh_mode >= 0:
|
||||
n_k, k_mesh, bz_weights = self.kmesh_build(nki, kmesh_mode)
|
||||
self.n_k = n_k
|
||||
self.k_mesh = k_mesh
|
||||
|
||||
# not used in this version: reset to dummy values?
|
||||
n_reps = [1 for i in range(n_inequiv_shells)]
|
||||
dim_reps = [0 for i in range(n_inequiv_shells)]
|
||||
T = []
|
||||
for ish in range(n_inequiv_shells):
|
||||
ll = 2 * corr_shells[inequiv_to_corr[ish]]['l'] + 1
|
||||
lmax = ll * (corr_shells[inequiv_to_corr[ish]]['SO'] + 1)
|
||||
T.append(numpy.zeros([lmax, lmax], numpy.complex_))
|
||||
|
||||
spin_w90name = ['_up', '_down']
|
||||
hamr_full = []
|
||||
|
||||
# TODO: generalise to SP=1 (only partially done)
|
||||
rot_mat_time_inv = [0 for i in range(n_corr_shells)]
|
||||
|
||||
# Second, let's read the file containing the Hamiltonian in WF basis produced by Wannier90
|
||||
for isp in range(n_spin):
|
||||
# begin loop on isp
|
||||
|
||||
# build filename according to wannier90 conventions
|
||||
if SP == 1:
|
||||
mpi.report(
|
||||
"Reading information for spin component n. %d" % isp)
|
||||
hr_file = self.w90_seed + spin_w90name[isp] + '_hr.dat'
|
||||
else:
|
||||
hr_file = self.w90_seed + '_hr.dat'
|
||||
# now grab the data from the H(R) file
|
||||
mpi.report(
|
||||
"The Hamiltonian in MLWF basis is extracted from %s ..." % hr_file)
|
||||
nr, rvec, rdeg, nw, hamr = self.read_wannier90hr(hr_file)
|
||||
# number of R vectors, their indices, their degeneracy, number of WFs, H(R)
|
||||
mpi.report("... done: %d R vectors, %d WFs found" % (nr, nw))
|
||||
|
||||
if isp == 0:
|
||||
# set or check some quantities that must be the same for both spins
|
||||
self.nrpt = nr
|
||||
|
||||
# k-point grid: (if not defined before)
|
||||
if kmesh_mode == -1:
|
||||
# the size of the k-point mesh is determined from the largest R vector
|
||||
nki = [2 * rvec[:, idir].max() + 1 for idir in range(3)]
|
||||
# it will be the same as in the win only when nki is odd, because of the
|
||||
# wannier90 convention: if we have nki k-points along the i-th direction,
|
||||
# then we should get 2*(nki/2)+nki%2 R points along that direction
|
||||
n_k, k_mesh, bz_weights = self.kmesh_build(nki)
|
||||
self.n_k = n_k
|
||||
self.k_mesh = k_mesh
|
||||
|
||||
# set the R vectors and their degeneracy
|
||||
self.rvec = rvec
|
||||
self.rdeg = rdeg
|
||||
|
||||
self.nwfs = nw
|
||||
# check that the total number of WFs makes sense
|
||||
if self.nwfs < dim_corr_shells:
|
||||
mpi.report("ERROR: number of WFs in the file smaller than number of correlated orbitals!")
|
||||
elif self.nwfs > dim_corr_shells:
|
||||
# NOTE: correlated shells must appear before uncorrelated ones inside the file
|
||||
mpi.report("Number of WFs larger than correlated orbitals:\n" +
|
||||
"WFs from %d to %d treated as uncorrelated" % (dim_corr_shells + 1, self.nwfs))
|
||||
else:
|
||||
mpi.report("Number of WFs equal to number of correlated orbitals")
|
||||
|
||||
# we assume spin up and spin down always have same total number of WFs
|
||||
n_orbitals = numpy.ones(
|
||||
[self.n_k, n_spin], numpy.int) * self.nwfs
|
||||
|
||||
else:
|
||||
# consistency check between the _up and _down file contents
|
||||
if nr != self.nrpt:
|
||||
mpi.report("Different number of R vectors for spin-up/spin-down!")
|
||||
if nw != self.nwfs:
|
||||
mpi.report("Different number of WFs for spin-up/spin-down!")
|
||||
|
||||
hamr_full.append(hamr)
|
||||
# FIXME: when do we actually need deepcopy()?
|
||||
# hamr_full.append(deepcopy(hamr))
|
||||
|
||||
for ir in range(nr):
|
||||
# checks if the Hamiltonian is real (it should, if wannierisation worked fine)
|
||||
if numpy.abs((hamr[ir].imag.max()).max()) > self._w90zero:
|
||||
mpi.report("H(R) has large complex components at R %d" % ir)
|
||||
# copy the R=0 block corresponding to the correlated shells
|
||||
# into another variable (needed later for finding rot_mat)
|
||||
if rvec[ir, 0] == 0 and rvec[ir, 1] == 0 and rvec[ir, 2] == 0:
|
||||
ham_corr0 = hamr[ir][0:dim_corr_shells, 0:dim_corr_shells]
|
||||
|
||||
# checks if ham0 is Hermitian
|
||||
if not numpy.allclose(ham_corr0.transpose().conjugate(), ham_corr0, atol=self._w90zero, rtol=1.e-9):
|
||||
raise ValueError("H(R=0) matrix is not Hermitian!")
|
||||
|
||||
# find rot_mat symmetries by diagonalising the on-site Hamiltonian of the first spin
|
||||
if isp == 0:
|
||||
use_rotations, rot_mat = self.find_rot_mat(n_corr_shells, corr_shells, shells_map, ham_corr0)
|
||||
else:
|
||||
# consistency check
|
||||
use_rotations_, rot_mat_ = self.find_rot_mat(n_corr_shells, corr_shells, shells_map, ham_corr0)
|
||||
if (use_rotations and not use_rotations_):
|
||||
mpi.report("Rotations cannot be used for spin component n. %d" % isp)
|
||||
for icrsh in range(n_corr_shells):
|
||||
if not numpy.allclose(rot_mat_[icrsh], rot_mat[icrsh], atol=self._w90zero, rtol=1.e-15):
|
||||
mpi.report("Rotations for spin component n. %d do not match!" % isp)
|
||||
# end loop on isp
|
||||
|
||||
mpi.report("The k-point grid has dimensions: %d, %d, %d" % tuple(nki))
|
||||
# if calculations are spin-polarized, then renormalize k-point weights
|
||||
if SP == 1:
|
||||
bz_weights = 0.5 * bz_weights
|
||||
|
||||
# Third, compute the hoppings in reciprocal space
|
||||
hopping = numpy.zeros([self.n_k, n_spin, numpy.max(n_orbitals), numpy.max(n_orbitals)], numpy.complex_)
|
||||
for isp in range(n_spin):
|
||||
# make Fourier transform H(R) -> H(k) : it can be done one spin at a time
|
||||
hamk = self.fourier_ham(self.nwfs, hamr_full[isp])
|
||||
# copy the H(k) in the right place of hoppings... is there a better way to do this??
|
||||
for ik in range(self.n_k):
|
||||
#hopping[ik,isp,:,:] = deepcopy(hamk[ik][:,:])*energy_unit
|
||||
hopping[ik, isp, :, :] = hamk[ik][:, :] * energy_unit
|
||||
|
||||
# Then, initialise the projectors
|
||||
k_dep_projection = 0 # we always have the same number of WFs at each k-point
|
||||
proj_mat = numpy.zeros([self.n_k, n_spin, n_corr_shells, max(
|
||||
[crsh['dim'] for crsh in corr_shells]), numpy.max(n_orbitals)], numpy.complex_)
|
||||
iorb = 0
|
||||
# Projectors simply consist in identity matrix blocks selecting those MLWFs that
|
||||
# correspond to the specific correlated shell indexed by icrsh.
|
||||
# NOTE: we assume that the correlated orbitals appear at the beginning of the H(R)
|
||||
# file and that the ordering of MLWFs matches the corr_shell info from the input.
|
||||
for icrsh in range(n_corr_shells):
|
||||
norb = corr_shells[icrsh]['dim']
|
||||
proj_mat[:, :, icrsh, 0:norb, iorb:iorb +
|
||||
norb] = numpy.identity(norb, numpy.complex_)
|
||||
iorb += norb
|
||||
|
||||
# Finally, save all required data into the HDF archive:
|
||||
ar = HDFArchive(self.hdf_file, 'a')
|
||||
if not (self.dft_subgrp in ar):
|
||||
ar.create_group(self.dft_subgrp)
|
||||
# The subgroup containing the data. If it does not exist, it is created. If it exists, the data is overwritten!
|
||||
things_to_save = ['energy_unit', 'n_k', 'k_dep_projection', 'SP', 'SO', 'charge_below', 'density_required',
|
||||
'symm_op', 'n_shells', 'shells', 'n_corr_shells', 'corr_shells', 'use_rotations', 'rot_mat',
|
||||
'rot_mat_time_inv', 'n_reps', 'dim_reps', 'T', 'n_orbitals', 'proj_mat', 'bz_weights', 'hopping',
|
||||
'n_inequiv_shells', 'corr_to_inequiv', 'inequiv_to_corr']
|
||||
for it in things_to_save:
|
||||
ar[self.dft_subgrp][it] = locals()[it]
|
||||
del ar
|
||||
|
||||
def read_wannier90hr(self, hr_filename="wannier_hr.dat"):
|
||||
"""
|
||||
Method for reading the seedname_hr.dat file produced by Wannier90 (http://wannier.org)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
hr_filename : string
|
||||
full name of the H(R) file produced by Wannier90 (usually seedname_hr.dat)
|
||||
|
||||
Returns
|
||||
-------
|
||||
nrpt : integer
|
||||
number of R vectors found in the file
|
||||
rvec_idx : numpy.array of integers
|
||||
Miller indices of the R vectors
|
||||
rvec_deg : numpy.array of floats
|
||||
weight of the R vectors
|
||||
num_wf : integer
|
||||
number of Wannier functions found
|
||||
h_of_r : list of numpy.array
|
||||
<w_i|H(R)|w_j> = Hamilonian matrix elements in the Wannier basis
|
||||
|
||||
"""
|
||||
|
||||
# Read only from the master node
|
||||
if not (mpi.is_master_node()):
|
||||
return
|
||||
|
||||
try:
|
||||
with open(hr_filename, "r") as hr_filedesc:
|
||||
hr_data = hr_filedesc.readlines()
|
||||
hr_filedesc.close()
|
||||
except IOError:
|
||||
mpi.report("The file %s could not be read!" % hr_filename)
|
||||
|
||||
mpi.report("Reading %s..." % hr_filename + hr_data[0])
|
||||
|
||||
try:
|
||||
# reads number of Wannier functions per spin
|
||||
num_wf = int(hr_data[1])
|
||||
nrpt = int(hr_data[2])
|
||||
except ValueError:
|
||||
mpi.report("Could not read number of WFs or R vectors")
|
||||
|
||||
# allocate arrays to save the R vector indexes and degeneracies and the Hamiltonian
|
||||
rvec_idx = numpy.zeros((nrpt, 3), dtype=int)
|
||||
rvec_deg = numpy.zeros(nrpt, dtype=int)
|
||||
h_of_r = [numpy.zeros((num_wf, num_wf), dtype=numpy.complex_)
|
||||
for n in range(nrpt)]
|
||||
|
||||
# variable currpos points to the current line in the file
|
||||
currpos = 2
|
||||
try:
|
||||
ir = 0
|
||||
# read the degeneracy of the R vectors (needed for the Fourier transform)
|
||||
while ir < nrpt:
|
||||
currpos += 1
|
||||
for x in hr_data[currpos].split():
|
||||
if ir >= nrpt:
|
||||
raise IndexError("wrong number of R vectors??")
|
||||
rvec_deg[ir] = int(x)
|
||||
ir += 1
|
||||
# for each direct lattice vector R read the block of the
|
||||
# Hamiltonian H(R)
|
||||
for ir, jj, ii in product(range(nrpt), range(num_wf), range(num_wf)):
|
||||
# advance one line, split the line into tokens
|
||||
currpos += 1
|
||||
cline = hr_data[currpos].split()
|
||||
# check if the orbital indexes in the file make sense
|
||||
if int(cline[3]) != ii + 1 or int(cline[4]) != jj + 1:
|
||||
mpi.report(
|
||||
"Inconsistent indices at %s%s of R n. %s" % (ii, jj, ir))
|
||||
rcurr = numpy.array(
|
||||
[int(cline[0]), int(cline[1]), int(cline[2])])
|
||||
if ii == 0 and jj == 0:
|
||||
rvec_idx[ir] = rcurr
|
||||
rprec = rcurr
|
||||
else:
|
||||
# check if the vector indices are consistent
|
||||
if not numpy.array_equal(rcurr, rprec):
|
||||
mpi.report(
|
||||
"Inconsistent indices for R vector n. %s" % ir)
|
||||
|
||||
# fill h_of_r with the matrix elements of the Hamiltonian
|
||||
h_of_r[ir][ii, jj] = complex(float(cline[5]), float(cline[6]))
|
||||
|
||||
except ValueError:
|
||||
mpi.report("Wrong data or structure in file %s" % hr_filename)
|
||||
|
||||
# return the data into variables
|
||||
return nrpt, rvec_idx, rvec_deg, num_wf, h_of_r
|
||||
|
||||
def find_rot_mat(self, n_sh, sh_lst, sh_map, ham0):
|
||||
"""
|
||||
Method for finding the matrices that bring from local to global coordinate systems
|
||||
(and viceversa), based on the eigenvalues of H(R=0)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_sh : integer
|
||||
number of shells
|
||||
sh_lst : list of shells-type dictionaries
|
||||
contains the shells (could be correlated or not)
|
||||
sh_map : list of integers
|
||||
mapping between shells
|
||||
ham0 : numpy.array of floats
|
||||
local Hamiltonian matrix elements
|
||||
|
||||
Returns
|
||||
-------
|
||||
istatus : integer
|
||||
if 0, something failed in the construction of the matrices
|
||||
rot_mat : list of numpy.array
|
||||
rotation matrix for each of the shell
|
||||
|
||||
"""
|
||||
|
||||
# initialize the rotation matrices to identities
|
||||
rot_mat = [numpy.identity(sh_lst[ish]['dim'], dtype=complex)
|
||||
for ish in range(n_sh)]
|
||||
istatus = 0
|
||||
|
||||
hs = ham0.shape
|
||||
if hs[0] != hs[1] or hs[0] != sum([sh['dim'] for sh in sh_lst]):
|
||||
mpi.report(
|
||||
"find_rot_mat: wrong block structure of input Hamiltonian!")
|
||||
istatus = 0
|
||||
# this error will lead into troubles later... early return
|
||||
return istatus, rot_mat
|
||||
|
||||
# TODO: better handling of degenerate eigenvalue case
|
||||
eigval_lst = []
|
||||
eigvec_lst = []
|
||||
iwf = 0
|
||||
# loop over shells
|
||||
for ish in range(n_sh):
|
||||
# nw = number of orbitals in this shell
|
||||
nw = sh_lst[ish]["dim"]
|
||||
# diagonalize the sub-block of H(0) corresponding to this shell
|
||||
eigval, eigvec = numpy.linalg.eigh(
|
||||
ham0[iwf:iwf + nw, iwf:iwf + nw])
|
||||
# find the indices sorting the eigenvalues in ascending order
|
||||
eigsrt = eigval[0:nw].argsort()
|
||||
# order eigenvalues and eigenvectors and save in a list
|
||||
eigval_lst.append(eigval[eigsrt])
|
||||
eigvec_lst.append(eigvec[eigsrt])
|
||||
iwf += nw
|
||||
# TODO: better handling of degenerate eigenvalue case
|
||||
if sh_map[ish] != ish: # issue warning only when there are equivalent shells
|
||||
for i in range(nw):
|
||||
for j in range(i + 1, nw):
|
||||
if (abs(eigval[j] - eigval[i]) < self._w90zero):
|
||||
mpi.report("WARNING: degenerate eigenvalue of H(0) detected for shell %d: " % (ish) +
|
||||
"global-to-local transformation might not work!")
|
||||
|
||||
for ish in range(n_sh):
|
||||
try:
|
||||
# build rotation matrices by combining the unitary
|
||||
# transformations that diagonalize H(0)
|
||||
rot_mat[ish] = numpy.dot(eigvec_lst[ish], eigvec_lst[
|
||||
sh_map[ish]].conjugate().transpose())
|
||||
except ValueError:
|
||||
mpi.report(
|
||||
"Global-to-local rotation matrices cannot be constructed!")
|
||||
|
||||
istatus = 1
|
||||
# check that eigenvalues are the same (within accuracy) for
|
||||
# equivalent shells
|
||||
if not numpy.allclose(eigval_lst[ish], eigval_lst[sh_map[ish]], atol=self._w90zero, rtol=1.e-15):
|
||||
mpi.report(
|
||||
"ERROR: eigenvalue mismatch between equivalent shells! %d" % ish)
|
||||
eigval_diff = eigval_lst[ish] - eigval_lst[sh_map[ish]]
|
||||
mpi.report("Eigenvalue difference: " + format(eigval_diff))
|
||||
istatus = 0
|
||||
|
||||
# TODO: add additional consistency check on rot_mat matrices?
|
||||
|
||||
return istatus, rot_mat
|
||||
|
||||
def kmesh_build(self, msize=None, mmode=0):
|
||||
"""
|
||||
Method for the generation of the k-point mesh.
|
||||
Right now it only supports the option for generating a full grid containing k=0,0,0.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
msize : list of 3 integers
|
||||
the dimensions of the mesh
|
||||
mmode : integer
|
||||
mesh generation mode (right now, only full grid available)
|
||||
|
||||
Returns
|
||||
-------
|
||||
nkpt : integer
|
||||
total number of k-points in the mesh
|
||||
k_mesh : numpy.array[nkpt,3] of floats
|
||||
the coordinates of all k-points
|
||||
wk : numpy.array[nkpt] of floats
|
||||
the weight of each k-point
|
||||
|
||||
"""
|
||||
|
||||
if mmode != 0:
|
||||
raise ValueError("Mesh generation mode not supported: %s" % mmode)
|
||||
|
||||
# a regular mesh including Gamma point
|
||||
# total number of k-points
|
||||
nkpt = msize[0] * msize[1] * msize[2]
|
||||
kmesh = numpy.zeros((nkpt, 3), dtype=float)
|
||||
ii = 0
|
||||
for ix, iy, iz in product(range(msize[0]), range(msize[1]), range(msize[2])):
|
||||
kmesh[ii, :] = [float(ix) / msize[0], float(iy) / msize[1], float(iz) / msize[2]]
|
||||
ii += 1
|
||||
# weight is equal for all k-points because wannier90 uses uniform grid on whole BZ
|
||||
# (normalization is always 1 and takes into account spin degeneracy)
|
||||
wk = numpy.ones([nkpt], dtype=float) / float(nkpt)
|
||||
|
||||
return nkpt, kmesh, wk
|
||||
|
||||
def fourier_ham(self, norb, h_of_r):
|
||||
"""
|
||||
Method for obtaining H(k) from H(R) via Fourier transform
|
||||
The R vectors and k-point mesh are read from global module variables
|
||||
|
||||
Parameters
|
||||
----------
|
||||
norb : integer
|
||||
number of orbitals
|
||||
h_of_r : list of numpy.array[norb,norb]
|
||||
Hamiltonian H(R) in Wannier basis
|
||||
|
||||
Returns
|
||||
-------
|
||||
h_of_k : list of numpy.array[norb,norb]
|
||||
transformed Hamiltonian H(k) in Wannier basis
|
||||
|
||||
"""
|
||||
|
||||
twopi = 2 * numpy.pi
|
||||
h_of_k = [numpy.zeros((norb, norb), dtype=numpy.complex_) for ik in range(self.n_k)]
|
||||
ridx = numpy.array(range(self.nrpt))
|
||||
for ik, ir in product(range(self.n_k), ridx):
|
||||
rdotk = twopi * numpy.dot(self.k_mesh[ik], self.rvec[ir])
|
||||
factor = (math.cos(rdotk) + 1j * math.sin(rdotk)) / float(self.rdeg[ir])
|
||||
h_of_k[ik][:, :] += factor * h_of_r[ir][:, :]
|
||||
|
||||
return h_of_k
|
@ -448,7 +448,6 @@ class SumkDFT:
|
||||
broadening = 0.01
|
||||
else: # broadening = 2 * \Delta omega, where \Delta omega is the spacing of omega points
|
||||
broadening = 2.0 * ( (mesh[1]-mesh[0])/(mesh[2]-1) )
|
||||
n_iw = 1025 # Default number of Matsubara frequencies
|
||||
|
||||
# Are we including Sigma?
|
||||
if with_Sigma:
|
||||
@ -457,10 +456,16 @@ class SumkDFT:
|
||||
if with_dc: sigma_minus_dc = self.add_dc(iw_or_w)
|
||||
if iw_or_w == "iw":
|
||||
beta = Sigma_imp[0].mesh.beta # override beta if Sigma_iw is present
|
||||
n_iw = len(Sigma_imp[0].mesh)
|
||||
mesh = Sigma_imp[0].mesh
|
||||
elif iw_or_w == "w":
|
||||
mesh = Sigma_imp[0].mesh
|
||||
else:
|
||||
if (iw_or_w == "w") and (mesh is None):
|
||||
raise ValueError, "lattice_gf: Give the mesh=(om_min,om_max,n_points) for the lattice GfReFreq."
|
||||
if iw_or_w == "iw":
|
||||
if beta is None: raise ValueError, "lattice_gf: Give the beta for the lattice GfReFreq."
|
||||
mesh = MeshImFreq(beta=beta, S='Fermion', n_max=1025) # Default number of Matsubara frequencies
|
||||
elif iw_or_w == "w":
|
||||
if mesh is None: raise ValueError, "lattice_gf: Give the mesh=(om_min,om_max,n_points) for the lattice GfReFreq."
|
||||
mesh = MeshReFreq(mesh[0],mesh[1],mesh[2])
|
||||
|
||||
# Check if G_latt is present
|
||||
set_up_G_latt = False # Assume not
|
||||
@ -479,12 +484,9 @@ class SumkDFT:
|
||||
gf_struct = [ (spn[isp], block_structure[isp]) for isp in range(self.n_spin_blocks[self.SO]) ]
|
||||
block_ind_list = [block for block,inner in gf_struct]
|
||||
if iw_or_w == "iw":
|
||||
glist = lambda : [ GfImFreq(indices=inner,beta=beta,n_points=n_iw) for block,inner in gf_struct]
|
||||
glist = lambda : [ GfImFreq(indices=inner,mesh=mesh) for block,inner in gf_struct ]
|
||||
elif iw_or_w == "w":
|
||||
if with_Sigma:
|
||||
glist = lambda : [ GfReFreq(indices=inner,mesh=Sigma_imp[0].mesh) for block,inner in gf_struct]
|
||||
else:
|
||||
glist = lambda : [ GfReFreq(indices=inner,window=(mesh[0],mesh[1]),n_points=mesh[2]) for block,inner in gf_struct]
|
||||
glist = lambda : [ GfReFreq(indices=inner,mesh=mesh) for block,inner in gf_struct ]
|
||||
G_latt = BlockGf(name_list = block_ind_list, block_list = glist(), make_copies = False)
|
||||
G_latt.zero()
|
||||
|
||||
@ -510,6 +512,8 @@ class SumkDFT:
|
||||
|
||||
return G_latt
|
||||
|
||||
def set_Sigma(self,Sigma_imp):
|
||||
self.put_Sigma(Sigma_imp)
|
||||
|
||||
def put_Sigma(self, Sigma_imp):
|
||||
r"""
|
||||
@ -557,7 +561,6 @@ class SumkDFT:
|
||||
for icrsh in range(self.n_corr_shells):
|
||||
for bname,gf in SK_Sigma_imp[icrsh]: gf << self.rotloc(icrsh,gf,direction='toGlobal')
|
||||
|
||||
|
||||
def extract_G_loc(self, mu=None, with_Sigma=True, with_dc=True):
|
||||
r"""
|
||||
Extracts the local downfolded Green function by the Brillouin-zone integration of the lattice Green's function.
|
||||
|
@ -47,6 +47,7 @@ class SumkDFTTools(SumkDFT):
|
||||
misc_data=misc_data)
|
||||
|
||||
|
||||
# Uses .data of only GfReFreq objects.
|
||||
def dos_wannier_basis(self, mu=None, broadening=None, mesh=None, with_Sigma=True, with_dc=True, save_to_file=True):
|
||||
"""
|
||||
Calculates the density of states in the basis of the Wannier functions.
|
||||
@ -163,6 +164,7 @@ class SumkDFTTools(SumkDFT):
|
||||
return DOS, DOSproj, DOSproj_orb
|
||||
|
||||
|
||||
# Uses .data of only GfReFreq objects.
|
||||
def dos_parproj_basis(self, mu=None, broadening=None, mesh=None, with_Sigma=True, with_dc=True, save_to_file=True):
|
||||
"""
|
||||
Calculates the orbitally-resolved DOS.
|
||||
@ -290,6 +292,7 @@ class SumkDFTTools(SumkDFT):
|
||||
return DOS, DOSproj, DOSproj_orb
|
||||
|
||||
|
||||
# Uses .data of only GfReFreq objects.
|
||||
def spaghettis(self,broadening=None,plot_shift=0.0,plot_range=None,ishell=None,mu=None,save_to_file='Akw_'):
|
||||
"""
|
||||
Calculates the correlated band structure using a real-frequency self energy.
|
||||
@ -377,6 +380,11 @@ class SumkDFTTools(SumkDFT):
|
||||
for sp in spn:
|
||||
Akw[sp][ish,ik,iom] = G_loc[sp].data[iom,ish,ish].imag/(-1.0*numpy.pi)
|
||||
|
||||
# Collect data from mpi
|
||||
for sp in spn:
|
||||
Akw[sp] = mpi.all_reduce(mpi.world, Akw[sp], lambda x,y : x+y)
|
||||
mpi.barrier()
|
||||
|
||||
if save_to_file and mpi.is_master_node():
|
||||
if ishell is None:
|
||||
for sp in spn: # loop over GF blocs:
|
||||
@ -394,7 +402,7 @@ class SumkDFTTools(SumkDFT):
|
||||
else: # ishell is not None
|
||||
for sp in spn:
|
||||
for ish in range(self.shells[ishell]['dim']):
|
||||
f = open(save_to_file+sp+'_proj'+str(ish)+'.dat','w') # Open file for storage:
|
||||
f = open(save_to_file+str(ishell)+'_'+sp+'_proj'+str(ish)+'.dat','w') # Open file for storage:
|
||||
for ik in range(self.n_k):
|
||||
for iom in range(n_om):
|
||||
if (mesh[iom] > om_minplot) and (mesh[iom] < om_maxplot):
|
||||
@ -565,6 +573,7 @@ class SumkDFTTools(SumkDFT):
|
||||
return vol_c, vol_p
|
||||
|
||||
|
||||
# Uses .data of only GfReFreq objects.
|
||||
def transport_distribution(self, beta, directions=['xx'], energy_window=None, Om_mesh=[0.0], with_Sigma=False, n_om=None, broadening=0.0):
|
||||
r"""
|
||||
Calculates the transport distribution
|
||||
|
30
python/version.py.in
Normal file
30
python/version.py.in
Normal file
@ -0,0 +1,30 @@
|
||||
################################################################################
|
||||
#
|
||||
# TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
#
|
||||
# Copyright (C) 2011 by M. Aichhorn, L. Pourovskii, V. Vildosola
|
||||
#
|
||||
# TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
version = "@DFT_TOOLS_VERSION@"
|
||||
triqs_hash = "@TRIQS_GIT_HASH@"
|
||||
cthyb_hash = "@CTHYB_GIT_HASH@"
|
||||
|
||||
def show_version():
|
||||
print "\nYou are using the dft_tools version %s\n"%version
|
||||
|
||||
def show_git_hash():
|
||||
print "\nYou are using the dft_tools git hash %s based on triqs git hash %s\n"%(cthyb_hash, triqs_hash)
|
@ -1,12 +1,18 @@
|
||||
# load triqs helper to set up tests
|
||||
find_package(TriqsTest)
|
||||
|
||||
FILE(COPY SrVO3.h5 SrVO3_Sigma.h5 SrVO3.pmat SrVO3.struct SrVO3.outputs SrVO3.oubwin SrVO3.ctqmcout SrVO3.symqmc SrVO3.sympar SrVO3.parproj hk_convert_hamiltonian.hk DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
#triqs_add_test_hdf(wien2k_convert " -p 1.e-6" )
|
||||
#triqs_add_test_hdf(hk_convert " -p 1.e-6" )
|
||||
#triqs_add_test_hdf(sumkdft_basic " -d 1.e-6" )
|
||||
#triqs_add_test_hdf(srvo3_Gloc " -d 1.e-6" )
|
||||
#triqs_add_test_hdf(srvo3_transp " -d 1.e-6" )
|
||||
#triqs_add_test_hdf(sigma_from_file " -d 1.e-6" )
|
||||
# Copy h5 files to binary dir
|
||||
FILE(GLOB all_h5_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h5)
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${all_h5_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
# Copy other files
|
||||
FILE(COPY SrVO3.pmat SrVO3.struct SrVO3.outputs SrVO3.oubwin SrVO3.ctqmcout SrVO3.symqmc SrVO3.sympar SrVO3.parproj hk_convert_hamiltonian.hk LaVO3-Pnma_hr.dat LaVO3-Pnma.inp DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
triqs_add_python_test(wien2k_convert)
|
||||
triqs_add_python_test(hk_convert)
|
||||
triqs_add_python_test(w90_convert)
|
||||
triqs_add_python_test(sumkdft_basic)
|
||||
triqs_add_python_test(srvo3_Gloc)
|
||||
triqs_add_python_test(srvo3_transp)
|
||||
triqs_add_python_test(sigma_from_file)
|
||||
|
||||
add_subdirectory(plovasp)
|
||||
|
7
test/LaVO3-Pnma.inp
Normal file
7
test/LaVO3-Pnma.inp
Normal file
@ -0,0 +1,7 @@
|
||||
0 3 2 3
|
||||
8.0
|
||||
4
|
||||
0 0 2 3 0 0
|
||||
1 0 2 3 0 0
|
||||
2 0 2 3 0 0
|
||||
3 0 2 3 0 0
|
3893
test/LaVO3-Pnma_hr.dat
Normal file
3893
test/LaVO3-Pnma_hr.dat
Normal file
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,12 @@
|
||||
|
||||
from pytriqs.applications.dft.converters import *
|
||||
from pytriqs.archive import *
|
||||
from pytriqs.utility.h5diff import h5diff
|
||||
import pytriqs.utility.mpi as mpi
|
||||
|
||||
Converter = HkConverter(filename='hk_convert_hamiltonian.hk',hdf_filename='hk_convert.output.h5')
|
||||
Converter = HkConverter(filename='hk_convert_hamiltonian.hk',hdf_filename='hk_convert.out.h5')
|
||||
|
||||
Converter.convert_dft_input()
|
||||
|
||||
if mpi.is_master_node():
|
||||
h5diff("hk_convert.out.h5","hk_convert.ref.h5")
|
||||
|
@ -1,7 +1,29 @@
|
||||
################################################################################
|
||||
#
|
||||
# TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
#
|
||||
# Copyright (C) 2011 by M. Aichhorn, L. Pourovskii, V. Vildosola
|
||||
#
|
||||
# TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
from pytriqs.archive import *
|
||||
from pytriqs.gf.local import *
|
||||
from pytriqs.gf.local.tools import *
|
||||
from pytriqs.applications.dft.sumk_dft_tools import *
|
||||
from pytriqs.utility.comparison_tests import *
|
||||
import numpy as np
|
||||
|
||||
# Read self energy from hdf file
|
||||
@ -24,9 +46,9 @@ a_list = [a for a,al in SK.gf_struct_solver[0].iteritems()]
|
||||
g_list = [read_gf_from_txt([['Sigma_' + a + '.dat']], a) for a in a_list]
|
||||
Sigma_txt = BlockGf(name_list = a_list, block_list = g_list, make_copies=False)
|
||||
|
||||
SK.put_Sigma(Sigma_imp = [Sigma_txt])
|
||||
SK.set_Sigma([Sigma_txt])
|
||||
|
||||
SK.hdf_file = 'sigma_from_file.output.h5'
|
||||
SK.hdf_file = 'sigma_from_file.out.h5'
|
||||
SK.save(['Sigma_imp_w'])
|
||||
|
||||
if ((Sigma_txt - Sigma_hdf).real < 1e-6) & ((Sigma_txt - Sigma_hdf).imag < 1e-6):
|
||||
|
@ -24,6 +24,8 @@ from pytriqs.gf.local import *
|
||||
from pytriqs.applications.dft.sumk_dft import *
|
||||
from pytriqs.applications.dft.converters.wien2k_converter import *
|
||||
from pytriqs.operators.util import set_operator_structure
|
||||
from pytriqs.utility.comparison_tests import *
|
||||
from pytriqs.utility.h5diff import h5diff
|
||||
|
||||
# Basic input parameters
|
||||
beta = 40
|
||||
@ -41,9 +43,12 @@ gf_struct = set_operator_structure(spin_names,orb_names,orb_hybridized)
|
||||
glist = [ GfImFreq(indices=inner,beta=beta) for block,inner in gf_struct.iteritems()]
|
||||
Sigma_iw = BlockGf(name_list = gf_struct.keys(), block_list = glist, make_copies = False)
|
||||
|
||||
SK.put_Sigma([Sigma_iw])
|
||||
Gloc=SK.extract_G_loc()
|
||||
SK.set_Sigma([Sigma_iw])
|
||||
Gloc = SK.extract_G_loc()
|
||||
|
||||
ar = HDFArchive('srvo3_Gloc.output.h5','w')
|
||||
ar['Gloc'] = Gloc[0]
|
||||
del ar
|
||||
if mpi.is_master_node():
|
||||
with HDFArchive('srvo3_Gloc.out.h5','w') as ar:
|
||||
ar['Gloc'] = Gloc[0]
|
||||
|
||||
if mpi.is_master_node():
|
||||
h5diff("srvo3_Gloc.out.h5","srvo3_Gloc.ref.h5")
|
||||
|
@ -23,6 +23,8 @@ from numpy import *
|
||||
from pytriqs.applications.dft.converters.wien2k_converter import *
|
||||
from pytriqs.applications.dft.sumk_dft import *
|
||||
from pytriqs.applications.dft.sumk_dft_tools import *
|
||||
from pytriqs.utility.comparison_tests import *
|
||||
from pytriqs.utility.h5diff import h5diff
|
||||
|
||||
beta = 40
|
||||
|
||||
@ -34,7 +36,7 @@ SK = SumkDFTTools(hdf_file='SrVO3.h5', use_dft_blocks=True)
|
||||
|
||||
ar = HDFArchive('SrVO3_Sigma.h5', 'a')
|
||||
Sigma = ar['dmft_transp_input']['Sigma_w']
|
||||
SK.put_Sigma(Sigma_imp = [Sigma])
|
||||
SK.set_Sigma([Sigma])
|
||||
SK.chemical_potential = ar['dmft_transp_input']['chemical_potential']
|
||||
SK.dc_imp = ar['dmft_transp_input']['dc_imp']
|
||||
del ar
|
||||
@ -43,6 +45,8 @@ SK.transport_distribution(directions=['xx'], broadening=0.0, energy_window=[-0.3
|
||||
#SK.save(['Gamma_w','Om_meshr','omega','directions'])
|
||||
#SK.load(['Gamma_w','Om_meshr','omega','directions'])
|
||||
SK.conductivity_and_seebeck(beta=beta)
|
||||
SK.hdf_file = 'srvo3_transp.output.h5'
|
||||
SK.hdf_file = 'srvo3_transp.out.h5'
|
||||
SK.save(['seebeck','optic_cond'])
|
||||
|
||||
if mpi.is_master_node():
|
||||
h5diff("srvo3_transp.out.h5","srvo3_transp.ref.h5")
|
||||
|
@ -22,14 +22,18 @@
|
||||
|
||||
from pytriqs.archive import *
|
||||
from pytriqs.applications.dft.sumk_dft_tools import SumkDFTTools
|
||||
|
||||
import pytriqs.utility.mpi as mpi
|
||||
from pytriqs.utility.comparison_tests import *
|
||||
from pytriqs.utility.h5diff import h5diff
|
||||
|
||||
SK = SumkDFTTools(hdf_file = 'SrVO3.h5')
|
||||
|
||||
dm = SK.density_matrix(method = 'using_gf', beta = 40)
|
||||
dm_pc = SK.partial_charges(beta=40,with_Sigma=False,with_dc=False)
|
||||
|
||||
ar = HDFArchive('sumkdft_basic.output.h5','w')
|
||||
ar['dm'] = dm
|
||||
ar['dm_pc'] = dm_pc
|
||||
del ar
|
||||
with HDFArchive('sumkdft_basic.out.h5','w') as ar:
|
||||
ar['dm'] = dm
|
||||
ar['dm_pc'] = dm_pc
|
||||
|
||||
if mpi.is_master_node():
|
||||
h5diff('sumkdft_basic.out.h5','sumkdft_basic.ref.h5')
|
||||
|
34
test/w90_convert.py
Normal file
34
test/w90_convert.py
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
#
|
||||
# Copyright (C) 2011 by M. Aichhorn, L. Pourovskii, V. Vildosola
|
||||
#
|
||||
# TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
|
||||
from pytriqs.applications.dft.converters import *
|
||||
from pytriqs.archive import *
|
||||
from pytriqs.utility.h5diff import h5diff
|
||||
import pytriqs.utility.mpi as mpi
|
||||
|
||||
Converter = Wannier90Converter(seedname='LaVO3-Pnma',hdf_filename='w90_convert.out.h5')
|
||||
|
||||
Converter.convert_dft_input()
|
||||
|
||||
if mpi.is_master_node():
|
||||
h5diff("w90_convert.out.h5","w90_convert.ref.h5")
|
BIN
test/w90_convert.ref.h5
Normal file
BIN
test/w90_convert.ref.h5
Normal file
Binary file not shown.
@ -22,13 +22,15 @@
|
||||
|
||||
from pytriqs.archive import *
|
||||
from pytriqs.applications.dft.converters import Wien2kConverter
|
||||
|
||||
from pytriqs.utility.comparison_tests import *
|
||||
from pytriqs.utility.h5diff import h5diff
|
||||
import pytriqs.utility.mpi as mpi
|
||||
|
||||
Converter = Wien2kConverter(filename='SrVO3')
|
||||
Converter.hdf_file = 'wien2k_convert.output.h5'
|
||||
Converter.hdf_file = 'wien2k_convert.out.h5'
|
||||
Converter.convert_dft_input()
|
||||
|
||||
Converter.convert_parproj_input()
|
||||
|
||||
|
||||
|
||||
if mpi.is_master_node():
|
||||
h5diff('wien2k_convert.out.h5','wien2k_convert.ref.h5')
|
||||
|
Loading…
Reference in New Issue
Block a user