Example #1
0
    def calc_momentum_distribution(self, mu, beta, with_Sigma, with_dc):
        things_to_read = ['n_k', 'n_orbitals', 'proj_mat',
                          'hopping', 'n_parproj', 'proj_mat_all']
        value_read = self.read_input_from_hdf(
            subgrp=self.bands_data, things_to_read=things_to_read)

        den = numpy.zeros([self.n_k, 2-self.SO, self.n_orbitals[0, 0], self.n_orbitals[0, 0]], numpy.complex_)

        spn = self.spin_block_names[self.SO]

        ikarray = numpy.array(list(range(self.n_k)))
        for ik in mpi.slice_array(ikarray):
            g_latt = self.lattice_gf(
                ik=ik, mu=mu, iw_or_w="iw", beta=beta, with_Sigma=with_Sigma, with_dc=with_dc)
            den0 = g_latt.density()
            g_latt.invert()
            for isp in range(len(spn)):
                den[ik, isp, :, :] = den0[spn[isp]][:, :]
                #
                # eigenvalue
                #
                #  ev[ik, isp, :] =  numpy.linalg.eigvalsh(g_latt[spn[isp]].data[len(g_latt[spn[isp]].mesh)//2, :, :])
        #
        # Collect density matrix across processes
        #
        den = mpi.all_reduce(mpi.world, den, lambda x, y: x + y)

        return den
Example #2
0
        def HT(res):
            import triqs.utility.mpi as mpi
            # First compute the eps_hat array
            eps_hat = epsilon_hat(
                self.dos.eps) if epsilon_hat else numpy.array(
                    [x * numpy.identity(N1) for x in self.dos.eps])
            assert eps_hat.shape[0] == self.dos.eps.shape[
                0], "epsilon_hat function behaves incorrectly"
            assert eps_hat.shape[1] == eps_hat.shape[
                2], "epsilon_hat function behaves incorrectly (result not a square matrix)"
            assert N1 == eps_hat.shape[
                1], "Size of Sigma and of epsilon_hat mismatch"

            res.zero()

            # Perform the sum over eps[i]
            tmp, tmp2 = res.copy(), res.copy()
            tmp << iOmega_n + mu + eta * 1j
            if not (Sigma_fnt):
                tmp -= Sigma
            if field != None: tmp -= field

            # I slice all the arrays on the node. Cf reduce operation below.
            for d, e_h, e in zip(*[
                    mpi.slice_array(A)
                    for A in [self.rho_for_sum, eps_hat, self.dos.eps]
            ]):
                tmp2.copy_from(tmp)
                tmp2 -= e_h
                if Sigma_fnt: tmp2 -= Sigma(e)
                tmp2.invert()
                tmp2 *= d
                res += tmp2
            # sum the res GF of all nodes and returns the results on all nodes...
            # Cf Boost.mpi.python, collective communicator for documentation.
            # The point is that res is pickable, hence can be transmitted between nodes without further code...
            res << mpi.all_reduce(mpi.world, res, lambda x, y: x + y)
            mpi.barrier()
Example #3
0
    def __call__(self,
                 Sigma,
                 mu=0,
                 eta=0,
                 field=None,
                 epsilon_hat=None,
                 result=None,
                 selected_blocks=()):
        """
        - Computes:
           result <- \[ \sum_k (\omega + \mu - field - t(k) - Sigma(k,\omega)) \]
           if result is None, it returns a new GF with the results.
           otherwise, result must be a GF, in which the calculation is done, and which is then returned.
           (this allows chain calculation: SK(mu = mu,Sigma = Sigma, result = G).total_density()
           which computes the sumK into G,  and returns the density of G.

        - Sigma can be a X, or a function k-> X or a function k,eps ->X where:
            - k is expected to be a 1d-numpy array of size self.dim of float,
              containing the k vector in the basis of the RBZ  (i.e.  -0.5< k_i <0.5)
            - eps is t(k)
            - X is anything such that X[BlockName] can be added/subtracted to a GFBloc for BlockName in selected_blocks.
              e.g. X can be a BlockGf(with at least the selected_blocks), or a dictionnary Blockname -> array
              if the array has the same dimension as the GF blocks (for example to add a static Sigma).

        - field: Any k independant object to be added to the GF

        - epsilon_hat: a function of eps_k returning a matrix, the dimensions of Sigma

        - selected_blocks: The calculation is done with the SAME t(k) for all blocks. If this list is not None
          only the blocks in this list are calculated.
          e.g. G and Sigma have block indices 'up' and 'down'.
               if selected_blocks ==None: 'up' and 'down' are calculated
               if selected_blocks == ['up']: only 'up' is calculated. 'down' is 0.


        """

        assert selected_blocks == (), "selected_blocks not supported for now"
        #S = Sigma.view_selected_blocks(selected_blocks) if selected_blocks else Sigma
        #Gres = result if result else Sigma.copy()
        #G = Gres.view_selected_blocks(selected_blocks) if selected_blocks else Gres

        # check Sigma
        # case 1) Sigma is a BlockGf
        if isinstance(Sigma, BlockGf):
            model = Sigma
            Sigma_fnt = False
        # case 2) Sigma is a function returning a BlockGf
        else:
            assert callable(
                Sigma), "If Sigma is not a BlockGf it must be a function"
            Sigma_Nargs = len(inspect.getargspec(Sigma)[0])
            assert Sigma_Nargs <= 2, "Sigma must be a function of k or of k and epsilon"
            if Sigma_Nargs == 1:
                model = Sigma(self.bz_points[0])
            elif Sigma_Nargs == 2:
                model = Sigma(self.bz_points[0], self.hopping[0])
            Sigma_fnt = True

        G = result if result else model.copy()
        assert isinstance(G, BlockGf), "G must be a BlockGf"

        # check input
        assert self.orthogonal_basis, "Local_G: must be orthogonal. non ortho cases not checked."
        assert len(list(set([g.target_shape[0] for i, g in G]))) == 1
        assert self.bz_weights.shape[0] == self.n_kpts(), "Internal Error"
        no = list(set([g.target_shape[0] for i, g in G]))[0]

        # Initialize
        G.zero()
        tmp, tmp2 = G.copy(), G.copy()
        mupat = mu * numpy.identity(no, numpy.complex_)
        tmp << iOmega_n
        if field != None: tmp -= field
        if not Sigma_fnt: tmp -= Sigma  # substract Sigma once for all

        # Loop on k points...
        for w, k, eps_k in zip(*[
                mpi.slice_array(A)
                for A in [self.bz_weights, self.bz_points, self.hopping]
        ]):

            eps_hat = epsilon_hat(eps_k) if epsilon_hat else eps_k
            tmp2 << tmp
            tmp2 -= tmp2.n_blocks * [eps_hat - mupat]

            if Sigma_fnt:
                if Sigma_Nargs == 1: tmp2 -= Sigma(k)
                elif Sigma_Nargs == 2: tmp2 -= Sigma(k, eps_k)

            tmp2.invert()
            tmp2 *= w
            G += tmp2

        G << mpi.all_reduce(mpi.world, G, lambda x, y: x + y)
        mpi.barrier()

        return G
Example #4
0
def get_G_w_from_A_w(A_w,
                     w_points,
                     np_interp_A=None,
                     np_omega=2000,
                     w_min=-10,
                     w_max=10,
                     broadening_factor=1.0):
    r""" Use Kramers-Kronig to determine the retarded Green function :math:`G(\omega)`

    This calculates :math:`G(\omega)` from the spectral function :math:`A(\omega)`.
    A numerical broadening of :math:`bf * i\Delta\omega`
    is used, with the adjustable broadening factor bf (default is 1).
    This function normalizes :math:`A(\omega)`.
    Use mpi to save time.

    Parameters
    ----------
    A_w : array
        Real-frequency spectral function.
    w_points : array
        Real-frequency grid points.
    np_interp_A : int
        Number of grid points A_w should be interpolated on before
        G_w is calculated. The interpolation is performed on a linear
        grid with np_interp_A points from min(w_points) to max(w_points).
    np_omega : int
        Number of equidistant grid points of the output Green function.
    w_min : float
        Start point of output Green function.
    w_max : float
        End point of output Green function.
    broadening_factor : float
        Factor multiplying the broadening :math:`i\Delta\omega`

    Returns
    -------
    G_w : GfReFreq
        TRIQS retarded Green function.
    """

    shape_A = np.shape(A_w)

    if len(shape_A) == 1:
        indices = [0]
        matrix_valued = False
    elif (len(shape_A) == 3) and (shape_A[0] == shape_A[1]):
        indices = list(range(0, shape_A[0]))
        matrix_valued = True
    else:
        raise Exception('A_w has wrong shape, must be n x n x n_w')

    if w_min > w_max:
        raise Exception('w_min must be smaller than w_max')

    if np_interp_A:
        w_points_interp = np.linspace(np.min(w_points),
                                      np.max(w_points), np_interp_A)
        if matrix_valued:
            A_temp = np.zeros((shape_A[0], shape_A[1], np_interp_A), dtype=complex)
            for i in range(shape_A[0]):
                for j in range(shape_A[1]):
                    A_temp[i, j, :] = np.interp(w_points_interp,
                                                w_points, A_w[i, j, :])
            A_w = A_temp
        else:
            A_w = np.interp(w_points_interp, w_points, A_w)
        w_points = w_points_interp

    G_w = GfReFreq(indices=indices, window=(w_min, w_max), n_points=np_omega)
    G_w.zero()

    iw_points = np.array(list(range(len(w_points))))

    for iw in mpi.slice_array(iw_points):
        domega = (w_points[min(len(w_points) - 1, iw + 1)] -
                  w_points[max(0, iw - 1)]) * 0.5
        if matrix_valued:
            for i in range(shape_A[0]):
                for j in range(shape_A[1]):
                    G_w[i, j] << G_w[i, j] + A_w[i, j, iw] * \
                        inverse(Omega - w_points[iw] + 1j * domega * broadening_factor) * domega
        else:
            G_w << G_w + A_w[iw] * \
                inverse(Omega - w_points[iw] + 1j * domega * broadening_factor) * domega

    G_w << mpi.all_reduce(mpi.world, G_w, lambda x, y: x + y)
    mpi.barrier()

    return G_w
Example #5
0
def mpi_all_reduce_g(g):

    g << mpi.all_reduce(mpi.world, g, lambda x, y: x + y)

    return g
             for isp in range(SK.n_spin_blocks[SK.SO])]
block_ind_list = [block for block, inner in gf_struct]
glist = lambda: [
    GfImFreq(indices=inner, mesh=mesh) for block, inner in gf_struct
]

G_latt_orb = BlockGf(name_list=block_ind_list,
                     block_list=glist(),
                     make_copies=False)
G_latt_orb.zero()

for ik in mpi.slice_array(ikarray):
    G_latt_KS = SK.lattice_gf(ik=ik, beta=beta)
    G_latt_KS *= SK.bz_weights[ik]
    for bname, gf in G_latt_orb:
        add_g_ik = gf.copy()
        add_g_ik.zero()
        add_g_ik << SK.downfold(
            ik, 0, bname, G_latt_KS[bname], gf, shells='csc', ir=None)
        gf << gf + add_g_ik

G_latt_orb << mpi.all_reduce(mpi.world, G_latt_orb, lambda x, y: x + y)

mpi.barrier()

if mpi.is_master_node():
    ar['DMFT_results']['Iterations']['G_latt_orb_it' +
                                     str(iteration_offset - 1)] = G_latt_orb
if mpi.is_master_node():
    del ar
Example #7
0
    def extract_G_loc(self,
                      mu=None,
                      iw_or_w='iw',
                      with_Sigma=True,
                      with_dc=True,
                      broadening=None):
        r"""
        """

        # +++ADDED
        # print_time function is inserted in several places for benchmark
        import time
        start = [time.time(), time.time()]

        def print_time(txt):
            # now = time.time()
            # print("time {:>8.5f}sec {:>8.5f}sec @ {}".format(now-start[0], now-start[1], txt))
            # start[0] = now
            pass

        # print("\n=====================")
        # print("Start extract_G_loc")
        print_time("start")

        if mu is None:
            mu = self.chemical_potential

        if iw_or_w == "iw":
            G_loc = [
                self.Sigma_imp_iw[icrsh].copy()
                for icrsh in range(self.n_corr_shells)
            ]  # this list will be returned
            beta = G_loc[0].mesh.beta
            G_loc_inequiv = [
                BlockGf(name_block_generator=[
                    (block, GfImFreq(indices=inner, mesh=G_loc[0].mesh))
                    for block, inner in self.gf_struct_solver[ish].items()
                ],
                        make_copies=False)
                for ish in range(self.n_inequiv_shells)
            ]
        elif iw_or_w == "w":
            G_loc = [
                self.Sigma_imp_w[icrsh].copy()
                for icrsh in range(self.n_corr_shells)
            ]  # this list will be returned
            mesh = G_loc[0].mesh
            G_loc_inequiv = [
                BlockGf(name_block_generator=[
                    (block, GfReFreq(indices=inner, mesh=mesh))
                    for block, inner in self.gf_struct_solver[ish].items()
                ],
                        make_copies=False)
                for ish in range(self.n_inequiv_shells)
            ]

        for icrsh in range(self.n_corr_shells):
            G_loc[icrsh].zero()  # initialize to zero

        print_time("k-sum start")

        ikarray = numpy.array(list(range(self.n_k)))
        for ik in mpi.slice_array(ikarray):
            print_time("in k-loop: k-sum")
            if iw_or_w == 'iw':
                G_latt = self.lattice_gf(ik=ik,
                                         mu=mu,
                                         iw_or_w=iw_or_w,
                                         with_Sigma=with_Sigma,
                                         with_dc=with_dc,
                                         beta=beta)
            elif iw_or_w == 'w':
                mesh_parameters = (G_loc[0].mesh.omega_min,
                                   G_loc[0].mesh.omega_max, len(G_loc[0].mesh))
                G_latt = self.lattice_gf(ik=ik,
                                         mu=mu,
                                         iw_or_w=iw_or_w,
                                         with_Sigma=with_Sigma,
                                         with_dc=with_dc,
                                         broadening=broadening,
                                         mesh=mesh_parameters)
            print_time("in k-loop: lattice_gf")
            G_latt *= self.bz_weights[ik]

            print_time("in k-loop: *bz_weights")
            for icrsh in range(self.n_corr_shells):
                # init temporary storage
                # tmp = G_loc[icrsh].copy()
                # for bname, gf in tmp:
                #     tmp[bname] << self.downfold(
                #         ik, icrsh, bname, G_latt[bname], gf)
                # G_loc[icrsh] += tmp
                # +++MODIFIED
                # Sum up directly into G_loc (no temporary storage is introduced)
                for bname, gf in G_loc[icrsh]:
                    self.downfold(ik,
                                  icrsh,
                                  bname,
                                  G_latt[bname],
                                  gf,
                                  overwrite_gf_inp=True,
                                  fac=+1)
            print_time("in k-loop: downfold")
        print_time("k-sum end")

        # Collect data from mpi
        for icrsh in range(self.n_corr_shells):
            G_loc[icrsh] << mpi.all_reduce(mpi.world, G_loc[icrsh],
                                           lambda x, y: x + y)
        mpi.barrier()
        print_time("mpi.all_reduce")

        # G_loc[:] is now the sum over k projected to the local orbitals.
        # here comes the symmetrisation, if needed:
        if self.symm_op != 0:
            G_loc = self.symmcorr.symmetrize(G_loc)

        # G_loc is rotated to the local coordinate system:
        if self.use_rotations:
            for icrsh in range(self.n_corr_shells):
                for bname, gf in G_loc[icrsh]:
                    G_loc[icrsh][bname] << self.rotloc(
                        icrsh, gf, direction='toLocal')

        # transform to CTQMC blocks:
        for ish in range(self.n_inequiv_shells):
            for block, inner in self.gf_struct_solver[ish].items():
                for ind1 in inner:
                    for ind2 in inner:
                        block_sumk, ind1_sumk = self.solver_to_sumk[ish][(
                            block, ind1)]
                        block_sumk, ind2_sumk = self.solver_to_sumk[ish][(
                            block, ind2)]
                        G_loc_inequiv[ish][block][ind1, ind2] << G_loc[
                            self.inequiv_to_corr[ish]][block_sumk][ind1_sumk,
                                                                   ind2_sumk]

        print_time("symm, rotations, solver_to_sumk")
        # print("End extract_G_loc")
        # print("=====================\n")

        # return only the inequivalent shells:
        return G_loc_inequiv