def compute_dos(self, fixmu, mu=None, totdens=None): #AV: as the gloc method is written for the Matsubara representation, # we pass an ad-hoc frequency to get the retarded Green's function fake_iw = -1j * self.w + self.deltino # the effective leads' self-energy is given by the sum over nleads # we also need to subtract the crystal fields, already included in Delta # at the moment we subtract H(k) or should we rather subtract just the diagonal elements epsilon_d? # this depends on the definition of the Delta obtained from the DFT calculation sw_leads = self.leadsw.sum(1) - self.hk.mean(0) # get the retarded Green's function and extract the dos from the diagonal elements gloc_w = KspaceHamiltonian.gloc(self, fake_iw, 0, sw_leads) self.dos = -1 / np.pi * orbspin.extract_diagonal(gloc_w.imag) siw_leads = self.leadsiw.sum(1) def get_totdens_for_mu(mu): gloc_iw = KspaceHamiltonian.gloc(self, self.iwleads, mu, siw_leads) #np.savetxt("hk_test", self.hk[0,:,0,:,0]) gloc_model = self.eye * 1 / (1j * self.iwleads + mu)[:, None, None, None, None] dens_model = fermi(-mu, self.beta) * self.eye dens_matrix = (gloc_iw - gloc_model).sum(0) / self.beta + dens_model self.densities = orbspin.extract_diagonal(dens_matrix) return self.densities.sum() if fixmu: self.mu = scipy.optimize.brentq( lambda mu: get_totdens_for_mu(mu) - totdens, self.w.min(), self.w.max()) else: self.mu = mu get_totdens_for_mu(mu)
def write_to_node(node, part, pshape=None): if pshape is None: try: pshape = part.shape except AttributeError: pshape = () pslice = qtty_slice if band_dims == 0: pass elif band_dims == 1: # extract the diagonal because that is what should go into HDF5 part = orbspin.extract_diagonal(part) axes_list = [-2, -1] + range(part.ndim - 2) part = part.transpose(axes_list) pshape = pshape[-2:] + pshape[:-4] if pslice is not None: pslice = (slice(None), ) * 2 + (qtty_slice, ) elif band_dims == 2: axes_list = [-4, -3, -2, -1] + range(part.ndim - 4) part = part.transpose(axes_list) pshape = pshape[-4:] + pshape[:-4] if pslice is not None: pslice = (slice(None), ) * 4 + (qtty_slice, ) else: warn("Unclear how to deal with > 2 band dims", UserWarning, 3) if write_everything: node.create_dataset(qtty_name + "/value", data=part) else: #print "SETTING", qtty_slice, "OF", qtty_name, "SHAPE", pshape dataset = node.require_dataset(qtty_name + "/value", shape=pshape, dtype=part.dtype, exact=True) dataset[pslice] = part
def gloc(self, iw, mu, siw, siw_gw=None): ziw = (1j * iw + mu)[:, None, None, None, None] * self.eye - siw orbspin.warn_offdiagonal(siw) zeta = orbspin.extract_diagonal(ziw - self.hloc) d2 = self.d[np.newaxis]**2 glociw = 2 * zeta / d2 * (1 - np.sqrt(1 - d2 / zeta**2)) glociw = orbspin.promote_diagonal(glociw) return glociw
def get(self, siws=None, smoms=None, giws=None, occs=None): if giws is None: # initializing with FLL double counting... better than 0 dc_fll = FullyLocalisedLimit(self.shell_av['densities'], self.shell_av['atom_list'], self.shell_av['u_full']) self.dc_value = dc_fll.get() return self.dc_value for ineq, giw, occ, occ0 in zip(self.ineq_list, giws, occs, self.d_dens_sum): # DOS as "approximated" by first Matsubara frequency iw0 = giw.shape[0] // 2 dos_fermi_level = -1 / np.pi * orbspin.trace(giw[iw0].imag) # impurity density from double occupations. # TODO: this is tied to diagonal hybr dens_impurity = orbspin.promote_diagonal( orbspin.extract_diagonal(occ)) dens_impurity = np.array(dens_impurity).astype(np.float) dens_impurity = np.sum(dens_impurity) # we do not use the non interacting density from Weiss field # but that from the DFT Hamiltonian. # that is a lot more stable # impurity non-interacting density (from Weiss field) #iw = tf.matfreq(beta, 'fermi', imp_result.problem.niwf) #eye = np.eye(imp_result.problem.norbitals * imp_result.problem.nspins) \ # .reshape(imp_result.problem.norbitals, imp_result.problem.nspins, # imp_result.problem.norbitals, imp_result.problem.nspins) #g0iw = orbspin.invert(imp_result.problem.g0iwinv) #g0iw_model = orbspin.invert(1j * iw * eye + imp_result.problem.muimp) #dens_model = lattice.fermi(-imp_result.problem.muimp) # FIXME offdiag #dens0_impurity = (g0iw - g0iw_model).real.sum(0) / imp_result.problem.beta \ # + dens_model if ineq.occ_dc_number is not None: dens0_impurity = ineq.occ_dc_number else: dens0_impurity = occ0 # If the DOS at the Fermi level is large, we do not want to adjust # too much for stability reasons (fudging) if dos_fermi_level > 1.: delta_dc = (dens0_impurity - dens_impurity) / dos_fermi_level else: delta_dc = dens0_impurity - dens_impurity # Fudging factor delta_dc *= 0.2 delta_dc = delta_dc * np.eye(ineq.nd * self.nspins).reshape( ineq.nd, self.nspins, ineq.nd, self.nspins) ineq.d_setpart(self.dc_value, ineq.d_downfold(self.dc_value) - delta_dc) return self.dc_value
def prepare_input(cls, qtty): orbspin.warn_offdiagonal(qtty) qtty = orbspin.extract_diagonal(qtty) if (np.abs(qtty.imag) > 1e-10).any(): warn("Quantity has non-vanishing imaginary part", UserWarning, 2) qtty = qtty.real if qtty.ndim > 2: axes_list = [-2, -1] + range(qtty.ndim - 2) qtty = qtty.transpose(axes_list) return qtty
def get_totdens_for_mu(mu): gloc_iw = KspaceHamiltonian.gloc(self, self.iwleads, mu, siw_leads) #np.savetxt("hk_test", self.hk[0,:,0,:,0]) gloc_model = self.eye * 1 / (1j * self.iwleads + mu)[:, None, None, None, None] dens_model = fermi(-mu, self.beta) * self.eye dens_matrix = (gloc_iw - gloc_model).sum(0) / self.beta + dens_model self.densities = orbspin.extract_diagonal(dens_matrix) return self.densities.sum()
def gloc(self, iw, mu, siw, siw_gw=None): orbspin.warn_offdiagonal(siw) siw = orbspin.extract_diagonal(siw) zeta = (1j * iw + mu)[:, None, None] - siw # compute integral de N(e)/(zeta - e) glociw = self.integrator( self.dos.transpose(1, 2, 0)[None, :, :, :] / (zeta[:, :, :, None] - self.w[None, None, None, :])) glociw = orbspin.promote_diagonal(glociw) return glociw
def get_gsigmaiw(cls, config, problem, result): gsigmaiw = None if config["QMC"]["MeasGSigmaiw"] == 1: gsigmaiw = result["gsigmaiw"] if config["QMC"]["WormMeasGSigmaiw"] == 1: if gsigmaiw is not None: warn("Worm GSigmaiw overwriting Z GSigmaiw", UserWarning, 2) gsigmaiw = result["gsigmaiw-worm"] gsigmaiw = orbspin.extract_diagonal(gsigmaiw.transpose(4,0,1,2,3)) \ .transpose(1,2,0) return gsigmaiw
def siw2gloc(self): self.glociw = self.lattice.gloc(self.my_iwf, self.mu, self.siw_full, self.siw_gw) self.gmodeliw, dmatrix = self.lattice.gmodel(self.my_iwf, self.mu, self.siw_moments, self.smom_gw) self.densmatrix = (self.glociw - self.gmodeliw).sum(0) / self.beta if self.mpi_comm is not None: self.densmatrix = self.mpi_comm.allreduce(self.densmatrix) self.densmatrix += dmatrix self.densities = orbspin.extract_diagonal(self.densmatrix) # Destroy large GW siw for MC cycle self.siw_GW_dyn = None
nat = len(cfg["Atoms"]) nneq = len( [ineq for ineq in args.hf['start'].keys() if ineq[0:4] == u'ineq']) nw = len(w) Siw = np.zeros((0, 2, nw)) DC = np.zeros((0, 2)) istart = 0 for i in xrange(1, nneq + 1): ineq = "ineq-%03d" % i s = iter[ineq]['siw/value'].value nds = args.hf['.config'].attrs['atoms.' + str(i) + '.nd'] nps = args.hf['.config'].attrs['atoms.' + str(i) + '.np'] d = iter['dc-latt/value'].value[istart:nds + nps] d = orbspin.extract_diagonal(d) # We upcast the selfenergy to (nbands x 2 x nw) here. This # could be optimized by passing Np(i) to delta_N and upcasting # from Nd(i) to Nbands for each w individually. Siw = np.vstack((Siw, s, np.zeros((nps, 2, nw)))) DC = np.vstack((DC, d)) istart = nds + nps wien2k.init(cfg, kpoints, sys.stdout) if args.debug: (dnk, g1, g2) = wien2k.delta_N_debug(beta, w, mu_lda, mu_dmft, Hk, Siw, DC, nat, nneq) else: dnk = wien2k.delta_N(beta, w, mu_lda, mu_dmft, Hk, Siw, DC, nat, nneq)
def get_giw(cls, config, problem, result): #typ = "legendre" # FIXME: QMC config does not contain FTtype typ = config["General"]["FTType"] if config["QMC"]["offdiag"] == 1 and typ == "legendre": typ = "legendre_full" if typ == "none": giw = -result["giw-meas"] elif typ == "none_worm": giw = result["giw-worm"] giw = orbspin.extract_diagonal(giw.transpose(4,0,1,2,3)) \ .transpose(1,2,0) elif typ == "plain": ntau = config["QMC"]["Ntau"] tf_matrix = tf.tau2mat(problem.beta, ntau, 'fermi', problem.niw) giw = tf.transform(tf_matrix, result["gtau"], None) elif typ == "legendre": nleg = config["QMC"]["NLegOrder"] tf_matrix = -tf.leg2mat(nleg, problem.niw) giw = tf.transform(tf_matrix, result["gleg"], None, onmismatch=tf.Truncate.tofirst, warn=False) elif typ == "legendre_full": nleg = config["QMC"]["NLegOrder"] tf_matrix = -tf.leg2mat(nleg, problem.niw) nbands = result["gleg-full"].shape[0] giw = np.zeros(shape=(nbands, 2, nbands, 2, problem.niw), dtype=complex) for b in range(0, nbands): for s in range(0, 2): giw[b, s, :, :, :] = tf.transform( tf_matrix, result["gleg-full"][b, s, :, :, :], None, onmismatch=tf.Truncate.tofirst, warn=False) #### the old one #tmp = tf.transform(tf_matrix, result["gleg-full"][b,s,:,:,:], None, #onmismatch=tf.Truncate.tofirst, warn=False) #for b2 in range(0,nbands): #for s2 in range(0,2): #for w in range(0,problem.niw): #print "w", w #giw[b,s,b2,s2,w] = tmp[b2,s2,w] giw = giw.reshape(nbands * 2, nbands * 2, problem.niw) giw_new = np.zeros_like(giw, dtype=complex) for i in range(0, problem.niw): tmp = giw[:, :, i] giw_new[:, :, i] = 0.5 * (tmp.transpose(1, 0) + tmp) giw = giw_new else: raise RuntimeError("Invalid transform type: `%s'" % typ) return giw # copy not necessary here.
def set_problem(self, problem, compute_fourpoint=0): # problem self.problem = problem problem_params = self.config_to_pstring({ "Hamiltonian": problem.interaction.name, "beta": problem.beta, "Nd": problem.norbitals, "ParaMag": int(problem.paramag), "QuantumNumbers": " ".join(problem.interaction.quantum_numbers), "Phonon": int(problem.use_phonons), "g_phonon": " ".join(problem.phonon_g), "omega0": " ".join(problem.phonon_omega0), "Screening": int(problem.use_screening), "Uw": self.Uw, }) symm_params = self.symm_to_pstring(problem.symmetry_moves) all_params = self.param_string + problem_params + symm_params ctqmc.init_paras(all_params) ctqmc.fourpnt = compute_fourpoint # prepare parameters if self.config["QMC"]["offdiag"] == 0: self.ftau = orbspin.promote_diagonal( orbspin.extract_diagonal(self.problem.ftau)) self.ftau = self.problem.ftau.transpose(1, 2, 3, 4, 0) # CT-HYB uses a different convention for muimp #self.muimp = -self.prepare_input(self.problem.muimp) self.muimp = -self.problem.muimp self.umatrix = self.problem.interaction.u_matrix.reshape( self.problem.nflavours, self.problem.nflavours, self.problem.nflavours, self.problem.nflavours) if self.Uw == 0: self.screening = self.problem.screening.transpose(1, 2, 3, 4, 0).real # START DYNAMICAL U if self.Uw == 1: #print " " #print " ****************************" #print " ****** U(w) is active ******" #print " ****************************" ### ===> UPDATE This is now done in the init above. ### ===> UPDATE _Retarded2Shifts = dynamicalU.Replace_Retarded_Interaction_by_a_Shift_of_instantaneous_Potentials(problem.beta, self.umatrix, self.Uw_Mat) ### ===> UPDATE The umatrix shifting is now performed in config.py. ### ===> UPDATE The umatrix shifting is now performed in config.py. ### ===> # This should be executed for all atoms in the first iteration ### ===> try: ### ===> self.iteration_ID # Not defined for first DMFT iteration ### ===> except: ### ===> self.umatrix_original = copy.copy(self.umatrix) ### ===> self.iteration_ID = 1 ### ===> if (self.umatrix==self.umatrix_original).all(): ### ===> self.umatrix = _Retarded2Shifts.shift_instantaneous_densitydensity_potentials(self.umatrix) ### ===> UPDATE The umatrix shifting is now performed in config.py. ### ===> UPDATE The umatrix shifting is now performed in config.py. ### ===> UPDATE This is now done in the init above. ### ===> UPDATE self.screening = _Retarded2Shifts.create_tau_dependent_UV_screening_function(problem.nftau, problem.beta, self.screening) # Perform chemical potential shift in each DMFT iteration if problem.norbitals == 1 and self.epsn == 0: self.muimp = self._Retarded2Shifts.shift_chemical_potential_for_single_band_case( self.muimp, self.umatrix)
def postprocessing(self, siw_method="improved", smom_method="estimate"): # This function is disjoint from the initialisation, because it is a # "derived" quantity that should be computed after averaging over bins fallback = False if siw_method == "dyson": if self.g_diagonal_only: # If the solver is only capable of supplying the spin/orbital- # diagonal terms of the Green's function, we need to make sure # that also only the diagonal terms of G_0 are taken into # account in the Dyson equation, otherwise Sigma erroneously # "counteracts" these terms. As an added performance benefit, # we can use 1/giw rather than the inversion in this case. self.siw = orbspin.promote_diagonal( orbspin.extract_diagonal(self.problem.g0inviw) - 1 / orbspin.extract_diagonal(self.giw)) else: self.siw = self.problem.g0inviw - orbspin.invert(self.giw) elif siw_method == "improved": if self.gsigmaiw is None: warn( "Cannot compute improved estimators - GSigmaiw missing\n" "Falling back to Dyson equation", UserWarning, 2) siw_method = "dyson" fallback = True raise NotImplementedError() # FIXME elif siw_method == 'improved_worm': if self.gsigmaiw is None: warn( "Cannot compute improved estimators - GSigmaiw missing\n" "Falling back to Dyson equation", UserWarning, 2) siw_method = "dyson" fallback = True if self.g_diagonal_only: #TODO: check gsigma sign self.siw = -orbspin.promote_diagonal( orbspin.extract_diagonal(self.gsigmaiw) / orbspin.extract_diagonal(self.giw)) else: raise NotImplementedError("Offdiagonal worm improved \n" "estimators not implemented") else: raise ValueError("unknown siw_method: %s" % siw_method) if smom_method == "extract": warn("Extracting moment of self-energy from the data", UserWarning, 2) self.smom = self.siw[:1].real.copy() elif smom_method == "estimate": if self.smom is None: warn( "Cannot compute smom estimate - rho1 and rho2 missing\n" "Falling back to extraction", UserWarning, 2) smom_method = "extract" fallback = True else: raise ValueError("unknown smom_method: %s" % smom_method) if fallback: self.postprocessing(siw_method, smom_method)