def averageGreen(delta0, mu0, w, SelfEnergy, parms, Nd, Ntot, tuneup, extra): BETA = float(parms["BETA"]); N_LAYERS = int(parms['N_LAYERS']); FLAVORS = int(parms['FLAVORS']); SPINS = int(parms['SPINS']); rot_mat = extra['rot_mat']; # calculate intersite Coulomb energy here Vc = zeros(N_LAYERS, dtype = 'f8'); # convert self energy to the C++ form SelfEnergy_rot = array([functions.irotate(SelfEnergy[s], extra['rot_mat']) for s in range(SPINS)]); SE = [array([s.flatten() for s in SelfEnergy_rot[n]]) for n in range(SPINS)]; v_delta = empty(0, 'f8'); v_nd = empty(0, 'f8'); ddelta = 0.; delta_step = 1.; dmu = 0.; mu_step = 5; tol = 0.005; # Delta loop while True: delta = delta0 + ddelta; v_mu = empty(0, 'f8'); v_n = empty(0, 'f8'); # mu loop while True: mu = mu0 + dmu; Gavg = average_green.integrate(w, delta, mu, SE, parms, extra); Gavg_diag = array([Gavg[0, :, i, i] for i in range(int(parms['NORB']))]).T; nf = getDensity(Gavg_diag, parms); my_ntot = 2*sum(nf); # factor of 2 due to spin if tuneup: print " adjust mu: " + str(mu) + " " + str(dmu) + " " + str(my_ntot); if Ntot < 0 or abs(Ntot - my_ntot) < tol or not tuneup: break; v_mu = r_[v_mu, dmu]; v_n = r_[v_n, my_ntot]; if v_n.min() < Ntot and v_n.max() > Ntot: dmu = interp_root(v_mu, v_n, Ntot); else: dmu += (1. if my_ntot < Ntot else -1.)*mu_step; my_nd = 2*sum(nf[:N_LAYERS*FLAVORS]); if tuneup: print "adjust double counting: " + str(delta) + " " + str(ddelta) + " " + str(my_nd) + " " + str(my_nd/N_LAYERS); if Nd < 0 or abs(Nd - my_nd) < tol or not tuneup: break; v_delta = r_[v_delta, ddelta]; v_nd = r_[v_nd, my_nd]; if v_nd.min() < Nd and v_nd.max() > Nd: ddelta = interp_root(v_delta, v_nd, Nd); else: ddelta += (1. if my_nd < Nd else -1.)*delta_step; Gavg = array([functions.rotate_all(Gavg[s], rot_mat) for s in range(SPINS)]); return Gavg, delta, mu, Vc;
# 0: no parallelization # 1: OpenMP with number of threads set by OMP_NUM_THREADS # 2: MPI with number of processes from the input parallel = 2 num_processes = 10 if len(sys.argv) > 1: num_processes = int(sys.argv[1]) HR, R = init.getHamiltonian(rham_file, 4) NORB = size(HR, 1) rot_mat = init.getRotationMatrix(N_LAYERS, FLAVORS, H0 = HR[nonzero(sum(R**2, 1)==0)[0][0]]) w = linspace(emin, emax, nbin) # set zero self energy and convert it into the flattened format SelfEnergy = zeros((SPINS, nbin, N_LAYERS*FLAVORS), dtype = 'c16') SelfEnergy_rot = array([irotate(SelfEnergy[s], rot_mat) for s in range(SPINS)]) SE = array([array([s.flatten() for s in SelfEnergy_rot[n]]) for n in range(SPINS)]) # prepare the parameter dict parms = { 'H' : magnetic_field, 'N_LAYERS' : N_LAYERS, 'FLAVORS' : FLAVORS, 'SPINS' : SPINS, 'NORB' : NORB, 'INTEGRATE_MOD' : 'int_donly_tilted_3bands', 'np' : num_processes, }
def averageGreen(delta0, mu0, w, SelfEnergy, parms, Nd, Ntot, tuneup, extra): N_LAYERS = int(parms['N_LAYERS']) FLAVORS = int(parms['FLAVORS']) SPINS = int(parms['SPINS']) rot_mat = extra['rot_mat'] parallel = int(parms.get('KINT_PARALLEL', 2)) # calculate intersite Coulomb energy here Vc = zeros(N_LAYERS, dtype=float) # convert self energy to the C++ form SelfEnergy_rot = array([irotate(SelfEnergy[s], rot_mat) for s in range(SPINS)]) SE = array([array([s.flatten() for s in SelfEnergy_rot[n]]) for n in range(SPINS)]) v_delta = array([]) ddelta = 0. delta_step = 1. v_nd = array([]) dmu = 0. mu_step = 0.5 tol = 0.003 firsttime = True initial_Gasymp = extra['G_asymp_coefs'] if 'G_asymp_coefs' in extra.keys()\ else None starting_error = 0. # Delta loop while True: delta = delta0 + ddelta if initial_Gasymp is not None: extra['G_asymp_coefs'][:N_LAYERS*FLAVORS] = initial_Gasymp[:N_LAYERS*FLAVORS] - ddelta v_mu = array([]) v_n = array([]) # mu loop while True: mu = mu0 + dmu if initial_Gasymp is not None: extra['G_asymp_coefs'] = initial_Gasymp - dmu Gavg = integrate(w, delta, mu, SE, parms, extra, parallel) Gavg_diag = array([[diag(Gavg[s, n]) for n in range(size(Gavg,1))] for s in range(SPINS)]) nf = getDensityFromGmat(Gavg_diag, float(parms['BETA']), extra) my_ntot = sum(nf) if SPINS == 2 else 2*sum(nf) print " adjust mu: %.5f %.5f %.5f"%(mu, dmu, my_ntot) if firsttime: starting_error = abs(Ntot - my_ntot)/N_LAYERS Gavg0 = Gavg.copy() firsttime = False if Ntot < 0 or abs(Ntot - my_ntot)/N_LAYERS < tol or not tuneup: break v_mu = r_[v_mu, dmu] v_n = r_[v_n, my_ntot] if v_n.min() < Ntot and v_n.max() > Ntot: dmu = interp_root(v_mu, v_n, Ntot) else: dmu += (1. if my_ntot < Ntot else -1.)*mu_step my_nd = sum(nf[:, :N_LAYERS*FLAVORS]) if tuneup: print ('adjust double counting: %.5f %.5f ' '%.5f %.5f')%(delta, ddelta, my_nd, my_nd/N_LAYERS) if Nd < 0 or abs(Nd - my_nd)/N_LAYERS < tol or not tuneup: break v_delta = r_[v_delta, ddelta] v_nd = r_[v_nd, my_nd] if v_nd.min() < Nd and v_nd.max() > Nd: ddelta = interp_root(v_delta, v_nd, Nd) else: ddelta += (1. if my_nd < Nd else -1.)*delta_step # adjusted Gavg with mu_new = mu_0 + N*dmu and # delta_new = delta_0 + N*ddelta; N = float(parms.get('TUNEUP_FACTOR', 1)) if N != 1. and (ddelta != 0. or dmu != 0.) and starting_error < 50*tol: mu = mu0 + N*dmu delta = delta0 + N*ddelta Gavg = integrate(w, delta, mu, SE, parms, extra, parallel) print ('TUNEUP_FACTOR = %d final adjustment: mu = %.4f, dmu = %.4f, ' 'delta = %.4f, ddelta = %.4f')%(N, mu, N*dmu, delta, N*ddelta) Gavg = array([rotate_all(Gavg[s], rot_mat) for s in range(SPINS)]) Gavg0 = array([rotate_all(Gavg0[s], rot_mat, need_extra = True) for s in range(SPINS)]) if initial_Gasymp is not None: extra['G_asymp_coefs'] = initial_Gasymp return Gavg, Gavg0, delta, mu, Vc