Пример #1
0
        def HT(Res) : 
            # First compute the eps_hat array
            eps_hat = Epsilon_Hat(self.dos.eps) if Epsilon_Hat else numpy.array( [ x* numpy.identity (Sigma.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 Sigma.N1 == eps_hat.shape[1], "Size of Sigma and of epsilon_hat mismatch"

            Res.zero()
            Sigma_fnt = callable(Sigma)
            if Sigma_fnt : assert len(inspect.getargspec(Sigma)[0]) ==1, "Sigma function is not of the correct type. See Documentation"

            # Perform the sum over eps[i]
            tmp,tmp2 = Res.copy(),Res.copy()
            tmp <<= GF_Initializers.A_Omega_Plus_B(1,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  itertools.izip (*[MPI.slice_array(A) for A in [self.rho_for_sum,eps_hat,self.dos.eps]]):
                tmp2.copyFrom(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()
Пример #2
0
    def simplepointdensmat(self):


        ntoi = self.names_to_ind[self.SO]
        bln = self.blocnames[self.SO]

        MMat = [numpy.zeros( [self.N_Orbitals[0][ntoi[bl]],self.N_Orbitals[0][ntoi[bl]]], numpy.complex_) for bl in bln] 

        densmat = [ {} for icrsh in xrange(self.N_corr_shells)]
        for icrsh in xrange(self.N_corr_shells):
            for bl in self.blocnames[self.corr_shells[icrsh][4]]:
                densmat[icrsh][bl] = numpy.zeros([self.corr_shells[icrsh][3],self.corr_shells[icrsh][3]], numpy.complex_)

        ikarray=numpy.array(range(self.Nk))
          
        for ik in MPI.slice_array(ikarray):
            
            unchangedsize = all( [ self.N_Orbitals[ik][ntoi[bln[ib]]]==len(MMat[ib]) 
                                   for ib in range(self.NspinblocsGF[self.SO]) ] )
               
            if (not unchangedsize):
                MMat = [numpy.zeros( [self.N_Orbitals[ik][ntoi[bl]],self.N_Orbitals[ik][ntoi[bl]]], numpy.complex_) for bl in bln] 

            for ibl,bl in enumerate(bln):
                ind = ntoi[bl]
                for inu in range(self.N_Orbitals[ik][ind]):
                    if ( (self.Hopping[ik][ind][inu,inu]-self.hfield*(1-2*ibl)) < 0.0): 
                        MMat[ibl][inu,inu] = 1.0
                    else:
                        MMat[ibl][inu,inu] = 0.0 


            for icrsh in range(self.N_corr_shells):
                for ibn,bn in enumerate(self.blocnames[self.corr_shells[icrsh][4]]):
                    isp = self.names_to_ind[self.corr_shells[icrsh][4]][bn]
                    #print ik, bn, isp
                    densmat[icrsh][bn] += self.BZ_weights[ik] * numpy.dot( numpy.dot(self.Proj_Mat[ik][isp][icrsh],MMat[ibn]) , 
                                                                           self.Proj_Mat[ik][isp][icrsh].transpose().conjugate() )

        # get data from nodes:
        for icrsh in range(self.N_corr_shells):
            for sig in densmat[icrsh]:
                densmat[icrsh][sig] = MPI.all_reduce(MPI.world,densmat[icrsh][sig],lambda x,y : x+y)
        MPI.barrier()

                    
        if (self.symm_op!=0): densmat = self.Symm_corr.symmetrise(densmat)

        # Rotate to local coordinate system:
        if (self.use_rotations):
            for icrsh in xrange(self.N_corr_shells):
                for bn in densmat[icrsh]:
                    if (self.rotmat_timeinv[icrsh]==1): densmat[icrsh][bn] = densmat[icrsh][bn].conjugate()
                    densmat[icrsh][bn] = numpy.dot( numpy.dot(self.rotmat[icrsh].conjugate().transpose(),densmat[icrsh][bn]) , 
                                                    self.rotmat[icrsh])
                

        return densmat
Пример #3
0
    def extract_Gloc(self, mu=None, withSigma = True):
        """ 
        extracts the local downfolded Green function at the chemical potential of the class.
        At the end, the local G is rotated from the gloabl coordinate system to the local system.
        if withSigma = False: Sigma is not included => non-interacting local GF
        """

        if (mu is None): mu = self.Chemical_Potential
            
        Gloc = [ self.Sigmaimp[icrsh].copy() for icrsh in xrange(self.N_corr_shells) ]   # this list will be returned  
        for icrsh in xrange(self.N_corr_shells): Gloc[icrsh].zero()                # initialize to zero

        ikarray=numpy.array(range(self.Nk))
        
        for ik in MPI.slice_array(ikarray):
            
            S = self.latticeGF_Matsubara(ik=ik,mu=mu,withSigma = withSigma) 
            S *= self.BZ_weights[ik]

                
            for icrsh in xrange(self.N_corr_shells):
                tmp = Gloc[icrsh].copy()                  # init temporary storage
                for sig,gf in tmp: tmp[sig] <<= self.downfold(ik,icrsh,sig,S[sig],gf)
                Gloc[icrsh] += tmp

        #collect data from MPI:
        for icrsh in xrange(self.N_corr_shells):
            Gloc[icrsh] <<= MPI.all_reduce(MPI.world,Gloc[icrsh],lambda x,y : x+y)
        MPI.barrier()

  
        # Gloc[:] is now the sum over k projected to the local orbitals.
        # here comes the symmetrisation, if needed:   
        if (self.symm_op!=0): Gloc = self.Symm_corr.symmetrise(Gloc)
        
        # Gloc is rotated to the local coordinate system:
        if (self.use_rotations):
            for icrsh in xrange(self.N_corr_shells):
                for sig,gf in Gloc[icrsh]: Gloc[icrsh][sig] <<= self.rotloc(icrsh,gf,direction='toLocal')

        # transform to CTQMC blocks:
        Glocret = [ GF( Name_Block_Generator = [ (a,GFBloc_ImFreq(Indices = al, Mesh = Gloc[0].mesh)) for a,al in self.GFStruct_Solver[i] ],
                        Copy = False) for i in xrange(self.N_inequiv_corr_shells)  ]
        for ish in xrange(self.N_inequiv_corr_shells):
            for ibl in range(len(self.GFStruct_Solver[ish])):
                for i in range(len(self.GFStruct_Solver[ish][ibl][1])):
                    for j in range(len(self.GFStruct_Solver[ish][ibl][1])):
                        bl   = self.GFStruct_Solver[ish][ibl][0]
                        ind1 = self.GFStruct_Solver[ish][ibl][1][i]
                        ind2 = self.GFStruct_Solver[ish][ibl][1][j]
                        Glocret[ish][bl][ind1,ind2] <<= Gloc[self.invshellmap[ish]][self.mapinv[ish][bl]][ind1,ind2]


        # return only the inequivalent shells:
        return Glocret
Пример #4
0
    def density_gf(self, Beta=40):
        """Calculates the density without setting up Gloc. It is useful for Hubbard I, and very fast."""

        densmat = [{} for icrsh in xrange(self.N_corr_shells)]
        for icrsh in xrange(self.N_corr_shells):
            for bl in self.blocnames[self.corr_shells[icrsh][4]]:
                densmat[icrsh][bl] = numpy.zeros(
                    [self.corr_shells[icrsh][3], self.corr_shells[icrsh][3]], numpy.complex_
                )

        ikarray = numpy.array(range(self.Nk))

        for ik in MPI.slice_array(ikarray):

            Gupf = self.latticeGF_Matsubara(ik=ik, mu=self.Chemical_Potential)
            Gupf *= self.BZ_weights[ik]
            dm = Gupf.density()
            MMat = [dm[bl] for bl in self.blocnames[self.SO]]

            for icrsh in range(self.N_corr_shells):
                for ibn, bn in enumerate(self.blocnames[self.corr_shells[icrsh][4]]):
                    isp = self.names_to_ind[self.corr_shells[icrsh][4]][bn]
                    # print ik, bn, isp
                    densmat[icrsh][bn] += numpy.dot(
                        numpy.dot(self.Proj_Mat[ik][isp][icrsh], MMat[ibn]),
                        self.Proj_Mat[ik][isp][icrsh].transpose().conjugate(),
                    )

        # get data from nodes:
        for icrsh in range(self.N_corr_shells):
            for sig in densmat[icrsh]:
                densmat[icrsh][sig] = MPI.all_reduce(MPI.world, densmat[icrsh][sig], lambda x, y: x + y)
        MPI.barrier()

        if self.symm_op != 0:
            densmat = self.Symm_corr.symmetrise(densmat)

        # Rotate to local coordinate system:
        if self.use_rotations:
            for icrsh in xrange(self.N_corr_shells):
                for bn in densmat[icrsh]:
                    if self.rotmat_timeinv[icrsh] == 1:
                        densmat[icrsh][bn] = densmat[icrsh][bn].conjugate()
                    densmat[icrsh][bn] = numpy.dot(
                        numpy.dot(self.rotmat[icrsh].conjugate().transpose(), densmat[icrsh][bn]), self.rotmat[icrsh]
                    )

        return densmat
Пример #5
0
        def HT(Res):
            # First compute the eps_hat array
            eps_hat = Epsilon_Hat(
                self.dos.eps) if Epsilon_Hat else numpy.array(
                    [x * numpy.identity(Sigma.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 Sigma.N1 == eps_hat.shape[
                1], "Size of Sigma and of epsilon_hat mismatch"

            Res.zero()
            Sigma_fnt = callable(Sigma)
            if Sigma_fnt:
                assert len(
                    inspect.getargspec(Sigma)[0]
                ) == 1, "Sigma function is not of the correct type. See Documentation"

            # Perform the sum over eps[i]
            tmp, tmp2 = Res.copy(), Res.copy()
            tmp <<= GF_Initializers.A_Omega_Plus_B(1, 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 itertools.izip(*[
                    MPI.slice_array(A)
                    for A in [self.rho_for_sum, eps_hat, self.dos.eps]
            ]):
                tmp2.copyFrom(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()
Пример #6
0
    def total_density(self, mu):
        """
        Calculates the total charge for the energy window for a given mu. Since in general N_Orbitals depends on k, 
        the calculation is done in the following order:
        G_aa'(k,iw) -> n(k) = Tr G_aa'(k,iw) -> sum_k n_k 
        
        mu: chemical potential
        
        The calculation is done in the global coordinate system, if distinction is made between local/global!
        """

        dens = 0.0
        ikarray = numpy.array(range(self.Nk))

        for ik in MPI.slice_array(ikarray):

            S = self.latticeGF_Matsubara(ik=ik, mu=mu)
            dens += self.BZ_weights[ik] * S.total_density()

        # collect data from MPI:
        dens = MPI.all_reduce(MPI.world, dens, lambda x, y: x + y)
        MPI.barrier()

        return dens
Пример #7
0
    def __call__(self,
                 Sigma,
                 mu=0,
                 eta=0,
                 Field=None,
                 Epsilon_Hat=None,
                 Res=None,
                 SelectedBlocks=()):
        """ 
	- Computes :
	   Res <- \[ \sum_k (\omega + \mu - Field - t(k) - Sigma(k,\omega)) \]
           if Res is None, it returns a new GF with the results.
           otherwise, Res must be a GF, in which the calculation is done, and which is then returned.
           (this allows chain calculation : SK(mu = mu,Sigma = Sigma, Res = 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 SelectedBlocks.
	      e.g. X can be a GF (with at least the SelectedBlocks), 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

        - SelectedBlocks : 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 SelectedBlocks ==None : 'up' and 'down' are calculated
	       if SelectedBlocks == ['up'] : only 'up' is calculated. 'down' is 0.


        """
        S = Sigma.View_SelectedBlocks(
            SelectedBlocks) if SelectedBlocks else Sigma
        Gres = Res if Res else Sigma.copy()
        G = Gres.View_SelectedBlocks(
            SelectedBlocks) if SelectedBlocks else Gres

        # check input
        assert self.Orthogonal_Basis, "Local_G : must be orthogonal. non ortho cases not checked."
        assert isinstance(G, GF), "G must be a GF"
        assert len(list(set([g.N1 for i, g in G]))) == 1
        assert self.BZ_weights.shape[0] == self.N_kpts(), "Internal Error"
        no = list(set([g.N1 for i, g in G]))[0]
        Sigma_Nargs = len(
            inspect.getargspec(Sigma)[0]) if callable(Sigma) else 0
        assert Sigma_Nargs <= 2, "Sigma function is not of the correct type. See Documentation"

        # 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 Sigma_Nargs == 0: tmp -= Sigma  # substract Sigma once for all

        # Loop on k points...
        for w, k, eps_k in izip(*[
                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.NBlocks * [eps_hat - mupat]

            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 Gres
Пример #8
0
    def __call__ (self, Sigma, mu=0, eta = 0, Field = None, Epsilon_Hat=None, Res = None, SelectedBlocks = ()):
	""" 
	- Computes :
	   Res <- \[ \sum_k (\omega + \mu - Field - t(k) - Sigma(k,\omega)) \]
           if Res is None, it returns a new GF with the results.
           otherwise, Res must be a GF, in which the calculation is done, and which is then returned.
           (this allows chain calculation : SK(mu = mu,Sigma = Sigma, Res = 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 SelectedBlocks.
	      e.g. X can be a GF (with at least the SelectedBlocks), 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

        - SelectedBlocks : 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 SelectedBlocks ==None : 'up' and 'down' are calculated
	       if SelectedBlocks == ['up'] : only 'up' is calculated. 'down' is 0.


        """
        S = Sigma.View_SelectedBlocks(SelectedBlocks) if SelectedBlocks else Sigma
        Gres = Res if Res else Sigma.copy() 
        G = Gres.View_SelectedBlocks(SelectedBlocks) if SelectedBlocks else Gres

        # check input
        assert self.Orthogonal_Basis, "Local_G : must be orthogonal. non ortho cases not checked."
        assert isinstance(G,GF), "G must be a GF"
        assert len(list(set([g.N1 for i,g in G]))) == 1
        assert self.BZ_weights.shape[0] == self.N_kpts(), "Internal Error"
        no = list(set([g.N1 for i,g in G]))[0]
        Sigma_Nargs = len(inspect.getargspec(Sigma)[0]) if callable (Sigma) else 0
        assert Sigma_Nargs <=2 , "Sigma function is not of the correct type. See Documentation"

        # 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 Sigma_Nargs==0: tmp -= Sigma  # substract Sigma once for all

        # Loop on k points...
        for w, k, eps_k in izip(*[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.NBlocks * [eps_hat - mupat]

            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 Gres
Пример #9
0
    def partial_charges(self):
        """Calculates the orbitally-resolved density matrix for all the orbitals considered in the input.
           The theta-projectors are used, hence case.parproj data is necessary"""

        #thingstoread = ['Dens_Mat_below','N_parproj','Proj_Mat_pc','rotmat_all']
        #retval = self.read_input_from_HDF(SubGrp=self.ParProjdata,thingstoread=thingstoread)
        retval = self.read_ParProj_input_from_HDF()
        if not retval: return retval
        if self.symm_op:
            self.Symm_par = Symmetry(self.HDFfile, subgroup=self.Symmpardata)

        # Density matrix in the window
        bln = self.blocnames[self.SO]
        ntoi = self.names_to_ind[self.SO]
        self.Dens_Mat_window = [[
            numpy.zeros([self.shells[ish][3], self.shells[ish][3]],
                        numpy.complex_) for ish in range(self.N_shells)
        ] for isp in range(len(bln))]  # init the density matrix

        mu = self.Chemical_Potential
        GFStruct_proj = [[(al, range(self.shells[i][3])) for al in bln]
                         for i in xrange(self.N_shells)]
        if hasattr(self, "Sigmaimp"):
            Gproj = [
                GF(Name_Block_Generator=[
                    (a, GFBloc_ImFreq(Indices=al, Mesh=self.Sigmaimp[0].mesh))
                    for a, al in GFStruct_proj[ish]
                ],
                   Copy=False) for ish in xrange(self.N_shells)
            ]
        else:
            Gproj = [
                GF(Name_Block_Generator=[(a, GFBloc_ImFreq(Indices=al,
                                                           Beta=40))
                                         for a, al in GFStruct_proj[ish]],
                   Copy=False) for ish in xrange(self.N_shells)
            ]

        for ish in xrange(self.N_shells):
            Gproj[ish].zero()

        ikarray = numpy.array(range(self.Nk))
        #print MPI.rank, MPI.slice_array(ikarray)
        #print "K-Sum starts on node",MPI.rank," at ",datetime.now()

        for ik in MPI.slice_array(ikarray):
            #print MPI.rank, ik, datetime.now()
            S = self.latticeGF_Matsubara(ik=ik, mu=mu)
            S *= self.BZ_weights[ik]

            for ish in xrange(self.N_shells):
                tmp = Gproj[ish].copy()
                for ir in xrange(self.N_parproj[ish]):
                    for sig, gf in tmp:
                        tmp[sig] <<= self.downfold_pc(ik, ir, ish, sig, S[sig],
                                                      gf)
                    Gproj[ish] += tmp

        #print "K-Sum done on node",MPI.rank," at ",datetime.now()
        #collect data from MPI:
        for ish in xrange(self.N_shells):
            Gproj[ish] <<= MPI.all_reduce(MPI.world, Gproj[ish],
                                          lambda x, y: x + y)
        MPI.barrier()

        #print "Data collected on node",MPI.rank," at ",datetime.now()

        # Symmetrisation:
        if (self.symm_op != 0): Gproj = self.Symm_par.symmetrise(Gproj)
        #print "Symmetrisation done on node",MPI.rank," at ",datetime.now()

        for ish in xrange(self.N_shells):

            # Rotation to local:
            if (self.use_rotations):
                for sig, gf in Gproj[ish]:
                    Gproj[ish][sig] <<= self.rotloc_all(ish,
                                                        gf,
                                                        direction='toLocal')

            isp = 0
            for sig, gf in Gproj[ish]:  #dmg.append(Gproj[ish].density()[sig])
                self.Dens_Mat_window[isp][ish] = Gproj[ish].density()[sig]
                isp += 1

        # add Density matrices to get the total:
        Dens_Mat = [[
            self.Dens_Mat_below[ntoi[bln[isp]]][ish] +
            self.Dens_Mat_window[isp][ish] for ish in range(self.N_shells)
        ] for isp in range(len(bln))]

        return Dens_Mat
Пример #10
0
    def DOSpartial(self, broadening=0.01):
        """calculates the orbitally-resolved DOS"""

        assert hasattr(self, "Sigmaimp"), "Set Sigma First!!"

        #thingstoread = ['Dens_Mat_below','N_parproj','Proj_Mat_pc','rotmat_all']
        #retval = self.read_input_from_HDF(SubGrp=self.ParProjdata, thingstoread=thingstoread)
        retval = self.read_ParProj_input_from_HDF()
        if not retval: return retval
        if self.symm_op:
            self.Symm_par = Symmetry(self.HDFfile, subgroup=self.Symmpardata)

        mu = self.Chemical_Potential

        GFStruct_proj = [[(al, range(self.shells[i][3]))
                          for al in self.blocnames[self.SO]]
                         for i in xrange(self.N_shells)]
        Gproj = [
            GF(Name_Block_Generator=[
                (a, GFBloc_ReFreq(Indices=al, Mesh=self.Sigmaimp[0].mesh))
                for a, al in GFStruct_proj[ish]
            ],
               Copy=False) for ish in xrange(self.N_shells)
        ]
        for ish in range(self.N_shells):
            Gproj[ish].zero()

        Msh = [x for x in self.Sigmaimp[0].mesh]
        N_om = len(Msh)

        DOS = {}
        for bn in self.blocnames[self.SO]:
            DOS[bn] = numpy.zeros([N_om], numpy.float_)

        DOSproj = [{} for ish in range(self.N_shells)]
        DOSproj_orb = [{} for ish in range(self.N_shells)]
        for ish in range(self.N_shells):
            for bn in self.blocnames[self.SO]:
                dl = self.shells[ish][3]
                DOSproj[ish][bn] = numpy.zeros([N_om], numpy.float_)
                DOSproj_orb[ish][bn] = numpy.zeros([dl, dl, N_om],
                                                   numpy.float_)

        ikarray = numpy.array(range(self.Nk))

        for ik in MPI.slice_array(ikarray):

            S = self.latticeGF_realfreq(ik=ik, mu=mu, broadening=broadening)
            S *= self.BZ_weights[ik]

            # non-projected DOS
            for iom in range(N_om):
                for sig, gf in S:
                    DOS[sig][iom] += gf._data.array[:, :, iom].imag.trace() / (
                        -3.1415926535)

            #projected DOS:
            for ish in xrange(self.N_shells):
                tmp = Gproj[ish].copy()
                for ir in xrange(self.N_parproj[ish]):
                    for sig, gf in tmp:
                        tmp[sig] <<= self.downfold_pc(ik, ir, ish, sig, S[sig],
                                                      gf)
                    Gproj[ish] += tmp

        # collect data from MPI:
        for sig in DOS:
            DOS[sig] = MPI.all_reduce(MPI.world, DOS[sig], lambda x, y: x + y)
        for ish in xrange(self.N_shells):
            Gproj[ish] <<= MPI.all_reduce(MPI.world, Gproj[ish],
                                          lambda x, y: x + y)
        MPI.barrier()

        if (self.symm_op != 0): Gproj = self.Symm_par.symmetrise(Gproj)

        # rotation to local coord. system:
        if (self.use_rotations):
            for ish in xrange(self.N_shells):
                for sig, gf in Gproj[ish]:
                    Gproj[ish][sig] <<= self.rotloc_all(ish,
                                                        gf,
                                                        direction='toLocal')

        for ish in range(self.N_shells):
            for sig, gf in Gproj[ish]:
                for iom in range(N_om):
                    DOSproj[ish][sig][
                        iom] += gf._data.array[:, :, iom].imag.trace() / (
                            -3.1415926535)
                DOSproj_orb[ish][
                    sig][:, :, :] += gf._data.array[:, :, :].imag / (
                        -3.1415926535)

        if (MPI.IS_MASTER_NODE()):
            # output to files
            for bn in self.blocnames[self.SO]:
                f = open('./DOScorr%s.dat' % bn, 'w')
                for i in range(N_om):
                    f.write("%s    %s\n" % (Msh[i], DOS[bn][i]))
                f.close()

                # partial
                for ish in range(self.N_shells):
                    f = open('DOScorr%s_proj%s.dat' % (bn, ish), 'w')
                    for i in range(N_om):
                        f.write("%s    %s\n" % (Msh[i], DOSproj[ish][bn][i]))
                    f.close()

                    for i in range(self.shells[ish][3]):
                        for j in range(i, self.shells[ish][3]):
                            Fname = './DOScorr' + bn + '_proj' + str(
                                ish) + '_' + str(i) + '_' + str(j) + '.dat'
                            f = open(Fname, 'w')
                            for iom in range(N_om):
                                f.write("%s    %s\n" %
                                        (Msh[iom], DOSproj_orb[ish][bn][i, j,
                                                                        iom]))
                            f.close()
Пример #11
0
    def partial_charges(self):
        """Calculates the orbitally-resolved density matrix for all the orbitals considered in the input.
           The theta-projectors are used, hence case.parproj data is necessary"""
           

        #thingstoread = ['Dens_Mat_below','N_parproj','Proj_Mat_pc','rotmat_all']
        #retval = self.read_input_from_HDF(SubGrp=self.ParProjdata,thingstoread=thingstoread)
        retval = self.read_ParProj_input_from_HDF()
        if not retval: return retval
        if self.symm_op: self.Symm_par = Symmetry(self.HDFfile,subgroup=self.Symmpardata)
        
        # Density matrix in the window
        bln = self.blocnames[self.SO]
        ntoi = self.names_to_ind[self.SO]
        self.Dens_Mat_window = [ [numpy.zeros([self.shells[ish][3],self.shells[ish][3]],numpy.complex_) for ish in range(self.N_shells)]   
                                 for isp in range(len(bln)) ]    # init the density matrix

        mu = self.Chemical_Potential
        GFStruct_proj = [ [ (al, range(self.shells[i][3])) for al in bln ]  for i in xrange(self.N_shells) ]
        if hasattr(self,"Sigmaimp"):
            Gproj = [GF(Name_Block_Generator = [ (a,GFBloc_ImFreq(Indices = al, Mesh = self.Sigmaimp[0].mesh)) for a,al in GFStruct_proj[ish] ], Copy = False)
                     for ish in xrange(self.N_shells)]
        else:
            Gproj = [GF(Name_Block_Generator = [ (a,GFBloc_ImFreq(Indices = al, Beta = 40)) for a,al in GFStruct_proj[ish] ], Copy = False)
                     for ish in xrange(self.N_shells)]

        for ish in xrange(self.N_shells): Gproj[ish].zero()

        ikarray=numpy.array(range(self.Nk))
        #print MPI.rank, MPI.slice_array(ikarray)
        #print "K-Sum starts on node",MPI.rank," at ",datetime.now()
        
        for ik in MPI.slice_array(ikarray):
            #print MPI.rank, ik, datetime.now()
            S = self.latticeGF_Matsubara(ik=ik,mu=mu)
            S *= self.BZ_weights[ik]

            for ish in xrange(self.N_shells):
                tmp = Gproj[ish].copy()
                for ir in xrange(self.N_parproj[ish]):
                    for sig,gf in tmp: tmp[sig] <<= self.downfold_pc(ik,ir,ish,sig,S[sig],gf)
                    Gproj[ish] += tmp
        
        #print "K-Sum done on node",MPI.rank," at ",datetime.now()
        #collect data from MPI:
        for ish in xrange(self.N_shells):
            Gproj[ish] <<= MPI.all_reduce(MPI.world,Gproj[ish],lambda x,y : x+y)
        MPI.barrier()

        #print "Data collected on node",MPI.rank," at ",datetime.now()

        # Symmetrisation:
        if (self.symm_op!=0): Gproj = self.Symm_par.symmetrise(Gproj)
        #print "Symmetrisation done on node",MPI.rank," at ",datetime.now()
        
        for ish in xrange(self.N_shells):

            # Rotation to local:
            if (self.use_rotations):
                for sig,gf in Gproj[ish]: Gproj[ish][sig] <<= self.rotloc_all(ish,gf,direction='toLocal')

            isp = 0
            for sig,gf in Gproj[ish]: #dmg.append(Gproj[ish].density()[sig])
                self.Dens_Mat_window[isp][ish] = Gproj[ish].density()[sig]
                isp+=1
       
        # add Density matrices to get the total:
        Dens_Mat = [ [ self.Dens_Mat_below[ntoi[bln[isp]]][ish]+self.Dens_Mat_window[isp][ish] for ish in range(self.N_shells)]
                     for isp in range(len(bln)) ]

        return Dens_Mat
Пример #12
0
    def DOSpartial(self,broadening=0.01):
        """calculates the orbitally-resolved DOS"""

        assert hasattr(self,"Sigmaimp"), "Set Sigma First!!"

        #thingstoread = ['Dens_Mat_below','N_parproj','Proj_Mat_pc','rotmat_all']
        #retval = self.read_input_from_HDF(SubGrp=self.ParProjdata, thingstoread=thingstoread)
        retval = self.read_ParProj_input_from_HDF()
        if not retval: return retval
        if self.symm_op: self.Symm_par = Symmetry(self.HDFfile,subgroup=self.Symmpardata)

        mu = self.Chemical_Potential

        GFStruct_proj = [ [ (al, range(self.shells[i][3])) for al in self.blocnames[self.SO] ]  for i in xrange(self.N_shells) ]
        Gproj = [GF(Name_Block_Generator = [ (a,GFBloc_ReFreq(Indices = al, Mesh = self.Sigmaimp[0].mesh)) for a,al in GFStruct_proj[ish] ], Copy = False ) 
                 for ish in xrange(self.N_shells)]
        for ish in range(self.N_shells): Gproj[ish].zero()

        Msh = [x for x in self.Sigmaimp[0].mesh]
        N_om = len(Msh)

        DOS = {}
        for bn in self.blocnames[self.SO]:
            DOS[bn] = numpy.zeros([N_om],numpy.float_)

        DOSproj     = [ {} for ish in range(self.N_shells) ]
        DOSproj_orb = [ {} for ish in range(self.N_shells) ]
        for ish in range(self.N_shells):
            for bn in self.blocnames[self.SO]:
                dl = self.shells[ish][3]
                DOSproj[ish][bn] = numpy.zeros([N_om],numpy.float_)
                DOSproj_orb[ish][bn] = numpy.zeros([dl,dl,N_om],numpy.float_)

        ikarray=numpy.array(range(self.Nk))

        for ik in MPI.slice_array(ikarray):

            S = self.latticeGF_realfreq(ik=ik,mu=mu,broadening=broadening)
            S *= self.BZ_weights[ik]

            # non-projected DOS
            for iom in range(N_om): 
                for sig,gf in S: DOS[sig][iom] += gf._data.array[:,:,iom].imag.trace()/(-3.1415926535)
               
            #projected DOS:
            for ish in xrange(self.N_shells):
                tmp = Gproj[ish].copy()
                for ir in xrange(self.N_parproj[ish]):
                    for sig,gf in tmp: tmp[sig] <<= self.downfold_pc(ik,ir,ish,sig,S[sig],gf)
                    Gproj[ish] += tmp
                   
        # collect data from MPI:
        for sig in DOS:
            DOS[sig] = MPI.all_reduce(MPI.world,DOS[sig],lambda x,y : x+y)
        for ish in xrange(self.N_shells):
            Gproj[ish] <<= MPI.all_reduce(MPI.world,Gproj[ish],lambda x,y : x+y)
        MPI.barrier()        
                  
        if (self.symm_op!=0): Gproj = self.Symm_par.symmetrise(Gproj)

        # rotation to local coord. system:
        if (self.use_rotations):
            for ish in xrange(self.N_shells):
                for sig,gf in Gproj[ish]: Gproj[ish][sig] <<= self.rotloc_all(ish,gf,direction='toLocal')
                
        for ish in range(self.N_shells):
            for sig,gf in Gproj[ish]:  
                for iom in range(N_om): DOSproj[ish][sig][iom] += gf._data.array[:,:,iom].imag.trace()/(-3.1415926535)
                DOSproj_orb[ish][sig][:,:,:] += gf._data.array[:,:,:].imag / (-3.1415926535)
	    

        if (MPI.IS_MASTER_NODE()):
            # output to files
            for bn in self.blocnames[self.SO]:
                f=open('./DOScorr%s.dat'%bn, 'w')
                for i in range(N_om): f.write("%s    %s\n"%(Msh[i],DOS[bn][i]))
                f.close()    

                # partial
                for ish in range(self.N_shells):
                    f=open('DOScorr%s_proj%s.dat'%(bn,ish),'w')
                    for i in range(N_om): f.write("%s    %s\n"%(Msh[i],DOSproj[ish][bn][i]))
                    f.close()
 
                    for i in range(self.shells[ish][3]):
                        for j in range(i,self.shells[ish][3]):
                            Fname = './DOScorr'+bn+'_proj'+str(ish)+'_'+str(i)+'_'+str(j)+'.dat'
                            f=open(Fname,'w')
                            for iom in range(N_om): f.write("%s    %s\n"%(Msh[iom],DOSproj_orb[ish][bn][i,j,iom]))
                            f.close()
Пример #13
0
    def calc_DensityCorrection(self, Filename="densmat.dat"):
        """ Calculates the density correction in order to feed it back to the DFT calculations."""

        assert type(Filename) == StringType, "Filename has to be a string!"

        ntoi = self.names_to_ind[self.SO]
        bln = self.blocnames[self.SO]

        # Set up deltaN:
        deltaN = {}
        for ib in bln:
            deltaN[ib] = [
                numpy.zeros([self.N_Orbitals[ik][ntoi[ib]], self.N_Orbitals[ik][ntoi[ib]]], numpy.complex_)
                for ik in range(self.Nk)
            ]

        ikarray = numpy.array(range(self.Nk))

        dens = {}
        for ib in bln:
            dens[ib] = 0.0

        for ik in MPI.slice_array(ikarray):

            S = self.latticeGF_Matsubara(ik=ik, mu=self.Chemical_Potential)
            for sig, g in S:
                deltaN[sig][ik] = S[sig].density()
                dens[sig] += self.BZ_weights[ik] * S[sig].total_density()

        # put MPI Barrier:
        for sig in deltaN:
            for ik in range(self.Nk):
                deltaN[sig][ik] = MPI.all_reduce(MPI.world, deltaN[sig][ik], lambda x, y: x + y)
            dens[sig] = MPI.all_reduce(MPI.world, dens[sig], lambda x, y: x + y)
        MPI.barrier()

        # now save to file:
        if MPI.IS_MASTER_NODE():
            if self.SP == 0:
                f = open(Filename, "w")
            else:
                f = open(Filename + "up", "w")
                f1 = open(Filename + "dn", "w")
            # write chemical potential (in Rydberg):
            f.write("%.14f\n" % (self.Chemical_Potential / self.EnergyUnit))
            if self.SP != 0:
                f1.write("%.14f\n" % (self.Chemical_Potential / self.EnergyUnit))
            # write beta in ryderg-1
            f.write("%.14f\n" % (S.Beta * self.EnergyUnit))
            if self.SP != 0:
                f1.write("%.14f\n" % (S.Beta * self.EnergyUnit))
            if self.SP == 0:
                for ik in range(self.Nk):
                    f.write("%s\n" % self.N_Orbitals[ik][0])
                    for inu in range(self.N_Orbitals[ik][0]):
                        for imu in range(self.N_Orbitals[ik][0]):
                            valre = (deltaN["up"][ik][inu, imu].real + deltaN["down"][ik][inu, imu].real) / 2.0
                            valim = (deltaN["up"][ik][inu, imu].imag + deltaN["down"][ik][inu, imu].imag) / 2.0
                            f.write("%.14f  %.14f " % (valre, valim))
                        f.write("\n")
                    f.write("\n")
                f.close()
            elif (self.SP == 1) and (self.SO == 0):
                for ik in range(self.Nk):
                    f.write("%s\n" % self.N_Orbitals[ik][0])
                    for inu in range(self.N_Orbitals[ik][0]):
                        for imu in range(self.N_Orbitals[ik][0]):
                            f.write(
                                "%.14f  %.14f " % (deltaN["up"][ik][inu, imu].real, deltaN["up"][ik][inu, imu].imag)
                            )
                        f.write("\n")
                    f.write("\n")
                f.close()
                for ik in range(self.Nk):
                    f1.write("%s\n" % self.N_Orbitals[ik][1])
                    for inu in range(self.N_Orbitals[ik][1]):
                        for imu in range(self.N_Orbitals[ik][1]):
                            f1.write(
                                "%.14f  %.14f " % (deltaN["down"][ik][inu, imu].real, deltaN["down"][ik][inu, imu].imag)
                            )
                        f1.write("\n")
                    f1.write("\n")
                f1.close()
            else:
                for ik in range(self.Nk):
                    f.write("%s\n" % self.N_Orbitals[ik][0])
                    for inu in range(self.N_Orbitals[ik][0]):
                        for imu in range(self.N_Orbitals[ik][0]):
                            f.write(
                                "%.14f  %.14f " % (deltaN["ud"][ik][inu, imu].real, deltaN["ud"][ik][inu, imu].imag)
                            )
                        f.write("\n")
                    f.write("\n")
                f.close()
                for ik in range(self.Nk):
                    f1.write("%s\n" % self.N_Orbitals[ik][0])
                    for inu in range(self.N_Orbitals[ik][0]):
                        for imu in range(self.N_Orbitals[ik][0]):
                            f1.write(
                                "%.14f  %.14f " % (deltaN["ud"][ik][inu, imu].real, deltaN["ud"][ik][inu, imu].imag)
                            )
                        f1.write("\n")
                    f1.write("\n")
                f1.close()

        return deltaN, dens
Пример #14
0
    def __call__ (self, Sigma, mu=0, eta = 0, Field = None, Res = None, SelectedBlocks = () ):
	""" 
	- Computes :
	   Res <- \[ \sum_k (\omega + \mu - Field - t(k) - Sigma(k,\omega)) \]
           if Res is None, it returns a new GF with the results.
           otherwise, Res must be a GF, in which the calculation is done, and which is then returned.
           (this allows chain calculation : SK(mu = mu,Sigma = Sigma, Res = 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 SelectedBlocks.
	      e.g. X can be a GF (with at least the SelectedBlocks), 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  Array_with_GF_Indices to be added to the GF 

        - SelectedBlocks : 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 SelectedBlocks ==None : 'up' and 'down' are calculated
	       if SelectedBlocks == ['up'] : only 'up' is calculated. 'down' is 0.

         """
        if Field : assert isinstance(Field,Array_with_GF_Indices) , " Field must be a  Array_with_GF_Indices object. Cf Example"
        S = Sigma.View_SelectedBlocks(SelectedBlocks) if SelectedBlocks else Sigma
        Gres = Res if Res else Sigma.copy() 
        G = Gres.View_SelectedBlocks(SelectedBlocks) if SelectedBlocks else Gres

        # check input
        assert self.Orthogonal_Basis, "Local_G : must be orthogonal. non ortho cases not checked."
        assert isinstance(G,GF), "G must be a GF"
        assert list(set([ g.N1 for i,g in G])) == [self.Hopping.shape[1]],"G size and hopping size mismatch"
        assert self.BZ_weights.shape[0] == self.N_kpts(), "Internal Error"
        Sigma_Nargs = len(inspect.getargspec(Sigma)[0]) if callable (Sigma) else 0
        assert Sigma_Nargs <=2 , "Sigma function is not of the correct type. See Documentation"

        #init
        G.zero()
        #tmp,tmp2 = GF(G),GF(G)
        tmp,tmp2 = G.copy(),G.copy()
        mupat = mu * self.Mu_Pattern 
        tmp <<= GF_Initializers.A_Omega_Plus_B(A=1,B=0)
        #tmp.Set_Omega()
        ##tmp += tmp.Nblocks() * [ mupat ]
        if Field : tmp -= Field 
        if Sigma_Nargs==0: tmp -= Sigma  # substract Sigma once for all

        # Loop on k points...
        for w, k, eps_k in izip(*[MPI.slice_array(A) for A in [self.BZ_weights, self.BZ_Points, self.Hopping]]):
            tmp2 <<= tmp
            #tmp2.copy_from(tmp)
            tmp2 -= tmp2.NBlocks * [eps_k -mupat ]
            #tmp2.save("tmp2_w")
            #Sigma.save("S_w")

            if Sigma_Nargs == 1: tmp2 -= Sigma (k)
            elif Sigma_Nargs ==2: tmp2 -= Sigma (k,eps_k)
            tmp2.invert()
            tmp2 *= w
            G += tmp2
            #G.save("GG1")
            #print mu,mupat,eps_k
            #assert 0
            #print G['up'][1,1]._data
        G <<= MPI.all_reduce(MPI.world,G,lambda x,y : x+y)
        MPI.barrier()

        return Res