Exemplo n.º 1
0
    def write_imp_problems(self, output):
        g0iw = [orbspin.invert(p.g0inviw) for p in self.imp_problems]

        output.write_quantity("g0iw-full", g0iw)
        output.write_quantity("g0iw", g0iw)
        output.write_quantity("fiw", [p.fiw for p in self.imp_problems])
        output.write_quantity("fmom", [p.fmom for p in self.imp_problems])
        output.write_quantity("ftau", [p.ftau for p in self.imp_problems])
        output.write_quantity("ftau-full", [p.ftau for p in self.imp_problems])
        output.write_quantity("muimp", [p.muimp for p in self.imp_problems])
        output.write_quantity("muimp-full",
                              [p.muimp for p in self.imp_problems])
Exemplo n.º 2
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)
Exemplo n.º 3
0
    def gloc2fiw(self):
        self.imp_problems = []

        if (self.use_gw == 1) and (np.sum(self.siw_full) != 0):
            muimp = (self.mu * self._eye - self.dc_full -
                     self.lattice.hloc.real - self.sigma_hartree -
                     np.sum(self.smom_gw, axis=0) / self.lattice.nkpoints)
        else:
            muimp = (self.mu * self._eye - self.dc_full -
                     self.lattice.hloc.real - self.sigma_hartree)

        atom = 0
        for ineq, siw_block, smom_block in zip(self.ineq_list, self.siw_dd,
                                               self.smom_dd):
            # extract d-d blocks and perform inversion.
            giw_block = ineq.d_downfold(self.glociw)
            g0inviw_block = orbspin.invert(giw_block)

            # Now we "undo" the frequency splitting in order to create
            # the same impurity problem for each core
            if self.mpi_comm is not None:
                g0inviw_block = self.mpi_strategy.allgather(g0inviw_block)

            # Remove self-energy using the Dyson equation.  Note that in
            # d+p or general multi-site, the d-d block is extracted *before*
            # the inversion and therefore the impurity self-energy is used.
            g0inviw_block += siw_block

            # giorgio: Symmetrisierung von G0inviw
            g0inviw_block.real[:, ...] = 0.5 * (g0inviw_block.real[:, ...] +
                                                g0inviw_block.real[::-1, ...])
            g0inviw_block.imag[:, ...] = 0.5 * (g0inviw_block.imag[:, ...] -
                                                g0inviw_block.imag[::-1, ...])

            nbands = g0inviw_block.shape[1]
            niw = g0inviw_block.shape[0]
            g0inviw_block = g0inviw_block.reshape(niw, nbands * 2, nbands * 2)

            g0_new = np.zeros_like(g0inviw_block, dtype=complex)
            for i in range(0, niw):
                tmp = g0inviw_block[i, :, :]
                g0_new[i, :, :] = 0.5 * (tmp.transpose(1, 0) + tmp)

            g0_new = g0_new.reshape(niw, nbands, 2, nbands, 2)
            g0inviw_block = g0_new

            # giorgio   ######

            # in principle, since the bare impurity propagator reads:
            # `1/G_0(iw) =  iw - muimp - F(iw)`, we have a freedom where to put
            # constant shifts.  However, constant terms in `F(iw)` translate to
            # an unresolvable delta peak at `F(tau=0)`. Therefore, we want the
            # zero-th moment of `F(iw)` to vanish, which in turn fixes `muimp`.
            eye_block = ineq.d_downfold(self._eye)

            # The first moment of the hybridisation function is given as
            # - P <H>^2 P + (P <H> P)^2, where P is the downfolding projector,
            # (see Eq. (4.63b) in Markus' thesis), so we cannot simply downfold
            # the second moment of the DOS.
            hloc_block = ineq.d_downfold(self.lattice.hloc)

            # GW Inclusion and Inclusion of GW 0th Moment
            if (self.use_gw == 1) and (np.sum(self.siw_full) != 0):
                norbitals_per_atom = np.int(self.lattice.norbitals /
                                            self.natoms)
                orbits = slice(atom * norbitals_per_atom,
                               (atom + 1) * norbitals_per_atom)
                # => Model based
                if self.use_gw_kaverage == 0:
                    smom_gw2 = np.sum(self.smom_gw[:, orbits, :, orbits, :] *
                                      self.smom_gw[:, orbits, :, orbits, :],
                                      axis=0) / self.lattice.nkpoints
                    fmom1_block = (
                        np.einsum("isjt,jtku->isku", hloc_block, hloc_block) -
                        ineq.d_downfold(self.lattice.hmom2)
                    )  #+ C1 - C2 - C3 - C4 - smom_gw2  # (-) CORRECT HERE!
                    # => K-average based
                else:
                    smom_gw2 = np.sum(self.smom_gw[:, orbits, :, orbits, :] *
                                      self.smom_gw[:, orbits, :, orbits, :],
                                      axis=0) / self.lattice.nkpoints
                    fmom1_block = (
                        np.einsum("isjt,jtku->isku", hloc_block, hloc_block) -
                        ineq.d_downfold(self.lattice.hmom2)
                    ) - smom_gw2  # MINUS SIGN IS CORRECT HERE!
            # No GW in first iteration
            else:
                fmom1_block = (
                    np.einsum("isjt,jtku->isku", hloc_block, hloc_block) -
                    ineq.d_downfold(self.lattice.hmom2))

            muimp_block = ineq.d_downfold(muimp)

            # fiw is defined in the bath picture, which means that:
            #      G0(iw)^{-1} = iw + muimp - F(-iw);   F(-iw) = F*(iw)
            # TODO: check if that is still true with complex F(tau)
            fiw_block = -1j*self.iwf[:,None,None,None,None] * eye_block \
                            + muimp_block - g0inviw_block.conj()
            fiw_model = fmom1_block / (1j *
                                       self.iwf[:, None, None, None, None])

            # GW Inclusion
            if (self.use_gw == 1) and (np.sum(self.siw_full) !=
                                       0) and (self.use_gw_kaverage == 0):
                extension_of = 1
                fiw_block_asymptotic, fiw_model_asymptotic, model_mom1 = self.gw.Reach_asymptotics_for_Hybridization(
                    fiw_block, fiw_model, self.iwf, extension_of)
                ftau_block = iw_to_tau_fast(
                    fiw_block_asymptotic - fiw_model_asymptotic,
                    self.nftau,
                    self.beta,
                    axis=0) - model_mom1 / 2.
                fmom_block = np.asarray(
                    (np.zeros_like(model_mom1), model_mom1))
            else:
                ftau_block = iw_to_tau_fast(
                    fiw_block - fiw_model, self.nftau, self.beta,
                    axis=0) - fmom1_block / 2.
                fmom_block = np.asarray(
                    (np.zeros_like(fmom1_block), fmom1_block))

            imp_problem = impurity.ImpurityProblem(self.beta, g0inviw_block,
                                                   fiw_block, fmom_block,
                                                   ftau_block, muimp_block,
                                                   ineq.dd_int, None, None,
                                                   ineq.symmetry_moves,
                                                   self.paramag)
            self.imp_problems.append(imp_problem)
            atom = atom + 1