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 xrange(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 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 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 xrange(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 = zip(*t) o1, o2, o3, o4 = ops o1, o2 = dagger(o1), dagger(o2) H += h_quart[idx] * o1 * o2 * o3 * o4 return H
index_converter.update({("B%i_%s" % (k, sn), 0): ("bath" + str(k), 0, "down" if sn == "dn" else "up") for k, sn in product(range(len(epsilon)), spin_names)}) # Make PomerolED solver object ed = PomerolED(index_converter, verbose=True) # Number of particles on the impurity H_loc = -mu * (n('up', 0) + n('dn', 0)) + U * n('up', 0) * n('dn', 0) # Bath Hamiltonian H_bath = sum(eps * n("B%i_%s" % (k, sn), 0) for sn, (k, eps) in product(spin_names, enumerate(epsilon))) # Hybridization Hamiltonian H_hyb = Operator() for k, v in enumerate(V): H_hyb += sum(v * c_dag("B%i_%s" % (k, sn), 0) * c(sn, 0) + np.conj(v) * c_dag(sn, 0) * c("B%i_%s" % (k, sn), 0) for sn in spin_names) # Complete Hamiltonian H = H_loc + H_hyb + H_bath # Diagonalize H ed.diagonalize(H) ########### # G^{(2)} # ###########
results_file_name = "kanamori" + (".qn" if use_qn else "") + ".h5" mpi.report("Welcome to Kanamori benchmark.") gf_struct = set_operator_structure(spin_names,orb_names,False) mkind = get_mkind(False,None) ## Hamiltonian H = h_int_kanamori(spin_names,orb_names, np.array([[0,U-3*J],[U-3*J,0]]), np.array([[U,U-2*J],[U-2*J,U]]), J,False) if use_qn: QN = [sum([n(*mkind("up",o)) for o in orb_names],Operator()), sum([n(*mkind("dn",o)) for o in orb_names],Operator())] for o in orb_names: dn = n(*mkind("up",o)) - n(*mkind("dn",o)) QN.append(dn*dn) p["partition_method"] = "quantum_numbers" p["quantum_numbers"] = QN mpi.report("Constructing the solver...") # Construct the solver S = SolverCore(beta=beta, gf_struct=gf_struct, n_tau=n_tau, n_iw=n_iw) mpi.report("Preparing the hybridization function...") # Set hybridization function
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
p["max_time"] = -1 p["random_name"] = "" p["random_seed"] = 123 * mpi.rank + 567 p["length_cycle"] = 50 p["n_warmup_cycles"] = 50000 p["n_cycles"] = 1200000 for modes in range(1,N_max+1): V = [0.2]*modes e = [-0.2]*modes #gf_struct = {str(n):[0] for n in range(0,len(V))} gf_struct = [ [str(bidx), [0]] for bidx in range(0,len(V)) ] # Local Hamiltonian H = Operator() # Quantum numbers (N_up and N_down) QN = [] for b, idxs in gf_struct: QN.append(n(b,0)) p["partition_method"] = "quantum_numbers" p["quantum_numbers"] = QN mpi.report("Constructing the solver...") # Construct the solver S = SolverCore(beta=beta, gf_struct=gf_struct, n_tau=n_tau, n_iw=n_iw) mpi.report("Preparing the hybridization function...") # Set hybridization function