Ejemplo n.º 1
0
    def __init__(
                 self,
                 file=None,
                 nbands=None,
                 bands=None,
                 kpoints=None,
                 e_skn=None,
                 eshift=None,
                 w=None,
                 ecut=150.,
                 eta=0.1,
                 ppa=False,
                 E0=None,
                 hilbert_trans=False,
                 wpar=1,
                 vcut=None,
                 numint=False,
                 txt=None
                ):

        BASECHI.__init__(self, calc=file, nbands=nbands, w=w, eshift=eshift, ecut=ecut, eta=eta, txt=devnull)

        self.file = file
        self.gwnbands = nbands
        self.bands = bands
        self.kpoints = kpoints
        self.user_skn = e_skn
        self.ppa = ppa
        self.E0 = E0
        self.hilbert_trans = hilbert_trans
        self.wpar = wpar
        self.vcut = vcut
        self.numint = numint
        self.gwtxtname = txt
Ejemplo n.º 2
0
    def __init__(
        self,
        calc=None,
        nbands=None,
        w=None,
        q=None,
        eshift=None,
        ecut=10.0,
        density_cut=None,
        G_plus_q=False,
        eta=0.2,
        rpad=None,
        vcut=None,
        ftol=1e-5,
        txt=None,
        xc="ALDA",
        hilbert_trans=True,
        time_ordered=False,
        optical_limit=False,
        comm=None,
        kcommsize=None,
    ):

        BASECHI.__init__(
            self,
            calc=calc,
            nbands=nbands,
            w=w,
            q=q,
            eshift=eshift,
            ecut=ecut,
            density_cut=density_cut,
            G_plus_q=G_plus_q,
            eta=eta,
            rpad=rpad,
            ftol=ftol,
            txt=txt,
            optical_limit=optical_limit,
        )

        # if vcut is None:
        #    vcut = '%dD' % self.calc.wfs.gd.pbc_c.sum()
        self.vcut = vcut

        self.xc = xc
        self.hilbert_trans = hilbert_trans
        self.full_hilbert_trans = time_ordered
        self.kcommsize = kcommsize
        self.comm = comm
        if self.comm is None:
            self.comm = world
        self.chi0_wGG = None
Ejemplo n.º 3
0
    def __init__(
            self,
            calc=None,
            nbands=None,
            nc=None,
            nv=None,
            w=None,
            q=None,
            eshift=None,
            ecut=10.,
            eta=0.2,
            gw_skn=None,  # GW QP energies in Hartree
            rpad=None,
            vcut=None,  # Coulomb cutoff only 2D works
            ftol=1e-5,
            txt=None,
            optical_limit=None,
            integrate_coulomb=None,
            print_coulomb=False,
            coupling=False,  # False : use Tamm-Dancoff Approx
            mode='BSE',  # BSE, TDHF or RPA
            kernel_file=None,  #'W_qGG',
            qsymm=True):

        BASECHI.__init__(self,
                         calc=calc,
                         nbands=nbands,
                         w=w,
                         q=q,
                         eshift=eshift,
                         ecut=ecut,
                         eta=eta,
                         rpad=rpad,
                         ftol=ftol,
                         txt=txt,
                         optical_limit=optical_limit)

        assert mode in ['RPA', 'TDHF', 'BSE']

        self.epsilon_w = None
        self.coupling = coupling
        self.vcut = vcut
        self.nc = nc  # conduction band index
        self.nv = nv  # valence band index
        self.gw_skn = gw_skn
        self.mode = mode
        self.integrate_coulomb = integrate_coulomb
        self.print_coulomb = print_coulomb
        self.kernel_file = kernel_file
        self.qsymm = qsymm
Ejemplo n.º 4
0
    def __init__(self,
                 calc=None,
                 nbands=None,
                 w=None,
                 q=None,
                 ecut=10.,
                 eta=0.2,
                 ftol=1e-5,
                 txt=None,
                 optical_limit=False):

        BASECHI.__init__(self, calc, nbands, w, q, ecut, eta, ftol, txt,
                         optical_limit)

        self.epsilon_w = None
Ejemplo n.º 5
0
Archivo: bse.py Proyecto: qsnake/gpaw
    def __init__(self,
                 calc=None,
                 nbands=None,
                 w=None,
                 q=None,
                 ecut=10.,
                 eta=0.2,
                 ftol=1e-5,
                 txt=None,
                 optical_limit=False):

        BASECHI.__init__(self, calc, nbands, w, q, ecut,
                     eta, ftol, txt, optical_limit)


        self.epsilon_w = None
Ejemplo n.º 6
0
    def __init__(self,
                 calc=None,
                 nbands=None,
                 nc=None,
                 nv=None,
                 w=None,
                 q=None,
                 eshift=None,
                 ecut=10.,
                 eta=0.2,
                 gw_skn=None, # GW QP energies in Hartree
                 rpad=None,
                 vcut=None,   # Coulomb cutoff only 2D works
                 ftol=1e-5,
                 txt=None,
                 optical_limit=None,
                 integrate_coulomb=None,
                 print_coulomb=False,
                 coupling=False,  # False : use Tamm-Dancoff Approx
                 mode='BSE',      # BSE, TDHF or RPA
                 kernel_file=None,#'W_qGG',
                 qsymm=True): 

        BASECHI.__init__(self, calc=calc, nbands=nbands, w=w, q=q,
                         eshift=eshift, ecut=ecut, eta=eta, rpad=rpad,
                         ftol=ftol, txt=txt, optical_limit=optical_limit)

        assert mode is 'RPA' or 'TDHF' or 'BSE'

        self.epsilon_w = None
        self.coupling = coupling
        self.vcut = vcut
        self.nc = nc # conduction band index
        self.nv = nv # valence band index
        self.gw_skn = gw_skn
        self.mode = mode
        self.integrate_coulomb = integrate_coulomb
        self.print_coulomb = print_coulomb
        self.kernel_file = kernel_file
        self.qsymm = qsymm
Ejemplo n.º 7
0
    def __init__(self,
                 calc=None,
                 nbands=None,
                 w=None,
                 q=None,
                 ecut=10.,
                 eta=0.2,
                 ftol=1e-5,
                 txt=None,
                 hilbert_trans=True,
                 full_response=False,
                 optical_limit=False,
                 kcommsize=None):

        BASECHI.__init__(self, calc, nbands, w, q, ecut, eta, ftol, txt,
                         optical_limit)

        self.hilbert_trans = hilbert_trans
        self.full_hilbert_trans = full_response
        self.kcommsize = kcommsize
        self.comm = world
        self.chi0_wGG = None
Ejemplo n.º 8
0
    def __init__(self,
                 file=None,
                 nbands=None,
                 bands=None,
                 kpoints=None,
                 e_skn=None,
                 eshift=None,
                 w=None,
                 ecut=150.,
                 eta=0.1,
                 ppa=False,
                 E0=None,
                 hilbert_trans=False,
                 wpar=1,
                 vcut=None,
                 numint=False,
                 txt=None):

        BASECHI.__init__(self,
                         calc=file,
                         nbands=nbands,
                         w=w,
                         eshift=eshift,
                         ecut=ecut,
                         eta=eta,
                         txt=devnull)

        self.file = file
        self.gwnbands = nbands
        self.bands = bands
        self.kpoints = kpoints
        self.user_skn = e_skn
        self.ppa = ppa
        self.E0 = E0
        self.hilbert_trans = hilbert_trans
        self.wpar = wpar
        self.vcut = vcut
        self.numint = numint
        self.gwtxtname = txt
Ejemplo n.º 9
0
Archivo: chi.py Proyecto: qsnake/gpaw
    def __init__(self,
                 calc=None,
                 nbands=None,
                 w=None,
                 q=None,
                 ecut=10.,
                 eta=0.2,
                 ftol=1e-5,
                 txt=None,
                 hilbert_trans=True,
                 full_response=False,
                 optical_limit=False,
                 kcommsize=None):

        BASECHI.__init__(self, calc, nbands, w, q, ecut,
                     eta, ftol, txt, optical_limit)

        self.hilbert_trans = hilbert_trans
        self.full_hilbert_trans = full_response
        self.kcommsize = kcommsize
        self.comm = world
        self.chi0_wGG = None
Ejemplo n.º 10
0
    def __init__(self,
                 calc=None,
                 nbands=None,
                 w=None,
                 q=None,
                 eshift=None,
                 ecut=10.,
                 density_cut=None,
                 G_plus_q=False,
                 eta=0.2,
                 rpad=None,
                 vcut=None,
                 ftol=1e-5,
                 txt=None,
                 xc='ALDA',
                 hilbert_trans=True,
                 time_ordered=False,
                 optical_limit=False,
                 comm=None,
                 kcommsize=None):

        BASECHI.__init__(self, calc=calc, nbands=nbands, w=w, q=q,
                         eshift=eshift, ecut=ecut,
                         density_cut=density_cut, G_plus_q=G_plus_q, eta=eta,
                         rpad=rpad, ftol=ftol, txt=txt,
                         optical_limit=optical_limit)
        
        #if vcut is None:
        #    vcut = '%dD' % self.calc.wfs.gd.pbc_c.sum()
        self.vcut = vcut

        self.xc = xc
        self.hilbert_trans = hilbert_trans
        self.full_hilbert_trans = time_ordered
        self.kcommsize = kcommsize
        self.comm = comm
        if self.comm is None:
            self.comm = world
        self.chi0_wGG = None
Ejemplo n.º 11
0
    def initialize(self):

        self.printtxt('')
        self.printtxt('-----------------------------------------------')
        self.printtxt('Belth Selpeter Equation calculation started at:')
        self.printtxt(ctime())

        BASECHI.initialize(self)

        calc = self.calc
        self.kd = kd = calc.wfs.kd

        # frequency points init
        self.dw = self.w_w[1] - self.w_w[0]
        assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) <
                1e-10).all()  # make sure its linear w grid
        assert self.w_w.max() == self.w_w[-1]

        self.dw /= Hartree
        self.w_w /= Hartree
        self.wmax = self.w_w[-1]
        self.Nw = int(self.wmax / self.dw) + 1

        # find the pair index and initialized pair energy (e_i - e_j) and occupation(f_i-f_j)
        self.e_S = {}
        focc_s = {}
        self.Sindex_S3 = {}
        iS = 0
        kq_k = self.kq_k
        for k1 in range(self.nkpt):
            ibzkpt1 = kd.kibz_k[k1]
            ibzkpt2 = kd.kibz_k[kq_k[k1]]
            for n1 in range(self.nbands):
                for m1 in range(self.nbands):
                    focc = self.f_kn[ibzkpt1, n1] - self.f_kn[ibzkpt2, m1]
                    if np.abs(focc) > self.ftol:
                        self.e_S[iS] = self.e_kn[ibzkpt2,
                                                 m1] - self.e_kn[ibzkpt1, n1]
                        focc_s[iS] = focc
                        self.Sindex_S3[iS] = (k1, n1, m1)
                        iS += 1
        self.nS = iS
        self.focc_S = np.zeros(self.nS)
        for iS in range(self.nS):
            self.focc_S[iS] = focc_s[iS]

        # parallel init
        self.Scomm = world
        # kcomm and wScomm is only to be used when wavefunctions r parallelly distributed.
        self.kcomm = world
        self.wScomm = serial_comm

        self.nS, self.nS_local, self.nS_start, self.nS_end = parallel_partition(
            self.nS, self.Scomm.rank, self.Scomm.size, reshape=False)
        self.print_bse()

        self.get_phi_aGp()

        # Coulomb kernel init
        self.kc_G = np.zeros(self.npw)
        for iG in range(self.npw):
            index = self.Gindex_G[iG]
            qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv)
            self.kc_G[iG] = 1. / np.inner(qG, qG)
        if self.optical_limit:
            self.kc_G[0] = 0.
        self.printtxt('')

        return
Ejemplo n.º 12
0
    def initialize(self):

        self.printtxt('----------------------------------------')
        self.printtxt('Bethe-Salpeter Equation calculation')
        self.printtxt('----------------------------------------')
        self.printtxt('Started at:  %s' % ctime())
        self.printtxt('')
        BASECHI.initialize(self)
        assert self.nspins == 1

        calc = self.calc
        self.kd = kd = calc.wfs.kd

        # frequency points init
        self.dw = self.w_w[1] - self.w_w[0]
        assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) <
                1e-10).all()  # make sure its linear w grid
        assert self.w_w.max() == self.w_w[-1]

        self.dw /= Hartree
        self.w_w /= Hartree
        self.wmax = self.w_w[-1]
        self.Nw = int(self.wmax / self.dw) + 1

        # band init
        if self.nc is None:
            nv = self.nvalence / 2 - 1
            self.nv = np.array([nv, nv + 1])  # conduction band start / end
            self.nc = np.array([nv + 1, nv + 2])  # valence band start / end

        self.printtxt('')
        self.printtxt('Number of electrons      : %d' % (self.nvalence))
        self.printtxt('Valence band included    : (band %d to band %d)' %
                      (self.nv[0], self.nv[1] - 1))
        self.printtxt('Conduction band included : (band %d to band %d)' %
                      (self.nc[0], self.nc[1] - 1))
        if self.eshift is not None:
            self.printtxt('Scissors operator        : %2.3f eV' % self.eshift)
        self.printtxt('')

        # find the pair index and initialized pair energy (e_i - e_j) and occupation(f_i-f_j)
        self.e_S = {}
        focc_s = {}
        self.Sindex_S3 = {}
        iS = 0
        kq_k = self.kq_k
        for k1 in range(self.kd.nbzkpts):
            ibzkpt1 = kd.bz2ibz_k[k1]
            ibzkpt2 = kd.bz2ibz_k[kq_k[k1]]
            for n1 in range(self.nv[0], self.nv[1]):
                for m1 in range(self.nc[0], self.nc[1]):
                    focc = self.f_skn[0][ibzkpt1, n1] - self.f_skn[0][ibzkpt2,
                                                                      m1]
                    if self.coupling:  # Dont use Tamm-Dancoff Approx.
                        check_ftol = np.abs(focc) > self.ftol
                    else:
                        check_ftol = focc > self.ftol
                    if check_ftol:
                        if self.gw_skn is None:
                            self.e_S[iS] = self.e_skn[0][
                                ibzkpt2, m1] - self.e_skn[0][ibzkpt1, n1]
                        else:
                            self.e_S[iS] = self.gw_skn[0][
                                ibzkpt2, m1] - self.gw_skn[0][ibzkpt1, n1]

                        focc_s[iS] = focc
                        self.Sindex_S3[iS] = (k1, n1, m1)
                        iS += 1
        self.nS = iS
        self.focc_S = np.zeros(self.nS)
        for iS in range(self.nS):
            self.focc_S[iS] = focc_s[iS]

        # q points init
        self.bzq_qc = kd.get_bz_q_points()
        if not self.qsymm:
            self.ibzq_qc = self.bzq_qc
        else:
            (self.ibzq_qc, self.ibzq_q, self.iop_q, self.timerev_q,
             self.diff_qc) = kd.get_ibz_q_points(self.bzq_qc,
                                                 calc.wfs.kd.symmetry.op_scc)
            if np.abs(self.bzq_qc - kd.bzk_kc).sum() < 1e-8:
                assert np.abs(self.ibzq_qc - kd.ibzk_kc).sum() < 1e-8
        self.nibzq = len(self.ibzq_qc)

        # Parallel initialization
        # kcomm and wScomm is only to be used when wavefunctions are distributed in parallel.
        self.comm = self.Scomm = world
        self.kcomm = world
        self.wScomm = serial_comm
        self.nS, self.nS_local, self.nS_start, self.nS_end = parallel_partition(
            self.nS, world.rank, world.size, reshape=False)

        self.print_bse()

        if calc.input_parameters['mode'] == 'lcao':
            calc.initialize_positions()

        # Coulomb interaction at q=0 for Hartree coupling
        ### 2D z direction only !!!!!!!!!!!!!!!!!!!!!!
        if self.integrate_coulomb is None:
            self.integrate_coulomb = []
            if self.vcut is None:
                pass
            elif self.vcut == '2D':
                for iG in range(len(self.Gvec_Gc)):
                    if self.Gvec_Gc[iG, 0] == 0 and self.Gvec_Gc[iG, 1] == 0:
                        self.integrate_coulomb.append(iG)
            else:
                raise NotImplementedError
        elif type(self.integrate_coulomb) is int:
            self.integrate_coulomb = range(self.integrate_coulomb)
        elif self.integrate_coulomb == 'all':
            self.integrate_coulomb = range(len(self.Gvec_Gc))
        elif type(self.integrate_coulomb) is list:
            pass
        else:
            raise 'Invalid option for integrate_coulomb'

        self.printtxt('')
        self.printtxt('Calculating bare Coulomb kernel')
        if not len(self.integrate_coulomb) == 0:
            self.printtxt(
                'Integrating Coulomb kernel at %s reciprocal lattice vector(s)'
                % len(self.integrate_coulomb))

        # Coulomb interaction at problematic G's for exchange coupling
        if len(self.integrate_coulomb) != 0:
            self.vint_Gq = []
            for iG in self.integrate_coulomb:
                v_q, v0_q = calculate_Kc_q(self.acell_cv,
                                           self.bcell_cv,
                                           self.pbc,
                                           self.kd.N_c,
                                           vcut=self.vcut,
                                           Gvec_c=self.Gvec_Gc[iG],
                                           q_qc=self.ibzq_qc.copy())
                self.vint_Gq.append(v_q)
                if self.print_coulomb:
                    self.printtxt('')
                    self.printtxt(
                        'Average kernel relative to bare kernel - \int v(q)dq / v(q0): '
                    )
                    self.printtxt('  G: % s' % self.Gvec_Gc[iG])
                    for iq in range(len(v_q)):
                        q_s = '    q = [%1.2f,  %1.2f,  %1.2f]: ' % (
                            self.ibzq_qc[iq, 0], self.ibzq_qc[iq, 1],
                            self.ibzq_qc[iq, 2])
                        v_rel = v_q[iq] / v0_q[iq]
                        self.printtxt(q_s + '%1.3f' % v_rel)
        self.printtxt('')

        self.V_qGG = self.full_bare_interaction()
Ejemplo n.º 13
0
    def initialize(self):

        self.ini = True

        BASECHI.initialize(self)

        self.txtname = self.gwtxtname
        self.output_init()

        self.printtxt('GPAW version %s' % (version))
        self.printtxt('-----------------------------------------------')
        self.printtxt('GW calculation started at:')
        self.printtxt(ctime())
        self.printtxt('-----------------------------------------------')
        self.starttime = time()

        calc = self.calc
        kd = self.kd

        # band init
        if self.gwnbands is None:
            if self.npw > calc.wfs.bd.nbands:
                self.nbands = calc.wfs.bd.nbands
            else:
                self.nbands = self.npw

        # eigenvalue init
        if self.user_skn is not None:
            self.printtxt('Use eigenvalues from user.')
            assert np.shape(
                self.user_skn
            )[0] == self.nspins, 'Eigenvalues not compatible with .gpw file!'
            assert np.shape(
                self.user_skn
            )[1] == self.kd.nibzkpts, 'Eigenvalues not compatible with .gpw file!'
            assert np.shape(
                self.user_skn)[2] >= self.nbands, 'Too few eigenvalues!'
            self.e_skn = self.user_skn
        else:
            self.printtxt('Use eigenvalues from the calculator.')

        # q point init
        self.bzq_kc = kd.get_bz_q_points()
        self.ibzq_qc = self.bzq_kc  # q point symmetry is not used at the moment.
        self.nqpt = np.shape(self.bzq_kc)[0]

        # frequency points init
        self.static = False

        if self.ppa:  # Plasmon Pole Approximation
            if self.E0 is None:
                self.E0 = Hartree
            self.E0 /= Hartree
            self.w_w = np.array([0., 1j * self.E0])
            self.hilbert_trans = False
            self.wpar = 1
        elif self.w_w is None:  # static COHSEX
            self.w_w = np.array([0.])
            self.static = True
            self.hilbert_trans = False
            self.wpar = 1
            self.eta = 0.0001 / Hartree
        else:
            # create nonlinear frequency grid
            # grid is linear from 0 to wcut with spacing dw
            # spacing is linearily increasing between wcut and wmax
            # Hilbert transforms are still carried out on linear grid
            wcut = self.w_w[0]
            wmax = self.w_w[1]
            dw = self.w_w[2]
            w_w = np.linspace(0., wcut, wcut / dw + 1)
            i = 1
            wi = wcut
            while wi < wmax:
                wi += i * dw
                w_w = np.append(w_w, wi)
                i += 1
            while len(w_w) % self.wpar != 0:
                wi += i * dw
                w_w = np.append(w_w, wi)
                i += 1

            dw_w = np.zeros(len(w_w))
            dw_w[0] = dw
            dw_w[1:] = w_w[1:] - w_w[:-1]

            self.w_w = w_w / Hartree
            self.dw_w = dw_w / Hartree
            self.eta_w = dw_w * 4 / Hartree
            self.wcut = wcut

            self.wmax = self.w_w[-1]
            self.wmin = self.w_w[0]
            self.dw = self.w_w[1] - self.w_w[0]
            self.Nw = len(self.w_w)
            #            self.wpar = int(self.Nw * self.npw**2 * 16. / 1024**2) // 1500 + 1 # estimate memory and parallelize over frequencies

            for s in range(self.nspins):
                emaxdiff = self.e_skn[s][:, self.nbands -
                                         1].max() - self.e_skn[s][:, 0].min()
                assert (self.wmax > emaxdiff
                        ), 'Maximum frequency must be larger than %f' % (
                            emaxdiff * Hartree)

        # GW kpoints init
        if self.kpoints is None:
            self.gwnkpt = self.kd.nibzkpts
            self.gwkpt_k = kd.ibz2bz_k
        else:
            self.gwnkpt = np.shape(self.kpoints)[0]
            self.gwkpt_k = self.kpoints

        # GW bands init
        if self.bands is None:
            self.gwnband = self.nbands
            self.bands = self.gwbands_n = np.arange(self.nbands)
        else:
            self.gwnband = np.shape(self.bands)[0]
            self.gwbands_n = self.bands

        self.alpha = 1j / (2 * pi * self.vol * self.kd.nbzkpts)

        # parallel init
        assert len(self.w_w) % self.wpar == 0
        self.wcommsize = self.wpar
        self.qcommsize = size // self.wpar
        assert self.qcommsize * self.wcommsize == size, 'wpar must be integer divisor of number of requested cores'
        if self.nqpt != 1:  # parallelize over q-points
            self.wcomm, self.qcomm, self.worldcomm = set_communicator(
                world, rank, size, self.wpar)
            self.ncomm = serial_comm
            self.dfcomm = self.wcomm
            self.kcommsize = 1
        else:  # parallelize over bands
            self.wcomm, self.ncomm, self.worldcomm = set_communicator(
                world, rank, size, self.wpar)
            self.qcomm = serial_comm
            if self.wpar > 1:
                self.dfcomm = self.wcomm
                self.kcommsize = 1
            else:
                self.dfcomm = self.ncomm
                self.kcommsize = self.ncomm.size
        nq, self.nq_local, self.q_start, self.q_end = parallel_partition(
            self.nqpt, self.qcomm.rank, self.qcomm.size, reshape=False)
        nb, self.nbands_local, self.m_start, self.m_end = parallel_partition(
            self.nbands, self.ncomm.rank, self.ncomm.size, reshape=False)
Ejemplo n.º 14
0
    def initialize(self):

        self.printtxt('----------------------------------------')
        self.printtxt('Bethe-Salpeter Equation calculation')
        self.printtxt('----------------------------------------')
        self.printtxt('Started at:  %s' % ctime())
        self.printtxt('')
        BASECHI.initialize(self)
        assert self.nspins == 1
        
        calc = self.calc
        self.kd = kd = calc.wfs.kd

        # frequency points init
        self.dw = self.w_w[1] - self.w_w[0]
        assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid
        assert self.w_w.max() == self.w_w[-1]

        self.dw /= Hartree
        self.w_w  /= Hartree
        self.wmax = self.w_w[-1] 
        self.Nw  = int(self.wmax / self.dw) + 1

        # band init
        if self.nc is None:
            nv = self.nvalence / 2 - 1
            self.nv = np.array([nv, nv+1]) # conduction band start / end
            self.nc = np.array([nv+1, nv+2]) # valence band start / end

        self.printtxt('')
        self.printtxt('Number of electrons      : %d' % (self.nvalence))
        self.printtxt('Valence band included    : (band %d to band %d)' %(self.nv[0], self.nv[1]-1))
        self.printtxt('Conduction band included : (band %d to band %d)' %(self.nc[0], self.nc[1]-1))
        if self.eshift is not None:
            self.printtxt('Scissors operator        : %2.3f eV' % self.eshift)
        self.printtxt('')
            
        # find the pair index and initialized pair energy (e_i - e_j) and occupation(f_i-f_j)
        self.e_S = {}
        focc_s = {}
        self.Sindex_S3 = {}
        iS = 0
        kq_k = self.kq_k
        for k1 in range(self.kd.nbzkpts):
            ibzkpt1 = kd.bz2ibz_k[k1]
            ibzkpt2 = kd.bz2ibz_k[kq_k[k1]]
            for n1 in range(self.nv[0], self.nv[1]): 
                for m1 in range(self.nc[0], self.nc[1]): 
                    focc = self.f_skn[0][ibzkpt1,n1] - self.f_skn[0][ibzkpt2,m1]
                    if self.coupling: # Dont use Tamm-Dancoff Approx.
                        check_ftol = np.abs(focc) > self.ftol
                    else:
                        check_ftol = focc > self.ftol
                    if check_ftol:
                        if self.gw_skn is None:
                            self.e_S[iS] = self.e_skn[0][ibzkpt2,m1] - self.e_skn[0][ibzkpt1,n1]
                        else:
                            self.e_S[iS] = self.gw_skn[0][ibzkpt2,m1] - self.gw_skn[0][ibzkpt1,n1]
                            
                        focc_s[iS] = focc
                        self.Sindex_S3[iS] = (k1, n1, m1)
                        iS += 1
        self.nS = iS
        self.focc_S = np.zeros(self.nS)
        for iS in range(self.nS):
            self.focc_S[iS] = focc_s[iS]

        # q points init
        self.bzq_qc = kd.get_bz_q_points()
        if not self.qsymm:
            self.ibzq_qc = self.bzq_qc
        else:
            (self.ibzq_qc, self.ibzq_q, self.iop_q,
             self.timerev_q, self.diff_qc) = kd.get_ibz_q_points(self.bzq_qc,
                                                                 calc.wfs.symmetry.op_scc)
            if np.abs(self.bzq_qc - kd.bzk_kc).sum() < 1e-8:
                assert np.abs(self.ibzq_qc - kd.ibzk_kc).sum() < 1e-8
        self.nibzq = len(self.ibzq_qc)

        # Parallel initialization 
        # kcomm and wScomm is only to be used when wavefunctions are distributed in parallel.
        self.comm = self.Scomm = world
        self.kcomm = world
        self.wScomm = serial_comm
        self.nS, self.nS_local, self.nS_start, self.nS_end = parallel_partition(
            self.nS, world.rank, world.size, reshape=False)

        self.print_bse()

        if calc.input_parameters['mode'] == 'lcao':
            calc.initialize_positions()

        # Coulomb interaction at q=0 for Hartree coupling
        ### 2D z direction only !!!!!!!!!!!!!!!!!!!!!!
        if self.integrate_coulomb is None:
            self.integrate_coulomb = []
            if self.vcut is None:
                pass
            elif self.vcut == '2D':
                for iG in range(len(self.Gvec_Gc)):
                    if self.Gvec_Gc[iG, 0] == 0 and self.Gvec_Gc[iG, 1] == 0:
                        self.integrate_coulomb.append(iG)
            else:
                raise NotImplementedError
        elif type(self.integrate_coulomb) is int:
            self.integrate_coulomb = range(self.integrate_coulomb)
        elif self.integrate_coulomb == 'all':
            self.integrate_coulomb = range(len(self.Gvec_Gc))
        elif type(self.integrate_coulomb) is list:
            pass
        else:
            raise 'Invalid option for integrate_coulomb'
        
        self.printtxt('')
        self.printtxt('Calculating bare Coulomb kernel')
        if not len(self.integrate_coulomb) == 0:
            self.printtxt('Integrating Coulomb kernel at %s reciprocal lattice vector(s)' % len(self.integrate_coulomb))
        
        # Coulomb interaction at problematic G's for exchange coupling
        if len(self.integrate_coulomb) != 0:
            self.vint_Gq = []
            for iG in self.integrate_coulomb:
                v_q, v0_q = calculate_Kc_q(self.acell_cv,
                                           self.bcell_cv,
                                           self.pbc,
                                           self.kd.N_c,
                                           vcut=self.vcut,
                                           Gvec_c=self.Gvec_Gc[iG],
                                           q_qc=self.ibzq_qc.copy())
                self.vint_Gq.append(v_q)                    
                if self.print_coulomb:
                    self.printtxt('')
                    self.printtxt('Average kernel relative to bare kernel - \int v(q)dq / v(q0): ')
                    self.printtxt('  G: % s' % self.Gvec_Gc[iG])
                    for iq in range(len(v_q)):
                        q_s = '    q = [%1.2f,  %1.2f,  %1.2f]: ' % (self.ibzq_qc[iq,0],
                                                                     self.ibzq_qc[iq,1],
                                                                     self.ibzq_qc[iq,2])
                        v_rel = v_q[iq] / v0_q[iq]
                        self.printtxt(q_s + '%1.3f' % v_rel)
        self.printtxt('')

        self.V_qGG = self.full_bare_interaction()

        return
Ejemplo n.º 15
0
    def initialize(self, simple_version=False):

        self.printtxt("")
        self.printtxt("-----------------------------------------")
        self.printtxt("Response function calculation started at:")
        self.starttime = time()
        self.printtxt(ctime())

        BASECHI.initialize(self)

        # Frequency init
        self.dw = None
        if len(self.w_w) == 1:
            self.hilbert_trans = False

        if self.hilbert_trans:
            self.dw = self.w_w[1] - self.w_w[0]
            #            assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid
            assert self.w_w.max() == self.w_w[-1]

            self.dw /= Hartree
            self.w_w /= Hartree
            self.wmax = self.w_w[-1]
            self.wcut = self.wmax + 5.0 / Hartree
            #            self.Nw  = int(self.wmax / self.dw) + 1
            self.Nw = len(self.w_w)
            self.NwS = int(self.wcut / self.dw) + 1
        else:
            self.Nw = len(self.w_w)
            self.NwS = 0
            if len(self.w_w) > 2:
                self.dw = self.w_w[1] - self.w_w[0]
                assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all()
                self.dw /= Hartree

        self.nvalbands = self.nbands
        tmpn = np.zeros(self.nspins, dtype=int)
        for spin in range(self.nspins):
            for n in range(self.nbands):
                if (self.f_skn[spin][:, n] - self.ftol < 0).all():
                    tmpn[spin] = n
                    break
        if tmpn.max() > 0:
            self.nvalbands = tmpn.max()

        # Parallelization initialize
        self.parallel_init()

        # Printing calculation information
        self.print_chi()

        if extra_parameters.get("df_dry_run"):
            raise SystemExit

        calc = self.calc

        # For LCAO wfs
        if calc.input_parameters["mode"] == "lcao":
            calc.initialize_positions()
        self.printtxt("     Max mem sofar   : %f M / cpu" % (maxrss() / 1024 ** 2))

        if simple_version is True:
            return
        # PAW part init
        # calculate <phi_i | e**(-i(q+G).r) | phi_j>
        # G != 0 part
        self.phi_aGp, self.phiG0_avp = self.get_phi_aGp(alldir=True)
        self.printtxt("Finished phi_aGp !")
        mem = np.array([self.phi_aGp[i].size * 16 / 1024.0 ** 2 for i in range(len(self.phi_aGp))])
        self.printtxt("     Phi_aGp         : %f M / cpu" % (mem.sum()))

        # Calculate ALDA kernel (not used in chi0)
        R_av = calc.atoms.positions / Bohr
        if self.xc == "RPA":  # type(self.w_w[0]) is float:
            self.Kc_GG = None
            self.printtxt("RPA calculation.")
        elif self.xc == "ALDA" or self.xc == "ALDA_X":
            # self.Kc_GG = calculate_Kc(self.q_c,
            #                          self.Gvec_Gc,
            #                          self.acell_cv,
            #                          self.bcell_cv,
            #                          self.calc.atoms.pbc,
            #                          self.vcut)
            # Initialize a CoulombKernel instance
            kernel = CoulombKernel(vcut=self.vcut, pbc=self.calc.atoms.pbc, cell=self.acell_cv)
            self.Kc_GG = kernel.calculate_Kc(self.q_c, self.Gvec_Gc, self.bcell_cv)

            self.Kxc_sGG = calculate_Kxc(
                self.gd,  # global grid
                self.gd.zero_pad(calc.density.nt_sG),
                self.npw,
                self.Gvec_Gc,
                self.gd.N_c,
                self.vol,
                self.bcell_cv,
                R_av,
                calc.wfs.setups,
                calc.density.D_asp,
                functional=self.xc,
                density_cut=self.density_cut,
            )

            self.printtxt("Finished %s kernel ! " % self.xc)

        return
Ejemplo n.º 16
0
Archivo: chi.py Proyecto: qsnake/gpaw
    def initialize(self):

        self.printtxt('')
        self.printtxt('-----------------------------------------')
        self.printtxt('Response function calculation started at:')
        self.starttime = time()
        self.printtxt(ctime())

        BASECHI.initialize(self)

        # Frequency init
        self.dw = None
        if len(self.w_w) == 1:
            self.HilberTrans = False

        if self.hilbert_trans:
            self.dw = self.w_w[1] - self.w_w[0]
            assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid
            assert self.w_w.max() == self.w_w[-1]
            
            self.dw /= Hartree
            self.w_w  /= Hartree
            self.wmax = self.w_w[-1] 
            self.wcut = self.wmax + 5. / Hartree
            self.Nw  = int(self.wmax / self.dw) + 1
            self.NwS = int(self.wcut / self.dw) + 1
        else:
            self.Nw = len(self.w_w)
            self.NwS = 0
            if len(self.w_w) > 1:
                self.dw = self.w_w[1] - self.w_w[0]
                assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all()
                self.dw /= Hartree
                
        if self.hilbert_trans:
            # for band parallelization.
            for n in range(self.nbands):
                if (self.f_kn[:, n] - self.ftol < 0).all():
                    self.nvalbands = n
                    break
        else:
            # if not hilbert transform, all the bands should be used.
            self.nvalbands = self.nbands

        # Parallelization initialize
        self.parallel_init()

        # Printing calculation information
        self.print_chi()

        if extra_parameters.get('df_dry_run'):
            raise SystemExit

        calc = self.calc

        # For LCAO wfs
        if calc.input_parameters['mode'] == 'lcao':
            calc.initialize_positions()        
        self.printtxt('     GS calculator   : %f M / cpu' %(maxrss() / 1024**2))
        # PAW part init
        # calculate <phi_i | e**(-i(q+G).r) | phi_j>
        # G != 0 part
        self.get_phi_aGp()

        # Calculate ALDA kernel for EELS spectrum
        # Use RPA kernel for Optical spectrum and rpa correlation energy
        if not self.optical_limit and np.dtype(self.w_w[0]) == float:
            R_av = calc.atoms.positions / Bohr
            self.Kxc_GG = calculate_Kxc(self.gd, # global grid
                                    calc.density.nt_sG,
                                    self.npw, self.Gvec_Gc,
                                    self.nG, self.vol,
                                    self.bcell_cv, R_av,
                                    calc.wfs.setups,
                                    calc.density.D_asp)

            self.printtxt('Finished ALDA kernel ! ')
        else:
            self.Kxc_GG = np.zeros((self.npw, self.npw))
            self.printtxt('Use RPA for optical spectrum ! ')
            self.printtxt('')
            
        return
Ejemplo n.º 17
0
    def initialize(self):

        self.ini = True

        BASECHI.initialize(self)

        self.txtname = self.gwtxtname
        self.output_init()

        self.printtxt('GPAW version %s' %(version))
        self.printtxt('-----------------------------------------------')
        self.printtxt('GW calculation started at:')
        self.printtxt(ctime())
        self.printtxt('-----------------------------------------------')
        self.starttime = time()

        calc = self.calc
        kd = self.kd

        # band init
        if self.gwnbands is None:
            if self.npw > calc.wfs.bd.nbands:
                self.nbands = calc.wfs.bd.nbands
            else:
                self.nbands = self.npw

        # eigenvalue init
        if self.user_skn is not None:
            self.printtxt('Use eigenvalues from user.')
            assert np.shape(self.user_skn)[0] == self.nspins, 'Eigenvalues not compatible with .gpw file!'
            assert np.shape(self.user_skn)[1] == self.kd.nibzkpts, 'Eigenvalues not compatible with .gpw file!'
            assert np.shape(self.user_skn)[2] >= self.nbands, 'Too few eigenvalues!'
            self.e_skn = self.user_skn
        else:
            self.printtxt('Use eigenvalues from the calculator.')

        # q point init
        self.bzq_kc = kd.get_bz_q_points()
        self.ibzq_qc = self.bzq_kc # q point symmetry is not used at the moment.
        self.nqpt = np.shape(self.bzq_kc)[0]
        
        # frequency points init
        self.static=False

        if self.ppa: # Plasmon Pole Approximation
            if self.E0 is None:
                self.E0 = Hartree
            self.E0 /= Hartree
            self.w_w = np.array([0., 1j*self.E0])
            self.hilbert_trans=False
            self.wpar=1
        elif self.w_w is None: # static COHSEX
            self.w_w = np.array([0.])
            self.static=True
            self.hilbert_trans=False
            self.wpar=1
            self.eta = 0.0001 / Hartree
        else:
            # create nonlinear frequency grid
            # grid is linear from 0 to wcut with spacing dw
            # spacing is linearily increasing between wcut and wmax
            # Hilbert transforms are still carried out on linear grid
            wcut = self.w_w[0]
            wmax = self.w_w[1]
            dw = self.w_w[2]
            w_w = np.linspace(0., wcut, wcut/dw+1)
            i=1
            wi=wcut
            while wi < wmax:
                wi += i*dw
                w_w = np.append(w_w, wi)
                i+=1
            while len(w_w) % self.wpar != 0:
                wi += i*dw
                w_w = np.append(w_w, wi)
                i+=1

            dw_w = np.zeros(len(w_w))
            dw_w[0] = dw
            dw_w[1:] = w_w[1:] - w_w[:-1]

            self.w_w = w_w / Hartree
            self.dw_w = dw_w / Hartree
            self.eta_w = dw_w * 4 / Hartree
            self.wcut = wcut

            self.wmax = self.w_w[-1]
            self.wmin = self.w_w[0]
            self.dw = self.w_w[1] - self.w_w[0]
            self.Nw = len(self.w_w)
#            self.wpar = int(self.Nw * self.npw**2 * 16. / 1024**2) // 1500 + 1 # estimate memory and parallelize over frequencies

            for s in range(self.nspins):
                emaxdiff = self.e_skn[s][:,self.nbands-1].max() - self.e_skn[s][:,0].min()
                assert (self.wmax > emaxdiff), 'Maximum frequency must be larger than %f' %(emaxdiff*Hartree)

        # GW kpoints init
        if self.kpoints is None:
            self.gwnkpt = self.kd.nibzkpts
            self.gwkpt_k = kd.ibz2bz_k
        else:
            self.gwnkpt = np.shape(self.kpoints)[0]
            self.gwkpt_k = self.kpoints

        # GW bands init
        if self.bands is None:
            self.gwnband = self.nbands
            self.bands = self.gwbands_n = np.arange(self.nbands)
        else:
            self.gwnband = np.shape(self.bands)[0]
            self.gwbands_n = self.bands

        self.alpha = 1j/(2*pi * self.vol * self.kd.nbzkpts)
        
        # parallel init
        assert len(self.w_w) % self.wpar == 0
        self.wcommsize = self.wpar
        self.qcommsize = size // self.wpar
        assert self.qcommsize * self.wcommsize == size, 'wpar must be integer divisor of number of requested cores'
        if self.nqpt != 1: # parallelize over q-points
            self.wcomm, self.qcomm, self.worldcomm = set_communicator(world, rank, size, self.wpar)
            self.ncomm = serial_comm
            self.dfcomm = self.wcomm
            self.kcommsize = 1
        else: # parallelize over bands
            self.wcomm, self.ncomm, self.worldcomm = set_communicator(world, rank, size, self.wpar)
            self.qcomm = serial_comm
            if self.wpar > 1:
                self.dfcomm = self.wcomm
                self.kcommsize = 1
            else:
                self.dfcomm = self.ncomm
                self.kcommsize = self.ncomm.size
        nq, self.nq_local, self.q_start, self.q_end = parallel_partition(
                                  self.nqpt, self.qcomm.rank, self.qcomm.size, reshape=False)
        nb, self.nbands_local, self.m_start, self.m_end = parallel_partition(
                                  self.nbands, self.ncomm.rank, self.ncomm.size, reshape=False)
Ejemplo n.º 18
0
    def initialize(self):

        self.printtxt('')
        self.printtxt('-----------------------------------------')
        self.printtxt('Response function calculation started at:')
        self.starttime = time()
        self.printtxt(ctime())

        BASECHI.initialize(self)

        # Frequency init
        self.dw = None
        if len(self.w_w) == 1:
            self.HilberTrans = False

        if self.hilbert_trans:
            self.dw = self.w_w[1] - self.w_w[0]
            assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) <
                    1e-10).all()  # make sure its linear w grid
            assert self.w_w.max() == self.w_w[-1]

            self.dw /= Hartree
            self.w_w /= Hartree
            self.wmax = self.w_w[-1]
            self.wcut = self.wmax + 5. / Hartree
            self.Nw = int(self.wmax / self.dw) + 1
            self.NwS = int(self.wcut / self.dw) + 1
        else:
            self.Nw = len(self.w_w)
            self.NwS = 0
            if len(self.w_w) > 1:
                self.dw = self.w_w[1] - self.w_w[0]
                assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all()
                self.dw /= Hartree

        if self.hilbert_trans:
            # for band parallelization.
            for n in range(self.nbands):
                if (self.f_kn[:, n] - self.ftol < 0).all():
                    self.nvalbands = n
                    break
        else:
            # if not hilbert transform, all the bands should be used.
            self.nvalbands = self.nbands

        # Parallelization initialize
        self.parallel_init()

        # Printing calculation information
        self.print_chi()

        if extra_parameters.get('df_dry_run'):
            raise SystemExit

        calc = self.calc

        # For LCAO wfs
        if calc.input_parameters['mode'] == 'lcao':
            calc.initialize_positions()
        self.printtxt('     GS calculator   : %f M / cpu' %
                      (maxrss() / 1024**2))
        # PAW part init
        # calculate <phi_i | e**(-i(q+G).r) | phi_j>
        # G != 0 part
        self.get_phi_aGp()

        # Calculate ALDA kernel for EELS spectrum
        # Use RPA kernel for Optical spectrum and rpa correlation energy
        if not self.optical_limit and np.dtype(self.w_w[0]) == float:
            R_av = calc.atoms.positions / Bohr
            self.Kxc_GG = calculate_Kxc(
                self.gd,  # global grid
                calc.density.nt_sG,
                self.npw,
                self.Gvec_Gc,
                self.nG,
                self.vol,
                self.bcell_cv,
                R_av,
                calc.wfs.setups,
                calc.density.D_asp)

            self.printtxt('Finished ALDA kernel ! ')
        else:
            self.Kxc_GG = np.zeros((self.npw, self.npw))
            self.printtxt('Use RPA for optical spectrum ! ')
            self.printtxt('')

        return
Ejemplo n.º 19
0
    def initialize(self, simple_version=False):

        self.printtxt('')
        self.printtxt('-----------------------------------------')
        self.printtxt('Response function calculation started at:')
        self.starttime = time()
        self.printtxt(ctime())

        BASECHI.initialize(self)

        # Frequency init
        self.dw = None
        if len(self.w_w) == 1:
            self.hilbert_trans = False

        if self.hilbert_trans:
            self.dw = self.w_w[1] - self.w_w[0]
#            assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid
            assert self.w_w.max() == self.w_w[-1]
            
            self.dw /= Hartree
            self.w_w /= Hartree
            self.wmax = self.w_w[-1] 
            self.wcut = self.wmax + 5. / Hartree
#            self.Nw  = int(self.wmax / self.dw) + 1
            self.Nw = len(self.w_w)
            self.NwS = int(self.wcut / self.dw) + 1
        else:
            self.Nw = len(self.w_w)
            self.NwS = 0
            if len(self.w_w) > 2:
                self.dw = self.w_w[1] - self.w_w[0]
                assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all()
                self.dw /= Hartree

        self.nvalbands = self.nbands
        tmpn = np.zeros(self.nspins, dtype=int)
        for spin in range(self.nspins):
            for n in range(self.nbands):
                if (self.f_skn[spin][:, n] - self.ftol < 0).all():
                    tmpn[spin] = n
                    break
        if tmpn.max() > 0:
            self.nvalbands = tmpn.max()

        # Parallelization initialize
        self.parallel_init()

        # Printing calculation information
        self.print_chi()

        if extra_parameters.get('df_dry_run'):
            raise SystemExit

        calc = self.calc

        # For LCAO wfs
        if calc.input_parameters['mode'] == 'lcao':
            calc.initialize_positions()        
        self.printtxt('     Max mem sofar   : %f M / cpu' %(maxrss() / 1024**2))

        if simple_version is True:
            return
        # PAW part init
        # calculate <phi_i | e**(-i(q+G).r) | phi_j>
        # G != 0 part
        self.phi_aGp, self.phiG0_avp = self.get_phi_aGp(alldir=True)
        self.printtxt('Finished phi_aGp !')
        mem = np.array([self.phi_aGp[i].size * 16 /1024.**2 for i in range(len(self.phi_aGp))])
        self.printtxt('     Phi_aGp         : %f M / cpu' %(mem.sum()))

        # Calculate ALDA kernel (not used in chi0)
        R_av = calc.atoms.positions / Bohr
        if self.xc == 'RPA': #type(self.w_w[0]) is float:
            self.Kc_GG = None
            self.printtxt('RPA calculation.')
        elif self.xc == 'ALDA' or self.xc == 'ALDA_X':
            #self.Kc_GG = calculate_Kc(self.q_c,
            #                          self.Gvec_Gc,
            #                          self.acell_cv,
            #                          self.bcell_cv,
            #                          self.calc.atoms.pbc,
            #                          self.vcut)
            # Initialize a CoulombKernel instance
            kernel = CoulombKernel(vcut=self.vcut,
                                   pbc=self.calc.atoms.pbc,
                                   cell=self.acell_cv)
            self.Kc_GG = kernel.calculate_Kc(self.q_c,
                                             self.Gvec_Gc,
                                             self.bcell_cv)
            
            self.Kxc_sGG = calculate_Kxc(self.gd, # global grid
                                         self.gd.zero_pad(calc.density.nt_sG),
                                         self.npw, self.Gvec_Gc,
                                         self.gd.N_c, self.vol,
                                         self.bcell_cv, R_av,
                                         calc.wfs.setups,
                                         calc.density.D_asp,
                                         functional=self.xc,
                                         density_cut=self.density_cut)
            
            self.printtxt('Finished %s kernel ! ' % self.xc)
                
        return
Ejemplo n.º 20
0
Archivo: bse.py Proyecto: qsnake/gpaw
    def initialize(self):

        self.printtxt('')
        self.printtxt('-----------------------------------------------')
        self.printtxt('Belth Selpeter Equation calculation started at:')
        self.printtxt(ctime())

        BASECHI.initialize(self)
        
        calc = self.calc
        self.kd = kd = calc.wfs.kd

        # frequency points init
        self.dw = self.w_w[1] - self.w_w[0]
        assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid
        assert self.w_w.max() == self.w_w[-1]

        self.dw /= Hartree
        self.w_w  /= Hartree
        self.wmax = self.w_w[-1] 
        self.Nw  = int(self.wmax / self.dw) + 1

        # find the pair index and initialized pair energy (e_i - e_j) and occupation(f_i-f_j)
        self.e_S = {}
        focc_s = {}
        self.Sindex_S3 = {}
        iS = 0
        kq_k = self.kq_k
        for k1 in range(self.nkpt):
            ibzkpt1 = kd.kibz_k[k1]
            ibzkpt2 = kd.kibz_k[kq_k[k1]]
            for n1 in range(self.nbands):
                for m1 in range(self.nbands):
                    focc = self.f_kn[ibzkpt1,n1] - self.f_kn[ibzkpt2,m1]
                    if np.abs(focc) > self.ftol:
                        self.e_S[iS] =self.e_kn[ibzkpt2,m1] - self.e_kn[ibzkpt1,n1]
                        focc_s[iS] = focc
                        self.Sindex_S3[iS] = (k1, n1, m1)
                        iS += 1
        self.nS = iS
        self.focc_S = np.zeros(self.nS)
        for iS in range(self.nS):
            self.focc_S[iS] = focc_s[iS]

        # parallel init
        self.Scomm = world
        # kcomm and wScomm is only to be used when wavefunctions r parallelly distributed.
        self.kcomm = world
        self.wScomm = serial_comm
        
        self.nS, self.nS_local, self.nS_start, self.nS_end = parallel_partition(
                               self.nS, self.Scomm.rank, self.Scomm.size, reshape=False)
        self.print_bse()

        self.get_phi_aGp()

        # Coulomb kernel init
        self.kc_G = np.zeros(self.npw)
        for iG in range(self.npw):
            index = self.Gindex_G[iG]
            qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv)
            self.kc_G[iG] = 1. / np.inner(qG, qG)
        if self.optical_limit:
            self.kc_G[0] = 0.
        self.printtxt('')
        
        return