def generic_densitydensity(h0, mf=None, mix=0.1, v=None, nk=8, solver="plain", maxerror=1e-5, filling=None, callback_mf=None, callback_dm=None, load_mf=True, compute_cross=True, compute_dd=True, verbose=1, compute_anomalous=True, compute_normal=True, info=False, callback_h=None, **kwargs): """Perform the SCF mean field""" if verbose > 1: info = True # if not h0.check_mode("spinless"): raise # sanity check mf = obj2mf(mf) h1 = h0.copy() # initial Hamiltonian h1.turn_dense() h1.nk = nk # store the number of kpoints if mf is None: try: if load_mf: mf = inout.load(mf_file) # load the file else: raise except: mf = dict() for d in v: mf[d] = np.exp(1j * np.random.random(h1.intra.shape)) mf[(0, 0, 0)] = mf[(0, 0, 0)] + mf[(0, 0, 0)].T.conjugate() else: pass # initial guess ii = 0 os.system("rm -f STOP") # remove stop file hop0 = hamiltonian2dict(h1) # create dictionary def f(mf, h=h1): """Function to minimize""" # print("Iteration #",ii) # Iteration mf0 = deepcopy(mf) # copy h = h1.copy() hop = update_hamiltonian(hop0, mf) # add the mean field to the Hamiltonian set_hoppings(h, hop) # set the new hoppings in the Hamiltonian if callback_h is not None: h = callback_h(h) # callback for the Hamiltonian t0 = time.perf_counter() # time dm = get_dm(h, v, nk=nk) # get the density matrix if callback_dm is not None: dm = callback_dm(dm) # callback for the density matrix t1 = time.perf_counter() # time # return the mean field mf = get_mf(v, dm, compute_cross=compute_cross, compute_dd=compute_dd, has_eh=h0.has_eh, compute_anomalous=compute_anomalous, compute_normal=compute_normal) if callback_mf is not None: mf = callback_mf(mf) # callback for the mean field t2 = time.perf_counter() # time if info: print("Time in density matrix = ", t1 - t0) # Difference if info: print("Time in the normal term = ", t2 - t1) # Difference scf = SCF() # create object scf.hamiltonian = h # store # h.check() # check the Hamiltonian scf.hamiltonian0 = h0 # store scf.mf = mf # store mean field if os.path.exists("STOP"): scf.mf = mf0 # use the guess scf.dm = dm # store density matrix scf.v = v # store interaction scf.tol = maxerror # maximum error return scf if solver == "plain": do_scf = True while do_scf: scf = f(mf) # new vector mfnew = scf.mf # new vector t0 = time.clock() # time diff = diff_mf(mfnew, mf) # mix mean field mf = mix_mf(mfnew, mf, mix=mix) # mix mean field t1 = time.clock() # time if info: print("Time in mixing", t1 - t0) if verbose > 0: print("ERROR in the SCF cycle", diff) #print("Mixing",dmix) if info: print() if diff < maxerror: scf = f(mfnew) # last iteration, with the unmixed mean field inout.save(scf.mf, mf_file) # save the mean field # scf.hamiltonian.check(tol=100*maxerror) # perform some sanity checks return scf else: # use different solvers scf = f(mf) # perform one iteration fmf2a = get_mf2array(scf) # convert MF to array fa2mf = get_array2mf(scf) # convert array to MF def fsol(x): # define the function to solve mf1 = fa2mf(x) # convert to a MF scf1 = f(mf1) # compute function xn = fmf2a(scf1.mf) # new vector diff = x - xn # difference vector print("ERROR", np.max(np.abs(diff))) print() return x - xn # return vector x0 = fmf2a(scf.mf) # initial guess # these methods do seem too efficient, but lets have them anyway if solver == "krylov": from scipy.optimize import newton_krylov x = newton_krylov(fsol, x0, rdiff=1e-3) # use the solver elif solver == "anderson": from scipy.optimize import anderson x = anderson(fsol, x0) # use the solver elif solver == "broyden1": from scipy.optimize import broyden1 x = broyden1(fsol, x0, f_tol=maxerror * 100) # use the solver elif solver == "linear": from scipy.optimize import linearmixing x = linearmixing(fsol, x0, f_tol=maxerror * 100) # use the solver else: raise # unrecognised solver mf = fa2mf(x) # transform to MF scf = f(mf) # compute the SCF with the solution scf.error = maxerror # store the error inout.save(scf.mf, mf_file) # save the mean field return scf # return the mean field
self_ene_dmp_init = np.array(self_ene_init) for iflavor in range(nflavor): for iflavor2 in range(nflavor): self_ene_dmp_init[:, iflavor, iflavor2] = self_ene_dmp_init[:, iflavor, iflavor2] * dmp_fact #symmetry if 'SYMM_MAT' in app_parms: nsymm = app_parms['SYMM_MAT'].shape[0] nf_sbl = imp_model.get_nflavor() / imp_model.get_nsbl() for isymm in xrange(nsymm): assert is_unitary(app_parms['SYMM_MAT'][isymm, :, :]) assert commute( imp_model.get_moment(1)[0:nf_sbl, 0:nf_sbl], app_parms['SYMM_MAT'][isymm, :, :]) #sciopt.root(calc_diff,self_ene_init,method="anderson",options={'nit' : app_parms["MAX_IT"], 'fatol' : app_parms["CONVERGED"], 'disp': True, 'M': 10}) dmft_result = DMFTResult() mix = 0.5 if 'mix' in app_parms: mix = app_parms['mix'] sciopt.linearmixing(calc_diff, self_ene_dmp_init, alpha=mix, iter=app_parms["MAX_IT"], f_rtol=app_parms["CONVERGED"], line_search=None, verbose=True) #sciopt.anderson(calc_diff,self_ene_dmp_init,iter=app_parms["MAX_IT"], f_rtol=app_parms["CONVERGED"], verbose=True)