def relabel_operators(op, from_list, to_list): """ Transform the operator op according to the single particle transform matrix U defined in the subspace of operators listed in fundamental_operators. """ op_idx_map = get_operator_index_map(from_list, include_dag=True) op_idx_set = set(op_idx_map) from_list, to_list = list(from_list), list(to_list) # -- Loop over given operator and substitute operators # -- in from_list to to_list op_trans = Operator() for term in op: op_factor = Operator(1.) for factor in term: if type(factor) is list: for dag, idxs in factor: tup = (dag, tuple(idxs)) if tup in op_idx_set: op_factor *= to_list[op_idx_map.index(tup)] else: op_factor *= {False: c, True: c_dag}[dag](*idxs) else: # constant prefactor op_factor *= factor op_trans += op_factor return op_trans
def operator_single_particle_transform(op, U, fundamental_operators): """ Transform the operator op according to the single particle transform matrix U defined in the subspace of operators listed in fundamental_operators. """ # -- Convert fundamental operators back and forth from index op_idx_map = get_operator_index_map(fundamental_operators) op_idx_set = set(op_idx_map) # -- Transformed creation operator def c_transf(s, i): if (s, i) not in op_idx_set: return c(s, i) k = op_idx_map.index((s, i)) ret = Operator() for l in range(U.shape[0]): op_idx = op_idx_map[l] ret += U[k, l] * c(*op_idx) return ret # -- Precompute transformed operators op_trans_dict = {} for fop in fundamental_operators: dag, idxs = op_serialize_fundamental(fop) op_trans_dict[(dag, idxs)] = c_transf(*idxs) op_trans_dict[(not dag, idxs)] = dagger(c_transf(*idxs)) # -- Loop over given operator and substitute operators # -- fundamental_operators with the transformed operators op_trans = Operator() for term in op: op_factor = Operator(1.) for factor in term: if type(factor) is list: for dag, idxs in factor: tup = (dag, tuple(idxs)) if tup in list(op_trans_dict.keys()): op_factor *= op_trans_dict[tup] else: op_factor *= {False: c, True: c_dag}[dag](*idxs) else: # constant prefactor op_factor *= factor op_trans += op_factor return op_trans
def convert_operator(self, O, ish=0): """ Converts a second-quantization operator from sumk structure to solver structure. Parameters ---------- O : triqs.operators.Operator Operator in sumk structure ish : int shell index on which the operator acts """ from triqs.operators import Operator, c, c_dag T = self.transformation[ish] sk2s = self.sumk_to_solver[ish] O_out = Operator(0) for monomial in O: coefficient = monomial[-1] new_monomial = Operator(1) #if coefficient > 1e-10: for single_operator in monomial[0]: new_single_operator = Operator(0) daggered = single_operator[0] blockname = single_operator[1][0] i = single_operator[1][1] for j in range(len(T[blockname])): if sk2s[(blockname, j)] != (None, None): if daggered: new_single_operator += ( T[blockname][j, i] * c_dag(*sk2s[(blockname, j)])) else: new_single_operator += ( T[blockname][j, i].conjugate() * c(*sk2s[(blockname, j)])) new_monomial *= new_single_operator O_out += new_monomial * coefficient return O_out
def test_fundamental(): assert (op_is_fundamental(c(0, 0)) is True) assert (op_is_fundamental(c_dag(0, 0)) is True) assert (op_is_fundamental(c_dag(0, 0) * c(0, 0)) is False) assert (op_is_fundamental(Operator(1.0)) is False) assert (op_serialize_fundamental(c(0, 0)) == (False, (0, 0))) assert (op_serialize_fundamental(c_dag(0, 0)) == (True, (0, 0))) assert (op_serialize_fundamental(c(2, 4)) == (False, (2, 4))) assert (op_serialize_fundamental(c_dag(4, 3)) == (True, (4, 3)))
def get_quadratic_operator(h, fundamental_operators): # -- Check Hermicity np.testing.assert_array_almost_equal(h, h.T.conj()) H = Operator(0.) for idx1, o1 in enumerate(fundamental_operators): o1 = dagger(o1) for idx2, o2 in enumerate(fundamental_operators): H += h[idx1, idx2] * o1 * o2 return H
def c_transf(s, i): if (s, i) not in op_idx_set: return c(s, i) k = op_idx_map.index((s, i)) ret = Operator() for l in range(U.shape[0]): op_idx = op_idx_map[l] ret += U[k, l] * c(*op_idx) return ret
def operator_from_quartic_tensor(h_quart, fundamental_operators): # -- Convert fundamental operators back and forth from index op_idx_map = get_operator_index_map(fundamental_operators) op_idx_set = set(op_idx_map) nop = len(fundamental_operators) H = Operator(0.) for t in itertools.product(enumerate(fundamental_operators), repeat=4): idx, ops = list(zip(*t)) o1, o2, o3, o4 = ops o1, o2 = dagger(o1), dagger(o2) H += h_quart[idx] * o1 * o2 * o3 * o4 return H
import unittest from triqs.operators import c, c_dag, Operator from triqs.atom_diag import * from itertools import product import numpy as np orbs = (1, 2, 3) spins = ("dn", "up") # Construct a sum of the pair hopping and spin flip terms from a 3-orbital Kanamori interaction Hamiltonian H_p = Operator() H_J = Operator() for o1, o2 in product(orbs, repeat=2): if o1 == o2: continue H_p += c_dag("dn", o1) * c_dag("up", o1) * c("up", o2) * c("dn", o2) H_J += c_dag("dn", o1) * c("up", o1) * c_dag("up", o2) * c("dn", o2) H = H_p + H_J fops1 = [(s, o) for (s, o) in product(spins, orbs)] fops2 = [(s, o) for (o, s) in product(orbs, spins)] ad1 = AtomDiag(H, fops1) ad2 = AtomDiag(H, fops2) # for e1, e2 in zip(ad1.energies, ad2.energies): # print(e1.round(5), e2.round(5))
def h_int_kanamori_d(spin_names, orb_names, U, Uprime, J_hund, off_diag=None, map_operator_structure=None, H_dump=None, d=None): r""" Create a Kanamori Hamiltonian using the density-density, spin-fip and pair-hopping interactions. .. math:: H = \frac{1}{2} \sum_{(i \sigma) \neq (j \sigma')} U_{i j}^{\sigma \sigma'} n_{i \sigma} n_{j \sigma'} - \sum_{i \neq j} J a^\dagger_{i \uparrow} a_{i \downarrow} a^\dagger_{j \downarrow} a_{j \uparrow} + \sum_{i \neq j} J a^\dagger_{i \uparrow} a^\dagger_{i \downarrow} a_{j \downarrow} a_{j \uparrow}. Parameters ---------- spin_names : list of strings Names of the spins, e.g. ['up','down']. orb_names : list of strings or int Names of the orbitals, e.g. [0,1,2] or ['t2g','eg']. U : 2D matrix or array :math:`U_{ij}^{\sigma \sigma} (same spins)` Uprime : 2D matrix or array :math:`U_{ij}^{\sigma \bar{\sigma}} (opposite spins)` J_hund : scalar :math:`J` 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. """ def d_dag(b, m): return dagger(d(b, m)) if H_dump: H_dump_file = open(H_dump, 'w') H_dump_file.write("Kanamori Hamiltonian:" + '\n') H = Operator() mkind = get_mkind(off_diag, map_operator_structure) # density terms: if H_dump: H_dump_file.write("Density-density terms:" + '\n') for s1, s2 in product(spin_names, spin_names): for a1, a2 in product(orb_names, orb_names): if (s1 == s2): U_val = U[orb_names.index(a1), orb_names.index(a2)] else: U_val = Uprime[orb_names.index(a1), orb_names.index(a2)] H_term = 0.5 * U_val * d_dag(*mkind(s1, a1)) * d( *mkind(s1, a1)) * d_dag(*mkind(s2, a2)) * d(*mkind(s2, a2)) 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, 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 s1, s2 in product(spin_names, spin_names): if (s1 == s2): continue for a1, a2 in product(orb_names, orb_names): if (a1 == a2): continue H_term = -0.5 * J_hund * d_dag(*mkind(s1, a1)) * d( *mkind(s2, a1)) * d_dag(*mkind(s2, a2)) * d(*mkind(s1, a2)) 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, a2), ) + '\t') H_dump_file.write(str(-J_hund) + '\n') # pair-hopping terms: if H_dump: H_dump_file.write("Pair-hopping terms:" + '\n') for s1, s2 in product(spin_names, spin_names): if (s1 == s2): continue for a1, a2 in product(orb_names, orb_names): if (a1 == a2): continue H_term = 0.5 * J_hund * d_dag(*mkind(s1, a1)) * d_dag( *mkind(s2, a1)) * d(*mkind(s2, a2)) * d(*mkind(s1, a2)) 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, a2), ) + '\t') H_dump_file.write(str(-J_hund) + '\n') return H
def d(b, m): ret = Operator() for i in range(len(v[b])): ret += v[b][m][i] * c(b, i) return ret