def CmpRealAxisBubble(filemesh, filegkr, fbubbleReal, Qlist, k_index): def Cmp_ChiQ_real(iOm, Q, gkr, k_m_q, nkp, norb, dx_, idxl, Nd, zero_ind, k_index): level = (iOm - 1) / Nd # which linear mesh should we use? om_idx = idxl[level] # index for the linear mesh on this level izero = (len(om_idx) - 1) / 2 # zero_ind on this level dOm = om_idx.index(zero_ind + iOm) - izero # om-Om in integer notation is i-dOm om_idx = array(om_idx) Qi = k_index(Q) codeBub = """ #line 239 "Suscept.py" using namespace std; for (int iorb=0; iorb<norb; iorb++){ for (int jorb=0; jorb<norb; jorb++){ complex<double> csum=0.0; for (int iom=izero; iom<izero+dOm+1; iom++){ double dom = (iom==izero || iom==izero+dOm) ? dx/2.0 : dx; // trapezoid rule has 1/2 at the last interval complex<double> csum2=0.0; for (int ik=0; ik<nkp; ik++){ int ikq = k_m_q(ik,Qi); int iom1 = om_idx(iom); int iom2 = om_idx(iom-dOm); complex<double> irhok=(gkr(iorb,jorb,iom1,ik)-conj(gkr(jorb,iorb,iom1,ik)))/2.0; // (G_k-G_k^+)/2 complex<double> irhoq=(gkr(jorb,iorb,iom2,ikq)-conj(gkr(iorb,jorb,iom2,ikq)))/2.0; csum2 -= irhok*irhoq; // rho_k * rho_{k+q} } csum += csum2*dom; } ImBub(iorb,jorb) = csum/(nkp*M_PI); } } """ ImBub = zeros((norb, norb), dtype=complex) dx = float(dx_) weave.inline(codeBub, [ 'ImBub', 'gkr', 'norb', 'dx', 'nkp', 'Qi', 'k_m_q', 'dOm', 'izero', 'om_idx' ], type_converters=weave.converters.blitz, compiler='gcc') return ImBub #print 'Qlist=', Qlist ########################## # Reading real axis mesh # ########################## fm = open(filemesh, 'r') lined = fm.next().split() (mdelta, mmax) = map(float, lined[:2]) Nd = int(lined[2]) (oml, idxl) = LinLogMesh.LinLogMeshGen(mdelta, mmax, Nd) #print 'Qlist=', Qlist ####################################### # Reading real axis Green's function # ####################################### # Reading some basic information from G_k fg = open(filegkr, 'r') first_line = fg.next() nkp, nsymop, nom, cixdm, norbitals = map(int, first_line.split()[1:6]) fg.close() (gkr, omr) = ReadGk(filegkr, nkp, nsymop, nom, cixdm) print 'shape(gkr)=', shape(gkr) if sum(abs(omr - oml)) > 1e-5: print 'Mesh in ' + filegkr + ' and in ' + filemesh + ' are not compatible.' zero_ind = oml.tolist().index(0.0) Oml = oml[zero_ind:] norb = cixdm ############################### # Computing real axis Bubble # ############################### # This is the zero frequency value chi0r0 = zeros((len(Qlist), norb, norb), dtype=float) #print 'Qlist=', Qlist for iq, Q in enumerate(Qlist): print 'Q=', Q ImBub = zeros((norb, norb, len(Oml)), dtype=complex) for iOm in range(1, len(Oml)): ImBub[:, :, iOm] = Cmp_ChiQ_real(iOm, Q, gkr, k_m_q, nkp, norb, Oml[iOm] - Oml[iOm - 1], idxl, Nd, zero_ind, k_index) ImBubr = real(ImBub) Bub = zeros((norb, norb, len(Oml)), dtype=complex) for iorb in range(norb): for jorb in range(norb): tOm = hstack((-Oml[::-1][:-1], Oml[1:])) ImB = hstack( (-ImBubr[iorb, jorb, ::-1][:-1], ImBubr[iorb, jorb, 1:])) Bub[iorb, jorb, 0] = integrate.trapz(ImB / tOm, x=tOm) / pi izero = len(tOm) / 2 for i in range(izero, len(tOm)): Bub[iorb, jorb, i - izero + 1] = krams.kramarskronig(ImB, tOm, i) + ImB[i] * 1j chi0r0[iq, :, :] = Bub[:, :, 0].real fq = open(fbubbleReal + str(iq), 'w') for iOm, Omx in enumerate(Oml): print >> fq, Omx, for iorb in range(norb): for jorb in range(norb): print >> fq, Bub[iorb, jorb, iOm].real, Bub[iorb, jorb, iOm].imag, print >> fq fq.close() print 'Chi_q-real axis: Q point', iq, 'finished' return chi0r0
def HighFrequency(self, params, DCs, nl_imp, extn, wbroad=0.0, kbroad=0.0, Q_ETOT=False): """ Corrects high-frequency of OCA spetral functions such that it gives correct nf, normalization and sigma_oo This is achieved by adding two Lorentzians at high frequency. One below EF in the interval (par['epsilon'][0][0],par[epsilon][0][1]) and one above EF in the interval (par['epsilon'][1][0],par[epsilon][1][1]) Input: params -- parameters must contain T Ed U epsilon - prefered positions of additional lorentzians Th - when high-frequency spectral function is cut, it is cut by fermi function with temperature Th Gh - the width of the two lorentzians added Output: Sig[b][iom] -- DMFT dynamic self-energy which vanishes at infinity sinf[b] -- DMFT self-energy at infinity Edc[b] -- double counting using DMFT occupancies The 'corrected' Green's function will be of the form: G(om) = int(A(x)/(om-x)) + a1/(om-eps1+i*Gh) + a2/(om-eps2+i*Gh) The equations to be satisfied are: normalization: m0 + a1 + a2 = 1 density: nc + a1 = nc_{exact} where nc=int(A(x)f(x)) and nc_{exact} is computed from pseudo spectral functions Sigma_oo: m1 + a1*eps1 + a2*eps2 = Eimp+Sigma_oo == dsinf The equations can be brought to the form x*u + y*v = w with u and v positive numbers and x and y unknown numbers in the interval [0,1] In terms of above quantities, we have u = a1*(eps[0][1]-eps[0][0]) v = a2*(eps[1][1]-eps[1][0]) w = Eimp+Sigma_oo - m1 - a1*eps[0][0] - a2*eps[1][0] x = (eps1-eps[0][0])/(eps[0][1]-eps[0][0]) y = (eps2-eps[1][0])/(eps[1][1]-eps[1][0]) The solution exists if 0<w<u+v In this case x is in the interval x=[max((w-v)/u,0), min(w/u,1)] and y is in the interval y=[max((w-u)/v,0), min(w/v,1)] The solution choosen is: if (v>u): x=0.5*(x_min+x_max) else : y=0.5*(y_min+y_max) """ ################################################ # Reading of parameters from impurity cix file # ################################################ # cix file is used to find the following variables: J, l, Ns, baths fc = open(self.dir + self.sparams['cix']) first_line = fc.next() # next line of cix contains Ns and baths cixdat = fc.next().split() if cixdat[0] == 'OFF-DIAGONAL': Nl = int(fc.next().split()[0]) for i in range(Nl): fc.next() cixdat = fc.next().split() baths = int(cixdat[0]) Ns = map(int, cixdat[1:1 + baths]) #print 'Ns=', Ns #print 'baths=', baths # Reading Aloc.imp which was produced by OCA fA = open(self.dir + self.sparams['AlocOut']) # Aloc.imp contains nf, moment, ntot,... first_line = fA.next().strip() adat = first_line.split() for par in adat: m = re.search('[ntot|nf|moment|dFimpG|Epot]=', par) if m is not None: exec(par) om = [] Af = [] for p in fA: dat = p.split() om.append(float(dat[0])) Af.append(map(float, dat[1:1 + baths])) Af = array(Af) om = array(om) # reading of bath Weiss field fAc = open(self.dir + self.sparams['Ac']) Acd = [] ii = 0 for p in fAc: dat = p.split() omega = float(dat[0]) if (abs(omega - om[ii]) > 1e-5): print 'Seems that %s and %s are not compatible. Exiting!' % ( self.sparams['AlocOut'], self.sparams['Ac']) sys.exit(1) ii += 1 Acd.append(map(float, dat[1:1 + baths])) Acd = array(Acd) # define some common variables in this functions T = params['T'][0] Ed = params['Ed'][0] epsilon = params['epsilon'][0] # Here we construct few functions for faster computation # of moments and occupancies # # dh - mesh weights according to trapezoid rule # omdh - omega*dh for calculation of first moment # fedh - f(omega)*dh for calculation of occupancy # dh = [0.5 * (om[1] - om[0])] omdh = [om[0] * dh[-1]] fedh = [ferm(om[0] / T) * dh[-1]] for im in range(1, len(om) - 1): dh.append(0.5 * (om[im + 1] - om[im - 1])) omdh.append(om[im] * dh[-1]) fedh.append(ferm(om[im] / T) * dh[-1]) dh.append(0.5 * (om[-1] - om[-2])) omdh.append(om[-1] * dh[-1]) fedh.append(ferm(om[-1] / T) * dh[-1]) dh = array(dh) omdh = array(omdh) fedh = array(fedh) #da = 0 #if DCs['scheme']=='default' : da = DCs['a'] # Here we compute self-energy(infinity) and # double-counting using impurity occupancy (sinf, Edc) = Sinftyv(self.Sigind_shifted, self.CF, params['U'][0], self.J, self.l, baths, Ns, nf, 0, self.fh_info) Sigind = array(self.Sigind_shifted) Diagonal = {} for i in range(len(Sigind)): for j in range(len(Sigind)): if Sigind[i, j] > 0: Diagonal[Sigind[i, j] - 1] = (i == j) Ud = params['U'][0] Jd = self.J DC_ones = array([int(Diagonal[i]) for i in range(len(Edc))]) # If user fixes double counting by certain predescribed nf0 # (fixn=True), we need to normalized actual nf[:] such that # sum(nf[:]) is equal to predefined nf0 # Here we do not change Sigma_{infinity} but only Edc. # Sigma_{infinity} is determined by actual nf, while Edc is determined by modified nf. if DCs == 'fixn' or DCs == 'nominal': nf0 = params['nf0'][0] Vdc = Ud * (nf0 - 0.5) - Jd * (nf0 / 2. - 0.5) Edc = DC_ones * Vdc Phidc = ntot * Vdc print >> self.fh_info, '# Edc=', Edc print >> self.fh_info, '# PhiDc=', Phidc elif DCs == 'FLL': nf0 = sum(nf) Vdc = Ud * (nf0 - 0.5) - Jd * (nf0 / 2. - 0.5) Edc = DC_ones * Vdc Phidc = Ud * 0.5 * nf0 * (nf0 - 1.) - Jd * 0.25 * nf0 * (nf0 - 2.) print >> self.fh_info, '# Edc=', Edc print >> self.fh_info, '# PhiDc=', Phidc elif DCs == 'AMF': nf0 = sum(nf) Ueff = Ud * (1 - 1. / (2. * (2. * self.l + 1.))) - Jd * self.l / (2 * self.l + 1.) Edc = DC_ones * Ueff * nf0 Phidc = Ueff * nf0**2 / 2. print >> self.fh_info, '# Edc=', Edc print >> self.fh_info, '# PhiDc=', Phidc elif DCs == 'fixEimp': (Eimp, Olap, Edc) = loadtxt(self.dir + '/Eimp.inp') Phidc = Edc[0] * ntot # Some info up to now print >> self.fh_info, '# l=%d T=%f U=%f J=%f' % ( self.l, T, params['U'][0], self.J) print >> self.fh_info, '# Eimp=', Ed print >> self.fh_info, '# baths=%d' % baths, 'Ns=', Ns print >> self.fh_info, '# ntot=%f' % ntot print >> self.fh_info, '# nf=', nf print >> self.fh_info, '# moment=', moment print >> self.fh_info, '# sinfty=', sinf.tolist() self.fh_info.flush() _Af = [] _Gf = [] _Sig = [] _Delta = [] _eps1 = [] _eps2 = [] _a1 = [] _a2 = [] for b in range( baths ): # over all components of spectral functions (over baths) nf_exact = nf[b] / Ns[b] dsinf = sinf[b] + Ed[b] # the limit of vanishing spectral weight, i.e., when we have only two poles # this formula should always be obeyed #if (dsinf<0 and epsilon[0][0]*nf_exact+epsilon[1][0]*(1-nf_exact)>dsinf): # print >> self.fh_info, 'epsilon was not choosen correctly and the solution can not be found!' # epsilon[1][0] = (dsinf - epsilon[0][0]*nf_exact)/(1-nf_exact) - 0.5 # print >> self.fh_info, 'setting epsilon[1][0] to ', epsilon[1][0] #if (dsinf>0 and epsilon[0][1]*nf_exact+epsilon[1][1]*(1-nf_exact)<dsinf): # print >> self.fh_info, 'epsilon was not choosen correctly and the solution can not be found!' # epsilon[0][1] = (dsinf - epsilon[1][1]*(1-nf_exact))/nf_exact + 0.5 # print >> self.fh_info, 'setting epsilon[0][1] to ', epsilon[0][1] Afo = array(Af[:, b]) m0 = dot(Afo, dh) m1 = dot(Afo, omdh) nc = dot(Afo, fedh) print >> self.fh_info, '#start [%d]: m0=%f m1=%f nc=%f nf_exact=%f' % ( b, m0, m1, nc, nf_exact) # By default we correct N, and normalization, but not s_oo! Correct_N = True Correct_soo = False if params.has_key('correct') and params['correct'][0] == 's_oo': Correct_soo = True if params.has_key('correct') and params['correct'][0] == None: Correct_N = False Correct_soo = False print 'Correct_N=', Correct_N print 'Correct_soo=', Correct_soo if Correct_N: small = 1e-3 a1 = nf_exact - nc if (a1 < -small): # weight below Ef is to large -> need to cut it a bit for im in range(len(om)): (a1n, a2n, m1n) = trycutAf(om[im], om, Afo, dh, omdh, fedh, nf_exact, params['Th'][0], self.fh_info) print >> self.fh_info, '#ca1 [%d]: cat L=%f a1=%f a2=%f m1=%f' % ( b, om[im], a1n, a2n, m1n) if a1n > 0: L1 = om[im] break (a1, a2, m0, m1, nc) = cutAf(L1, om, Afo, dh, omdh, fedh, nf_exact, params['Th'][0], self.fh_info) a2 = 1 - m0 - a1 if (a2 < -small): # lorentzian weight above Ef is to large -> need to cut it a bit for im in range(len(om) - 1, 0, -1): (a1n, a2n, m1n) = trycutAf(om[im], om, Afo, dh, omdh, fedh, nf_exact, params['Th'][0], self.fh_info) print >> self.fh_info, '#ca2 [%d]: cat L=%f a1=%f a2=%f m1=%f' % ( b, om[im], a1n, a2n, m1n) if a2n > 0: L2 = om[im] break (a1, a2, m0, m1, nc) = cutAf(L2, om, Afo, dh, omdh, fedh, nf_exact, params['Th'][0], self.fh_info) # Find u,v,w for this set of parameters (a1, a2, u, v, w) = uvw(m0, m1, nf_exact, nc, dsinf, epsilon) print >> self.fh_info, '# [%d]: miss-nf=%f miss-weight=%f s_oo=%f a1=%f a2=%f u=%f v=%f w=%f' % ( b, nf_exact - nc, 1 - m0, sinf[b], a1, a2, u, v, w) self.fh_info.flush() if Correct_soo: # Here we compute the positions of the two lorentzian # which will allow the exact density, normalization and sigma_oo (success, x, y) = Soluvw(u, v, w) else: success = True m0 = dot(Afo, dh) m1 = dot(Afo, omdh) nc = dot(Afo, fedh) a1 = nf_exact - nc a2 = 1 - m0 - a1 x = 0 y = 1 # If is not possible to get exact density, normalization and sigma_oo by adding # two lorentzians # Will try to cut high-frequency spectral function Lb = None if (not success): # Here we cut the spectral function to make it more symmetric # start cutting at large frequency # cuts until the condition is met L0 = om[-1] # cut at positive frequency (success, a1, a2, x, y) = ww(L0, params['Th'][0], om, Afo, dh, omdh, fedh, nf_exact, epsilon, dsinf, self.fh_info) L0 /= 1.05 for j in range(100): (success, a1, a2, x, y) = ww(L0, params['Th'][0], om, Afo, dh, omdh, fedh, nf_exact, epsilon, dsinf, self.fh_info) if success: break L0 /= 1.05 (successn, a1n, a2n, xn, yn) = ww_cut(L0, params['Th'][0], om, Afo, dh, omdh, fedh, nf_exact, epsilon, dsinf, self.fh_info) if (not success): print "Can't determin a way to get exact nf, norm and sigma_oo. You have to figure out the way to do that!" sys.exit(1) print >> self.fh_info, "# [%d] a1=%f a2=%f x=%f y=%f" % ( b, a1, a2, x, y) eps1_ = epsilon[0][0] + x * (epsilon[0][1] - epsilon[0][0]) eps2_ = epsilon[1][0] + y * (epsilon[1][1] - epsilon[1][0]) print >> self.fh_info, '# [%d]: a1=%f a2=%f eps1=%f eps2=%f' % ( b, a1, a2, eps1_, eps2_) print >> self.fh_info # Actual cutting of the functions and adding the Lorentzians #Afn = Afo # use cutted function if (params.has_key('FUN') and params['FUN'] == 'LOR'): # Adding the Lorentzians if a1 > small: for i in range(len(om)): Afo[i] += -( a1 / pi / (om[i] - eps1_ + params['Gh'][0] * 1j)).imag() if a2 > small: for i in range(len(om)): Afo[i] += -( a2 / pi / (om[i] - eps2_ + params['Gh'][0] * 1j)).imag() else: if a1 > small: for i in range(len(om)): # Adding the Lorentzians Afo[i] += a1 * exp(-( (om[i] - eps1_) / params['Gh'][0])**2) / sqrt( pi * params['Gh'][0]**2) if a2 > small: for i in range(len(om)): Afo[i] += a2 * exp(-( (om[i] - eps2_) / params['Gh'][0])**2) / sqrt( pi * params['Gh'][0]**2) _eps1.append(eps1_) _eps2.append(eps2_) _a1.append(a1) _a2.append(a2) Ac = array(Acd[:, b]) gf = [] sig = [] Delta = [] for i in range(len(om)): gr = -pi * krams.kramarskronig(Afo, om, i) gc = gr - pi * Afo[i] * 1j deltar = -pi * krams.kramarskronig(Ac, om, i) delta = deltar - pi * Ac[i] * 1j gf.append(gc) Delta.append(delta) sigm = om[i] - Ed[b] - 1 / gc - delta - sinf[b] if sigm.imag > 0: sigm = sigm.real - 1e-12j sig.append(sigm) _Af.append(Afo) _Gf.append(gf) _Sig.append(sig) _Delta.append(Delta) if Correct_N: print >> self.fh_info for b in range(baths): print >> self.fh_info, '## [%d]: eps1=%f eps2=%f a1=%f a2=%f' % ( b, _eps1[b], _eps2[b], _a1[b], _a2[b]) self.fh_info.flush() shutil.move(self.dir + self.sparams['gloc'], self.dir + self.sparams['gloc'] + '_o') shutil.move(self.dir + self.sparams['sig'], self.dir + self.sparams['sig'] + '_o') shutil.move(self.dir + self.sparams['AlocOut'], self.dir + self.sparams['AlocOut'] + '_o') fg = open(self.dir + self.sparams['gloc'], 'w') fs = open(self.dir + self.sparams['sig'], 'w') fa = open(self.dir + self.sparams['AlocOut'], 'w') fd = open(self.dir + 'Delta.out', 'w') print >> fs, '# s_oo=', sinf.tolist() print >> fs, '# Edc=', Edc.tolist() print >> fa, first_line for i in range(len(om)): print >> fg, om[i], for b in range(baths): print >> fg, _Gf[b][i].real, _Gf[b][i].imag, print >> fg print >> fs, om[i], for b in range(baths): print >> fs, _Sig[b][i].real, _Sig[b][i].imag, print >> fs print >> fa, om[i], for b in range(baths): print >> fa, _Af[b][i], print >> fa print >> fd, om[i], for b in range(baths): print >> fd, _Delta[b][i].real, _Delta[b][i].imag, print >> fd fg.close() fs.close() fa.close() fd.close() shutil.copy2(self.dir + self.sparams['AlocOut'], self.dir + self.sparams['AlocOut'] + '.' + extn) shutil.copy2(self.dir + self.sparams['AlocOut'] + '_o', self.dir + self.sparams['AlocOut'] + '_o.' + extn) #shutil.copy2(self.dir+self.sparams['sig'], self.dir+self.sparams['sig']+'.'+extn) if os.path.exists(self.dir + 'oca_log.000'): shutil.copy2(self.dir + 'oca_log.000', self.dir + 'oca_log.000' + '.' + extn) else: shutil.copy2(self.dir + 'nohup_imp.out', self.dir + 'nohup_imp.out' + '.' + extn) Ry2eV = 13.60569193 fE = open(self.dir + '/Eorb.dat', 'w') print >> fE, ' Tr(Sigma*G)/2=', Epot print >> fE, ' Phidc=', Phidc print >> fE, ' Fimp-TrlogGimp=', dFimpG print >> fE, ' Tr(Sigma*G)/2-Phidc=', Epot - Phidc if (Q_ETOT): print >> fE, ':EORB ', (Epot - Phidc) / Ry2eV else: print >> fE, ':EORB ', dFimpG / Ry2eV fE.close() fE = open(self.dir + '/sig.out', 'w') print >> fE, '# s_oo=', sinf.tolist() print >> fE, '# Edc=', Edc.tolist() for iom in range(len(om)): print >> fE, ("%20.15f " % om[iom]), for b in range(len(_Sig)): print >> fE, ( "%20.15f %20.15f " % (_Sig[b][iom].real + sinf[b] - Edc[b], _Sig[b][iom].imag)), print >> fE #return (om, _Sig, sinf, Edc, ntot) return ntot