Exemple #1
0
    def write_lattice_problem(self, output):
        # This quantity is potentially distributed over cores, so we need to
        # take that into account here.
        if self.mpi_comm is not None:
            output.write_distributed("glocnew",
                                     self.mpi_strategy.parts(self.glociw),
                                     self.mpi_strategy.shape(self.glociw))
            glociw = self.mpi_strategy.allgather(
                orbspin.extract_diagonal(self.glociw))
            output.write_quantity("glocnew-lattice", glociw)
        else:
            output.write_quantity("glocnew", self.glociw)
            output.write_quantity("glocnew-lattice",
                                  orbspin.extract_diagonal(self.glociw))

        output.write_quantity("dc", self.dc_full)
        output.write_quantity("dc-latt", self.dc_full)
        if self.use_hartree:
            output.write_quantity("sigma-hartree", self.sigma_hartree)

        # FIXME: hack; should got into some write routine of ShellAveraged
        if isinstance(self.dc, doublecounting.ShellAveraged):
            output.write_quantity("ubar", self.dc.ubar)
            output.write_quantity("jbar", self.dc.jbar)

        # The rest is consistent on all nodes
        output.write_quantity("mu", self.mu)
        output.write_quantity("gdensnew", self.densmatrix)
Exemple #2
0
    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)
Exemple #3
0
    def write_before_mu_search(self, output):
        # This quantity is potentially distributed over cores, so we need to
        # take that into account here.
        if self.mpi_comm is not None:
            output.write_distributed("glocold",
                                     self.mpi_strategy.parts(self.glociw),
                                     self.mpi_strategy.shape(self.glociw))
            glociw = self.mpi_strategy.allgather(
                orbspin.extract_diagonal(self.glociw))
            output.write_quantity("glocold-lattice", glociw)
        else:
            output.write_quantity("glocold", self.glociw)
            output.write_quantity("glocold-lattice",
                                  orbspin.extract_diagonal(self.glociw))

        output.write_quantity("gdensold", self.densmatrix)
Exemple #4
0
 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] + list(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] + list(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
Exemple #5
0
 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
Exemple #6
0
    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
Exemple #7
0
 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
Exemple #8
0
 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()
Exemple #9
0
    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
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
    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.
Exemple #13
0
    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)
Exemple #14
0
    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)
Exemple #15
0
    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 range(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)