Automatic basis rotations in DFT+DMFT

When performing calculations with off-diagonal terms in the hybridisation function or in the local Hamiltonian, one is often limited by the fermionic sign-problem slowing down the QMC calculations significantly. This can occur for instance if the crystal shows locally rotated or distorted cages, or when spin-orbit coupling is included. The examples for this are included in the Tutorials of this documentation.

However, as the fermonic sign in the QMC calculation is no physical observable, one can try to improve the calculation by rotating to another basis. While this basis can in principle be chosen arbitrarily, two choices which have shown good results; name the basis sets that diagonalize the local Hamiltonian or the local density matrix of the system.

As outlined in section Manipulating the Green’s functions block structure, the BlockStructure includes all necessary functionalities. While it is possible to manually transform each Green’s functions and self energies between the sumk and the solver basis, this leads to cumbersum code and is discouraged. Instead, in order to facilitate the block-structure manipulations for an actual DFT+DMFT calculation, some of the necessary steps are automatically included automatically. As soon as the transformation matrix is stored in the BlockStructure, the transformation is automatically performed when using SumkDFT’s extract_G_loc(), put_Sigma(), and calc_dc() (see below).

Setting up the initial solver structure from DFT

Before the actual calculation one has to specify the solver basis structure, in which the impurity problem will be tackled. The different available approximation were introduced in section Manipulating the Green’s functions block structure. An important feature of DFTTools is that there is an automatic way to determine the entries of the Green’s function matrix that are zero by symmetry, when initialising the class:

from triqs_dft_tools.sumk_dft import *
SK = SumkDFT(hdf_file,use_dft_blocks='True')

The flag use_dft_blocks=True analysis the local density matrix, determines the zero entries, and sets up a minimal solver structure. Alternatively, this step can be achieved by (see the reference manual for options):

SK.analyse_block_structure()

Finding the transformation matrix

The SumkDFT class offers a method that can determine transformation matrices to certain new basis. It is called as follows:

SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal')

Possible option for prop_to_be_diagonal are eal (diagonalises the local hamiltonian) or dm (diagonalises the local density matrix). This routine stores the transformation matrix in the SK.block_structure class, such that it can be used to rotate the basis.

Automatic transformation during the DMFT loop

During a DMFT loop one is often switching back and forth between the unrotated basis (Sumk-Space) and the rotated basis that is used by the QMC Solver. Once the SK.block_structure.transformation property is set as shown above, this is done automatically, meaning that SumkDFT’s extract_G_loc(), put_Sigma(), and calc_dc() are doing the transformations by default:

for it in range(iteration_offset, iteration_offset + n_iterations):
    # every GF is in solver space here
    S.G0_iw << inverse(S.Sigma_iw + inverse(S.G_iw))

    # solve the impurity in solver space -> hopefully better sign
    S.solve(h_int = H, **p)

    # calc_dc(..., transform = True) by default
    SK.calc_dc(S.G_iw.density(), U_interact=U, J_hund=J, orb=0, use_dc_formula=DC_type)

    # put_Sigma(..., transform_to_sumk_blocks = True) by default
    SK.put_Sigma([S.Sigma_iw])

    SK.calc_mu()

    # extract_G_loc(..., transform_to_solver_blocks = True) by default
    S.G_iw << SK.extract_G_loc()[0]

Warning

Before doing the DMFT self-consistency loop, one must not forget to also transform the interaction Hamiltonian to the diagonal basis! This can be also be done with a method of the BlockStructure class, namely the convert_operator() method. Having set up a Hamiltonian in the sumk structure, it can easily be transformed to the solver structure (including rotations of basis, picking of orbitals, making matrices diagonal, etc) by:

H_solver = SK.block_structure.convert_operator(H_sumk)

We refer to the tutorials on how to set up the Hamiltonian H_sumk in selected cases. Note that this transformation might generally lead to complex values in the interaction Hamiltonian. Unless you know better and can make everything real, you should take care of using the correct version of the TRIQS CTQMC solver.