Source code for dmft_tools.interaction_hamiltonian

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
################################################################################
#
# solid_dmft - A versatile python wrapper to perform DFT+DMFT calculations
#              utilizing the TRIQS software library
#
# Copyright (C) 2018-2020, ETH Zurich
# Copyright (C) 2021, The Simons Foundation
#      authors: A. Hampel, M. Merkel, and S. Beck
#
# solid_dmft 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.
#
# solid_dmft 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
# solid_dmft (in the file COPYING.txt in this directory). If not, see
# <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Contains all functions related to constructing the interaction Hamiltonian.
"""

# system
import os
import numpy as np
from itertools import product

# triqs
from h5 import HDFArchive
import triqs.utility.mpi as mpi
from triqs.gf import make_gf_imfreq
from triqs.operators import util, n, c, c_dag, Operator
from solid_dmft.dmft_tools import common


try:
    import forktps as ftps
except ImportError:
    pass

[docs] def _load_crpa_interaction_matrix(sum_k, general_params, gw_params, filename='UIJKL'): """ Loads dynamic interaction data to use as an interaction Hamiltonian. """ def _round_to_int(data): return (np.array(data) + .5).astype(int) if gw_params['code'] == 'Vasp': # Loads data from VASP cRPA file print('Loading Vasp cRPA matrix from file: '+str(filename)) data = np.loadtxt(filename, unpack=True) u_matrix_four_indices = np.zeros(_round_to_int(np.max(data[:4], axis=1)), dtype=complex) for entry in data.T: # VASP switches the order of the indices, ijkl -> ikjl i, k, j, l = _round_to_int(entry[:4])-1 u_matrix_four_indices[i, j, k, l] = entry[4] + 1j * entry[5] # Slices up the four index U-matrix, separating shells u_matrix_four_indices_per_shell = [None] * sum_k.n_inequiv_shells first_index_shell = 0 for ish in range(sum_k.n_corr_shells): icrsh = sum_k.corr_to_inequiv[ish] n_orb = common.get_n_orbitals(sum_k)[icrsh]['up'] u_matrix_temp = u_matrix_four_indices[first_index_shell:first_index_shell+n_orb, first_index_shell:first_index_shell+n_orb, first_index_shell:first_index_shell+n_orb, first_index_shell:first_index_shell+n_orb] # I think for now we should stick with real interactions make real u_matrix_temp.imag = 0.0 if ish == icrsh: u_matrix_four_indices_per_shell[icrsh] = u_matrix_temp elif not np.allclose(u_matrix_four_indices_per_shell[icrsh], u_matrix_temp, atol=1e-6, rtol=0): # TODO: for some reason, some entries in the matrices differ by a sign. Check that # mpi.report(np.allclose(np.abs(u_matrix_four_indices_per_shell[icrsh]), np.abs(u_matrix_temp), # atol=1e-6, rtol=0)) mpi.report('Warning: cRPA matrix for impurity {} '.format(icrsh) + 'differs for shells {} and {}'.format(sum_k.inequiv_to_corr[icrsh], ish)) first_index_shell += n_orb if not np.allclose(u_matrix_four_indices.shape, first_index_shell): print('Warning: different number of orbitals in cRPA matrix than in calculation.') elif gw_params['code'] == 'aimbes': from solid_dmft.gw_embedding.bdft_converter import convert_gw_output u_matrix_four_indices_per_shell = [] # lad GW input from h5 file if mpi.is_master_node(): if 'Uloc_dlr' not in gw_params: gw_data, ir_kernel = convert_gw_output( general_params['jobname'] + '/' + general_params['seedname'] + '.h5', gw_params['h5_file'], it_1e = gw_params['it_1e'], it_2e = gw_params['it_2e'], ha_ev_conv = True ) gw_params.update(gw_data) for icrsh in range(sum_k.n_inequiv_shells): # for now we assume that up / down are equal if general_params['h_int_type'][icrsh] in ('crpa', 'crpa_density_density'): Uloc_0 = make_gf_imfreq(gw_params['Uloc_dlr'][icrsh]['up'],1) u_matrix_four_indices_per_shell.append(Uloc_0.data[0,:,:,:,:] + gw_params['Vloc'][icrsh]['up']) else: u_matrix_four_indices_per_shell.append(gw_params['Vloc'][icrsh]['up']) u_matrix_four_indices_per_shell[icrsh] = u_matrix_four_indices_per_shell[icrsh] mpi.barrier() u_matrix_four_indices_per_shell = mpi.bcast(u_matrix_four_indices_per_shell) gw_params = mpi.bcast(gw_params) else: raise ValueError('Unknown code for reading cRPA results: {}'.format(gw_params['code'])) return u_matrix_four_indices_per_shell, gw_params
# def _adapt_U_2index_for_SO(Umat, Upmat): # """ # Changes the two-index U matrices such that for a system consisting of a # single block 'ud' with the entries (1, up), (1, down), (2, up), (2, down), # ... the matrices are consistent with the case without spin-orbit coupling. # Parameters # ---------- # Umat : numpy array # The two-index interaction matrix for parallel spins without SO. # Upmat : numpy array # The two-index interaction matrix for antiparallel spins without SO. # Returns # ------- # Umat_SO : numpy array # The two-index interaction matrix for parallel spins. Because in SO all # entries have nominal spin 'ud', this matrix now contains the original # Umat and Upmat. # Upmat_SO : numpy array # The two-index interaction matrix for antiparallel spins. Unused because # in SO, all spins have the same nominal spin 'ud'. # """ # Umat_SO = np.zeros(np.array(Umat.shape)*2, dtype=Umat.dtype) # Umat_SO[::2, ::2] = Umat_SO[1::2, 1::2] = Umat # Umat_SO[::2, 1::2] = Umat_SO[1::2, ::2] = Upmat # Upmat_SO = None # return Umat_SO, Upmat_SO
[docs] def _adapt_U_4index_for_SO(Umat_full): """ Changes the four-index U matrix such that for a system consisting of a single block 'ud' with the entries (1, up), (1, down), (2, up), (2, down), ... the matrix is consistent with the case without spin-orbit coupling. This can be derived directly from the definition of the Slater Hamiltonian. Parameters ---------- Umat_full : numpy array The four-index interaction matrix without SO. Returns ------- Umat_full_SO : numpy array The four-index interaction matrix with SO. For a matrix U_ijkl, the indices i, k correspond to spin sigma, and indices j, l to sigma'. """ Umat_full_SO = np.zeros(np.array(Umat_full.shape)*2, dtype=Umat_full.dtype) for spin, spin_prime in ((0, 0), (0, 1), (1, 0), (1, 1)): Umat_full_SO[spin::2, spin_prime::2, spin::2, spin_prime::2] = Umat_full return Umat_full_SO
[docs] def _construct_kanamori(sum_k, general_params, solver_type_per_imp, icrsh, den_den=False): """ Constructs the Kanamori interaction Hamiltonian. Only Kanamori does not need the full four-index matrix. Therefore, we can construct it directly from the parameters U and J. """ n_orb = common.get_n_orbitals(sum_k)[icrsh]['up'] if sum_k.SO == 1: assert n_orb % 2 == 0 n_orb = n_orb // 2 if n_orb not in (2, 3): mpi.report('warning: are you sure you want to use the kanamori hamiltonian ' + 'outside the t2g or eg manifold?') # check if Uprime has been specified manually if general_params['U_prime'][icrsh] is None: U_prime = general_params['U'][icrsh] - 2.0 * general_params['J'][icrsh] else: U_prime = general_params['U_prime'][icrsh] mpi.report('U = {:.2f}, U\' = {:.2f}, J = {:.2f}\n'.format(general_params['U'][icrsh], U_prime, general_params['J'][icrsh])) if solver_type_per_imp[icrsh] == 'ftps': # 1-band modell requires J and U' equals zero if n_orb == 1: up, j = 0.0, 0.0 else: up = U_prime j = general_params['J'][icrsh] h_int = ftps.solver_core.HInt(u=general_params['U'][icrsh], j=j, up=up, dd=den_den) elif sum_k.SO == 0: # Constructs U matrix Umat, Upmat = util.U_matrix_kanamori(n_orb=n_orb, U_int=general_params['U'][icrsh], J_hund=general_params['J'][icrsh], Up_int=U_prime) if den_den: h_int = util.h_int_density(sum_k.spin_block_names[sum_k.SO], n_orb, map_operator_structure=sum_k.sumk_to_solver[icrsh], U=Umat, Uprime=Upmat, H_dump=os.path.join(general_params['jobname'], f'H_imp{icrsh}.txt')) else: h_int = util.h_int_kanamori(sum_k.spin_block_names[sum_k.SO], n_orb, map_operator_structure=sum_k.sumk_to_solver[icrsh], U=Umat, Uprime=Upmat, J_hund=general_params['J'][icrsh], H_dump=os.path.join(general_params['jobname'], f'H_imp{icrsh}.txt')) else: h_int = _construct_kanamori_soc(general_params['U'][icrsh], general_params['J'][icrsh], n_orb, sum_k.sumk_to_solver[icrsh], os.path.join(general_params['jobname'], f'H_imp{icrsh}.txt')) return h_int
[docs] def _construct_kanamori_soc(U_int, J_hund, n_orb, map_operator_structure, H_dump=None): r""" Adapted from triqs.operators.util.hamiltonians.h_int_kanamori. Assumes that spin_names == ['ud'] and that map_operator_structure is given. """ orb_names = list(range(n_orb)) if H_dump: H_dump_file = open(H_dump, 'w') H_dump_file.write("Kanamori Hamiltonian:" + '\n') H = Operator() mkind = util.op_struct.get_mkind(None, map_operator_structure) s = 'ud' # density terms: # TODO: reformulate in terms of Umat and Upmat for consistency with triqs? if H_dump: H_dump_file.write("Density-density terms:" + '\n') for a1, a2 in product(orb_names, orb_names): if a1 == a2: # same spin and orbital continue if a1 // 2 == a2 // 2: # same orbital (, different spins) U_val = U_int elif a1 % 2 != a2 % 2: # different spins (, different orbitals) U_val = U_int - 2*J_hund else: # same spins (, different orbitals) U_val = U_int - 3*J_hund H_term = 0.5 * U_val * n(*mkind(s, a1)) * n(*mkind(s, a2)) H += H_term # Dump terms of H if H_dump and not H_term.is_zero(): H_dump_file.write('%s' % (mkind(s, a1), ) + '\t') H_dump_file.write('%s' % (mkind(s, a2), ) + '\t') H_dump_file.write(str(U_val) + '\n') # spin-flip terms: if H_dump: H_dump_file.write("Spin-flip terms:" + '\n') for a1, a2, a3, a4 in product(orb_names, orb_names, orb_names, orb_names): if a1 == a2 or a1 == a3 or a1 == a4 or a2 == a3 or a2 == a4 or a3 == a4: continue if not (a1//2 == a2//2 and a3//2 == a4//2 and a1//2 != a3//2 and a1 % 2 != a3 % 2): continue H_term = -0.5 * J_hund * c_dag(*mkind(s, a1)) * c(*mkind(s, a2)) * c_dag(*mkind(s, a3)) * c(*mkind(s, a4)) H += H_term # Dump terms of H if H_dump and not H_term.is_zero(): H_dump_file.write('%s' % (mkind(s, a1), ) + '\t') H_dump_file.write('%s' % (mkind(s, a2), ) + '\t') H_dump_file.write('%s' % (mkind(s, a3), ) + '\t') H_dump_file.write('%s' % (mkind(s, a4), ) + '\t') H_dump_file.write(str(-J_hund) + '\n') # pair-hopping terms: if H_dump: H_dump_file.write("Pair-hopping terms:" + '\n') for a1, a2, a3, a4 in product(orb_names, orb_names, orb_names, orb_names): if a1 == a2 or a1 == a3 or a1 == a4 or a2 == a3 or a2 == a4 or a3 == a4: continue if not (a1//2 == a2//2 and a3//2 == a4//2 and a1//2 != a3//2 and a1 % 2 != a3 % 2): continue H_term = 0.5 * J_hund * c_dag(*mkind(s, a1)) * c_dag(*mkind(s, a2)) * c(*mkind(s, a4)) * c(*mkind(s, a3)) H += H_term # Dump terms of H if H_dump and not H_term.is_zero(): H_dump_file.write('%s' % (mkind(s, a1), ) + '\t') H_dump_file.write('%s' % (mkind(s, a2), ) + '\t') H_dump_file.write('%s' % (mkind(s, a3), ) + '\t') H_dump_file.write('%s' % (mkind(s, a4), ) + '\t') H_dump_file.write(str(-J_hund) + '\n') return H
[docs] def _construct_dynamic(sum_k, general_params, icrsh): """ Constructs the interaction Hamiltonian for a frequency-dependent interaction. Works only without spin-orbit coupling and only for one orbital. """ mpi.report('###### Dynamic U calculation ######, load parameters from input archive.') U_onsite = None if mpi.is_master_node(): with HDFArchive(general_params['jobname']+'/'+general_params['seedname']+'.h5', 'r') as ar: U_onsite = ar['dynamic_U']['U_scr'] U_onsite = mpi.bcast(U_onsite) n_orb = common.get_n_orbitals(sum_k)[icrsh]['up'] if sum_k.SO == 1: raise ValueError('dynamic U not implemented for SO!=0') if n_orb > 1: raise ValueError('dynamic U not implemented for more than one orbital') mpi.report('onsite interaction value for imp {}: {:.3f}'.format(icrsh, U_onsite[icrsh])) h_int = util.h_int_density(sum_k.spin_block_names[sum_k.SO], n_orb, map_operator_structure=sum_k.sumk_to_solver[icrsh], U=np.array([[0]]), Uprime=np.array([[U_onsite[icrsh]]]), H_dump=os.path.join(general_params['jobname'], f'H_imp{icrsh}.txt')) return h_int
[docs] def _generate_four_index_u_matrix(sum_k, general_params, icrsh): """ Generates the four-index interaction matrix per impurity with the interaction parameters U and J (and ratio_F4_F2 for the d shell). """ # ish points to the shell representative of the current group ish = sum_k.inequiv_to_corr[icrsh] n_orb = common.get_n_orbitals(sum_k)[icrsh]['up'] if sum_k.SO == 1: assert n_orb % 2 == 0 n_orb = n_orb // 2 l = sum_k.corr_shells[ish]['l'] if l != 2: slater_integrals = util.U_J_to_radial_integrals(l=l, U_int=general_params['U'][icrsh], J_hund=general_params['J'][icrsh]) else: # Implements parameter R=F4/F2. For R=0.63 equivalent to util.U_J_to_radial_integrals U = general_params['U'][icrsh] J = general_params['J'][icrsh] R = general_params['ratio_F4_F2'][icrsh] R = 0.63 if R is None else R slater_integrals = np.array([U, 14*J/(1+R), 14*J*R/(1+R)]) mpi.report('\nImpurity {}: The corresponding slater integrals are'.format(icrsh)) formatted_slater_integrals = [y for x in list(zip([2*x for x in range(len(slater_integrals))], slater_integrals)) for y in x] mpi.report(('F{:d} = {:.2f}, '*len(slater_integrals)).format(*formatted_slater_integrals)) # Constructs U matrix # construct full spherical symmetric U matrix and transform to cubic basis # the order for the cubic orbitals is given by the convention. The TRIQS # convention is as follows ("xy","yz","z^2","xz","x^2-y^2") # this is consistent with the order of orbitals in the VASP interface # but not necessarily with wannier90, qe, and wien2k! # This is also true for the f-shell. Umat_full = util.U_matrix_slater(l=l, radial_integrals=slater_integrals, basis='spherical') Umat_full = util.transform_U_matrix(Umat_full, util.spherical_to_cubic(l=l, convention=general_params['h_int_basis'])) if l == 2 and n_orb == 2: Umat_full = util.eg_submatrix(Umat_full) mpi.report('Using eg subspace of interaction Hamiltonian') elif l == 2 and n_orb == 3: Umat_full = util.t2g_submatrix(Umat_full) mpi.report('Using t2g subspace of interaction Hamiltonian') elif n_orb != 2*l+1: raise ValueError(f'Imp {icrsh}: for the Slater Hamiltonian, please use either ' f'the full shell with 2l+1={2*l+1} orbitals ' 'or the t2g or eg subspace of the d shell with 3 or 2 orbitals.') return Umat_full
[docs] def _rotate_four_index_matrix(sum_k, general_params, Umat_full, icrsh): """ Rotates the four index matrix into the local frame. """ ish = sum_k.inequiv_to_corr[icrsh] # Transposes rotation matrix here because TRIQS has a slightly different definition Umat_full_rotated = util.transform_U_matrix(Umat_full, sum_k.rot_mat[ish].T) if general_params['h_int_type'][icrsh] in ('density_density', 'crpa_density_density', 'dyn_density_density'): if not np.allclose(Umat_full_rotated, Umat_full): mpi.report('WARNING: applying a rotation matrix changes the dens-dens Hamiltonian.\n' + 'This changes the definition of the ignored spin flip and pair hopping.') elif general_params['h_int_type'][icrsh] in ('full_slater', 'crpa', 'dyn_full'): if not np.allclose(Umat_full_rotated, Umat_full): mpi.report('WARNING: applying a rotation matrix changes the interaction Hamiltonian.\n' + 'Please ensure that the rotation is correct!') return Umat_full_rotated
[docs] def _construct_density_density(sum_k, general_params, Umat_full_rotated, icrsh): """ Constructs the density-density Slater-Hamiltonian from the four-index interaction matrix. """ # Constructs Hamiltonian from Umat_full_rotated n_orb = common.get_n_orbitals(sum_k)[icrsh]['up'] Umat, Upmat = util.reduce_4index_to_2index(Umat_full_rotated) h_int = util.h_int_density(sum_k.spin_block_names[sum_k.SO], n_orb, map_operator_structure=sum_k.sumk_to_solver[icrsh], U=Umat, Uprime=Upmat, H_dump=os.path.join(general_params['jobname'], f'H_imp{icrsh}.txt')) return h_int
[docs] def _construct_slater(sum_k, general_params, Umat_full_rotated, icrsh): """ Constructs the full Slater-Hamiltonian from the four-index interaction matrix. """ n_orb = common.get_n_orbitals(sum_k)[icrsh]['up'] h_int = util.h_int_slater(sum_k.spin_block_names[sum_k.SO], n_orb, map_operator_structure=sum_k.sumk_to_solver[icrsh], U_matrix=Umat_full_rotated, H_dump=os.path.join(general_params['jobname'], f'H_imp{icrsh}.txt')) return h_int
[docs] def h_int_simple_intra(spin_names,n_orb,U,off_diag=None,map_operator_structure=None,H_dump=None): r""" Create a simple intra orbital density-density Hamiltonian. (no inter orbital terms) .. math:: H = \frac{1}{2} \sum_{i \sigma \neq \sigma')} U_{i i}^{\sigma \sigma'} n_{i \sigma} n_{i \sigma'}. Parameters ---------- spin_names : list of strings Names of the spins, e.g. ['up','down']. n_orb : int Number of orbitals. U : float U value off_diag : boolean Do we have (orbital) off-diagonal elements? If yes, the operators and blocks are denoted by ('spin', 'orbital'), otherwise by ('spin_orbital',0). map_operator_structure : dict Mapping of names of GF blocks names from one convention to another, e.g. {('up', 0): ('up_0', 0), ('down', 0): ('down_0',0)}. If provided, the operators and blocks are denoted by the mapping of ``('spin', 'orbital')``. H_dump : string Name of the file to which the Hamiltonian should be written. Returns ------- H : Operator The Hamiltonian. """ from triqs.operators.util.op_struct import get_mkind if H_dump: H_dump_file = open(H_dump,'w') H_dump_file.write("Density-density Hamiltonian:" + '\n') H = Operator() mkind = get_mkind(off_diag,map_operator_structure) if H_dump: H_dump_file.write("Density-density terms:" + '\n') for s1, s2 in product(spin_names,spin_names): if (s1 is not s2): for a1 in range(n_orb): H_term = 0.5 * U * n(*mkind(s1,a1)) * n(*mkind(s2,a1)) H += H_term # Dump terms of H if H_dump and not H_term.is_zero(): H_dump_file.write('%s'%(mkind(s1,a1),) + '\t') H_dump_file.write('%s'%(mkind(s2,a1),) + '\t') H_dump_file.write(str(U) + '\n') return H
[docs] def construct(sum_k, general_params, solver_type_per_imp, gw_params=None): """ Constructs the interaction Hamiltonian. Currently implemented are the Kanamori Hamiltonian (usually for 2 or 3 orbitals), the density-density and the full Slater Hamiltonian (for 2, 3, or 5 orbitals). If sum_k.rot_mat is non-identity, we have to consider rotating the interaction Hamiltonian: the Kanamori Hamiltonian does not change because it is invariant under orbital mixing but all the other Hamiltonians are at most invariant under rotations in space. Therefore, sum_k.rot_mat has to be correct before calling this method. The parameters U and J will be interpreted differently depending on the type of the interaction Hamiltonian: it is either the Kanamori parameters for the Kanamori Hamiltonian or the orbital-averaged parameters (consistent with DFT+U, https://cms.mpi.univie.ac.at/wiki/index.php/LDAUTYPE ) for all other Hamiltonians. Note also that for all Hamiltonians except Kanamori, the order of the orbitals matters. The correct order is specified here: triqs.github.io/triqs/unstable/documentation/python_api/triqs.operators.util.U_matrix.spherical_to_cubic.html """ # Extracts U and J mpi.report('*** interaction parameters ***') # Constructs the interaction Hamiltonian. Needs to come after setting sum_k.rot_mat mpi.report('\nConstructing the interaction Hamiltonians') h_int = [None] * sum_k.n_inequiv_shells for icrsh in range(sum_k.n_inequiv_shells): mpi.report('\nImpurity {}: constructing a {} type interaction Hamiltonian'.format(icrsh, general_params['h_int_type'][icrsh])) # Kanamori if general_params['h_int_type'][icrsh] == 'kanamori': h_int[icrsh] = _construct_kanamori(sum_k, general_params, solver_type_per_imp, icrsh, den_den=False) continue if general_params['h_int_type'][icrsh] == 'kanamori_den_den': h_int[icrsh] = _construct_kanamori(sum_k, general_params, solver_type_per_imp, icrsh, den_den=True) continue # for density density or full slater get full four-index U matrix if general_params['h_int_type'][icrsh] in ('density_density', 'full_slater'): mpi.report('\nNote: The input parameters U and J here are orbital-averaged parameters.') mpi.report('Note: The order of the orbitals is important. See also the doc string of this method.') # Checks that all entries are l == 2 or R is None if (sum_k.corr_shells[sum_k.inequiv_to_corr[icrsh]]['l'] != 2 and general_params['ratio_F4_F2'][icrsh] is not None): raise ValueError('Ratio F4/F2 only implemented for d-shells ' + 'but set in impurity {}'.format(icrsh)) if general_params['h_int_type'][icrsh] == 'density_density' and solver_type_per_imp[icrsh] == 'ftps': # TODO: implement raise NotImplementedError('Note: Density-density not implemented for ftps.') Umat_full = _generate_four_index_u_matrix(sum_k, general_params, icrsh) if sum_k.SO == 1: Umat_full = _adapt_U_4index_for_SO(Umat_full) # Rotates the interaction matrix Umat_full_rotated = _rotate_four_index_matrix(sum_k, general_params, Umat_full, icrsh) # construct slater / density density from U tensor if general_params['h_int_type'][icrsh] == 'full_slater': h_int[icrsh] = _construct_slater(sum_k, general_params, Umat_full_rotated, icrsh) else: h_int[icrsh] = _construct_density_density(sum_k, general_params, Umat_full_rotated, icrsh) continue # simple total impurity occupation interation: U/2 (Ntot^2 - Ntot) if general_params['h_int_type'][icrsh] == 'ntot': n_tot_op = Operator() for block, n_orb in sum_k.gf_struct_solver[icrsh].items(): n_tot_op += sum(n(block, orb) for orb in range(n_orb)) h_int[icrsh] = general_params['U'][icrsh]/2.0 * (n_tot_op*n_tot_op - n_tot_op) continue if general_params['h_int_type'][icrsh] == 'simple_intra': h_int[icrsh] = h_int_simple_intra(sum_k.spin_block_names[sum_k.SO], common.get_n_orbitals(sum_k)[icrsh]['up'], map_operator_structure=sum_k.sumk_to_solver[icrsh], U=general_params['U'][icrsh], H_dump=os.path.join(general_params['jobname'], f'H_imp{icrsh}.txt')) continue # read from file options if general_params['h_int_type'][icrsh] in ('crpa', 'crpa_density_density', 'dyn_density_density', 'dyn_full'): Umat_full, gw_params = _load_crpa_interaction_matrix(sum_k, general_params, gw_params) if sum_k.SO == 1: Umat_full[icrsh] = _adapt_U_4index_for_SO(Umat_full[icrsh]) # Rotates the interaction matrix if sum_k.use_rotations: Umat_full[icrsh] = _rotate_four_index_matrix(sum_k, general_params, Umat_full[icrsh], icrsh) Umat_full[icrsh][np.abs(Umat_full[icrsh]) < general_params['U_crpa_threshold']] = 0.0 gw_params['U_matrix_rot']= Umat_full # construct slater / density density from U tensor if general_params['h_int_type'][icrsh] in ('crpa', 'dyn_full'): h_int[icrsh] = _construct_slater(sum_k, general_params, Umat_full[icrsh].real, icrsh) else: h_int[icrsh] = _construct_density_density(sum_k, general_params, Umat_full[icrsh].real, icrsh) continue raise NotImplementedError('Error when constructing the interaction Hamiltonian.') return h_int, gw_params