Пример #1
0
    def __init__(
            self,
            atoms,  # XXX do we need atoms at this stage ?
            *args,
            name='raman',
            exext='.alpha',
            txt='-',
            verbose=False,
            comm=world,
            **kwargs):
        """
        Parameters
        ----------
        atoms: ase Atoms object
        exext: string
          Extension for excitation filenames
        txt:
          Output stream
        verbose:
          Verbosity level of output
        comm:
          Communicator, default world
        """
        kwargs['name'] = name
        self.exname = kwargs.pop('exname', name)

        super().__init__(atoms, *args, **kwargs)

        self.exext = exext

        self.timer = Timer()
        self.txt = convert_string_to_fd(txt)
        self.verbose = verbose

        self.comm = comm
Пример #2
0
    def __init__(self, cell_cv, response='density', comm=mpi.world,
                 txt='-', timer=None, nblocks=1, eshift=0.0):
        """Baseclass for Brillouin zone integration and band summation.

        Simple class to calculate integrals over Brilloun zones
        and summation of bands.

        comm: mpi.communicator
        nblocks: block parallelization
        """
        
        self.response = response
        self.comm = comm
        self.eshift = eshift
        self.nblocks = nblocks
        self.vol = abs(np.linalg.det(cell_cv))
        if nblocks == 1:
            self.blockcomm = self.comm.new_communicator([comm.rank])
            self.kncomm = comm
        else:
            assert comm.size % nblocks == 0, comm.size
            rank1 = comm.rank // nblocks * nblocks
            rank2 = rank1 + nblocks
            self.blockcomm = self.comm.new_communicator(range(rank1, rank2))
            ranks = range(comm.rank % nblocks, comm.size, nblocks)
            self.kncomm = self.comm.new_communicator(ranks)

        if comm.rank != 0:
            txt = devnull
        self.fd = convert_string_to_fd(txt, comm)

        self.timer = timer or Timer()
Пример #3
0
def calculate_renormalized_kernel(pd, calc, functional, fd):
    """Renormalized kernel"""

    from gpaw.xc.fxc import KernelDens
    kernel = KernelDens(calc,
                        functional, [pd.kd.bzk_kc[0]],
                        fd,
                        calc.wfs.kd.N_c,
                        None,
                        ecut=pd.ecut * Ha,
                        tag='',
                        timer=Timer())

    kernel.calculate_fhxc()
    r = Reader('fhxc_%s_%s_%s_%s.gpw' % ('', functional, pd.ecut * Ha, 0))
    Kxc_sGG = np.array([r.get('fhxc_sGsG')])

    v_G = 4 * np.pi / pd.G2_qG[0]
    Kxc_sGG[0] -= np.diagflat(v_G)

    if pd.kd.gamma:
        Kxc_sGG[:, 0, :] = 0.0
        Kxc_sGG[:, :, 0] = 0.0

    return Kxc_sGG
Пример #4
0
    def __init__(
            self,
            atoms,
            Excitations,
            indices=None,
            gsname='rraman',  # name for ground state calculations
            exname=None,  # name for excited state calculations
            delta=0.01,
            nfree=2,
            directions=None,
            exkwargs={},  # kwargs to be passed to Excitations
            exext='.ex.gz',  # extension for Excitation names
            txt='-',
            verbose=False):
        assert (nfree == 2)
        Vibrations.__init__(self, atoms, indices, gsname, delta, nfree)
        self.name = gsname + '-d%.3f' % delta
        if exname is None:
            exname = gsname
        self.exname = exname + '-d%.3f' % delta
        self.exext = exext

        if directions is None:
            self.directions = np.array([0, 1, 2])
        else:
            self.directions = np.array(directions)

        self.exobj = Excitations
        self.exkwargs = exkwargs

        self.timer = Timer()
        self.txt = get_txt(txt, rank)

        self.verbose = verbose
Пример #5
0
    def __init__(self,
                 calc,
                 xc='RPA',
                 filename=None,
                 skip_gamma=False,
                 qsym=True,
                 nlambda=None,
                 nfrequencies=16,
                 frequency_max=800.0,
                 frequency_scale=2.0,
                 frequencies=None,
                 weights=None,
                 world=mpi.world,
                 nblocks=1,
                 wstc=False,
                 txt=sys.stdout):

        if isinstance(calc, str):
            calc = GPAW(calc, txt=None, communicator=mpi.serial_comm)
        self.calc = calc

        if world.rank != 0:
            txt = devnull
        elif isinstance(txt, str):
            txt = open(txt, 'w')
        self.fd = txt

        self.timer = Timer()

        if frequencies is None:
            frequencies, weights = get_gauss_legendre_points(
                nfrequencies, frequency_max, frequency_scale)
            user_spec = False
        else:
            assert weights is not None
            user_spec = True

        self.omega_w = frequencies / Hartree
        self.weight_w = weights / Hartree

        if nblocks > 1:
            assert len(self.omega_w) % nblocks == 0
            assert wstc

        self.wstc = wstc
        self.nblocks = nblocks
        self.world = world

        self.skip_gamma = skip_gamma
        self.ibzq_qc = None
        self.weight_q = None
        self.initialize_q_points(qsym)

        # Energies for all q-vetors and cutoff energies:
        self.energy_qi = []

        self.filename = filename

        self.print_initialization(xc, frequency_scale, nlambda, user_spec)
Пример #6
0
def get_xc_kernel(pd, chi0, functional='ALDA', chi0_wGG=None):
    """Factory function that calls the relevant functions below"""

    calc = chi0.calc
    fd = chi0.fd
    nspins = len(calc.density.nt_sG)
    assert nspins == 1

    if functional[0] == 'A':
        # Standard adiabatic kernel
        print('Calculating %s kernel' % functional, file=fd)
        Kxc_sGG = calculate_Kxc(pd, calc, functional=functional)
    elif functional[0] == 'r':
        # Renormalized kernel
        print('Calculating %s kernel' % functional, file=fd)
        from gpaw.xc.fxc import KernelDens
        kernel = KernelDens(
            calc,
            functional,
            [pd.kd.bzk_kc[0]],
            fd,
            calc.wfs.kd.N_c,
            None,
            ecut=pd.ecut * Ha,
            tag='',
            timer=Timer(),
        )
        kernel.calculate_fhxc()
        r = Reader('fhxc_%s_%s_%s_%s.gpw' % ('', functional, pd.ecut * Ha, 0))
        Kxc_sGG = np.array([r.get('fhxc_sGsG')])

        v_G = 4 * np.pi / pd.G2_qG[0]
        Kxc_sGG[0] -= np.diagflat(v_G)

        if pd.kd.gamma:
            Kxc_sGG[:, 0, :] = 0.0
            Kxc_sGG[:, :, 0] = 0.0
    elif functional[:2] == 'LR':
        print('Calculating LR kernel with alpha = %s' % functional[2:],
              file=fd)
        Kxc_sGG = calculate_lr_kernel(pd, calc, alpha=float(functional[2:]))
    elif functional == 'DM':
        print('Calculating DM kernel', file=fd)
        Kxc_sGG = calculate_dm_kernel(pd, calc)
    elif functional == 'Bootstrap':
        print('Calculating Bootstrap kernel', file=fd)
        if chi0.world.rank == 0:
            chi0_GG = chi0_wGG[0]
            chi0.world.broadcast(chi0_GG, 0)
        else:
            nG = pd.ngmax
            chi0_GG = np.zeros((nG, nG), complex)
            chi0.world.broadcast(chi0_GG, 0)
        Kxc_sGG = calculate_bootstrap_kernel(pd, chi0_GG, fd)
    else:
        raise ValueError('%s kernel not implemented' % functional)

    return Kxc_sGG
Пример #7
0
    def __init__(self, lrtddft=None, index=0, d=0.001, txt=None,
                 parallel=0, communicator=None, name=None, restart=None):
        """ExcitedState object.
        parallel: Can be used to parallelize the numerical force calculation
        over images.
        """

        self.timer = Timer()
        self.atoms = None
        if isinstance(index, int):
            self.index = UnconstraintIndex(index)
        else:
            self.index = index

        self.results = {}
        self.results['forces'] = None
        self.results['energy'] = None
        if communicator is None:
            try:
                communicator = lrtddft.calculator.wfs.world
            except:
                communicator = mpi.world
        self.world = communicator

        if restart is not None:
            self.read(restart)
            if txt is None:
                self.txt = self.lrtddft.txt
            else:
                self.txt = convert_string_to_fd(txt, self.world)

        if lrtddft is not None:
            self.lrtddft = lrtddft
            self.calculator = self.lrtddft.calculator
            self.atoms = self.calculator.atoms
            self.parameters = self.calculator.parameters
            if txt is None:
                self.txt = self.lrtddft.txt
            else:
                self.txt = convert_string_to_fd(txt, self.world)

        self.d = d
        self.parallel = parallel
        self.name = name

        self.log = GPAWLogger(self.world)
        self.log.fd = self.txt
        self.reader = None
        self.calculator.log.fd = self.txt
        self.log('#', self.__class__.__name__, __version__)
        self.log('#', self.index)
        if name:
            self.log('name=' + name)
        self.log('# Force displacement:', self.d)
        self.log
Пример #8
0
    def __init__(self, calculator=None, **kwargs):

        self.timer = Timer()
        self.diagonalized = False

        changed = self.set(**kwargs)

        if isinstance(calculator, basestring):
            ExcitationList.__init__(self, None, self.txt)
            self.filename = calculator
        else:
            ExcitationList.__init__(self, calculator, self.txt)

        if self.filename is not None:
            self.read(self.filename)
            if set(['istart', 'jend', 'energy_range']) & set(changed):
                # the user has explicitely demanded these
                self.diagonalize()
            return

        if self.eh_comm is None:
            self.eh_comm = mpi.serial_comm
        elif isinstance(self.eh_comm,
                        (mpi.world.__class__, mpi.serial_comm.__class__)):
            # Correct type already.
            pass
        else:
            # world should be a list of ranks:
            self.eh_comm = mpi.world.new_communicator(np.asarray(self.eh_comm))

        if calculator is not None and calculator.initialized:
            # XXXX not ready for k-points
            assert (len(calculator.wfs.kd.ibzk_kc) == 1)
            if not isinstance(calculator.wfs, FDWaveFunctions):
                raise RuntimeError(
                    'Linear response TDDFT supported only in real space mode')
            if calculator.wfs.kd.comm.size > 1:
                err_txt = 'Spin parallelization with Linear response '
                err_txt += "TDDFT. Use parallel={'domain': world.size} "
                err_txt += 'calculator parameter.'
                raise NotImplementedError(err_txt)
            if self.xc == 'GS':
                self.xc = calculator.hamiltonian.xc
            if calculator.parameters.mode != 'lcao':
                calculator.converge_wave_functions()
            if calculator.density.nct_G is None:
                spos_ac = calculator.initialize_positions()
                calculator.wfs.initialize(calculator.density,
                                          calculator.hamiltonian, spos_ac)

            self.update(calculator)
Пример #9
0
    def __init__(self,
                 restart=None,
                 ignore_bad_restart_file=False,
                 label=None,
                 atoms=None,
                 timer=None,
                 communicator=None,
                 txt='-',
                 parallel=None,
                 **kwargs):

        self.parallel = dict(self.default_parallel)
        if parallel:
            for key in parallel:
                if key not in self.default_parallel:
                    allowed = ', '.join(list(self.default_parallel.keys()))
                    raise TypeError('Unexpected keyword "{}" in "parallel" '
                                    'dictionary.  Must be one of: {}'.format(
                                        key, allowed))
            self.parallel.update(parallel)

        if timer is None:
            self.timer = Timer()
        else:
            self.timer = timer

        self.scf = None
        self.wfs = None
        self.occupations = None
        self.density = None
        self.hamiltonian = None
        self.spos_ac = None  # XXX store this in some better way.

        self.observers = []  # XXX move to self.scf
        self.initialized = False

        self.world = communicator
        if self.world is None:
            self.world = mpi.world
        elif not hasattr(self.world, 'new_communicator'):
            self.world = mpi.world.new_communicator(np.asarray(self.world))

        self.log = GPAWLogger(world=self.world)
        self.log.fd = txt

        self.reader = None

        Calculator.__init__(self, restart, ignore_bad_restart_file, label,
                            atoms, **kwargs)
Пример #10
0
    def __init__(self, calculator=None, **kwargs):

        self.timer = Timer()

        self.set(**kwargs)

        if isinstance(calculator, str):
            ExcitationList.__init__(self, None, self.txt)
            self.filename = calculator
        else:
            ExcitationList.__init__(self, calculator, self.txt)

        if self.filename is not None:
            return self.read(self.filename)

        if self.eh_comm is None:
            self.eh_comm = mpi.serial_comm
        elif isinstance(self.eh_comm, (mpi.world.__class__,
                                       mpi.serial_comm.__class__)):
            # Correct type already.
            pass
        else:
            # world should be a list of ranks:
            self.eh_comm = mpi.world.new_communicator(np.asarray(eh_comm))

        if calculator is not None and calculator.initialized:
            if not isinstance(calculator.wfs, FDWaveFunctions):
                raise RuntimeError(
                    'Linear response TDDFT supported only in real space mode')
            if calculator.wfs.kd.comm.size > 1:
                err_txt = 'Spin parallelization with Linear response '
                err_txt += "TDDFT. Use parallel = {'domain' : 'domain_only'} "
                err_txt += 'calculator parameter.'
                raise NotImplementedError(err_txt)
            if self.xc == 'GS':
                self.xc = calculator.hamiltonian.xc.name
            if calculator.input_parameters.mode != 'lcao':
                calculator.converge_wave_functions()
            if calculator.density.nct_G is None:
                spos_ac = calculator.initialize_positions()
                calculator.wfs.initialize(calculator.density,
                                          calculator.hamiltonian, spos_ac)

            self.update(calculator)
Пример #11
0
    def __init__(self,
                 restart=None,
                 ignore_bad_restart_file=False,
                 label=None,
                 atoms=None,
                 timer=None,
                 communicator=None,
                 txt='-',
                 parallel=None,
                 **kwargs):

        self.parallel = dict(self.default_parallel)
        if parallel:
            self.parallel.update(parallel)

        if timer is None:
            self.timer = Timer()
        else:
            self.timer = timer

        self.scf = None
        self.wfs = None
        self.occupations = None
        self.density = None
        self.hamiltonian = None

        self.observers = []  # XXX move to self.scf
        self.initialized = False

        self.world = communicator
        if self.world is None:
            self.world = mpi.world
        elif not hasattr(self.world, 'new_communicator'):
            self.world = mpi.world.new_communicator(np.asarray(self.world))

        self.log = GPAWLogger(world=self.world)
        self.log.fd = txt

        self.reader = None

        Calculator.__init__(self, restart, ignore_bad_restart_file, label,
                            atoms, **kwargs)
Пример #12
0
    def __init__(self, lrtddft, d=0.001, txt=None, parallel=None):
        """Finite difference calculator for LrTDDFT.

        parallel: Can be used to parallelize the numerical force
        calculation over images
        """
        self.timer = Timer()
        self.atoms = None

        world = mpi.world
        if lrtddft is not None:
            self.lrtddft = lrtddft
            self.calculator = self.lrtddft.calculator
            self.atoms = self.calculator.atoms
            if self.calculator.initialized:
                world = self.calculator.wfs.world

            if txt is None:
                self.txt = self.lrtddft.txt
            else:
                self.txt = get_txt(txt, world.rank)
        prnt('#', self.__class__.__name__, version, file=self.txt)

        self.d = d
        self.parallel = {
            'world': world, 'mycomm': world, 'ncalcs': 1, 'icalc': 0}
        if world.size < 2:
            if parallel > 0:
                prnt('#', (self.__class__.__name__ + ':'),
                     'Serial calculation, keyword parallel ignored.',
                     file=self.txt)
        elif parallel > 0:
            mycomm, ncalcs, icalc = distribute_cpus(parallel, world)
            if type(ncalcs) != type(1):
                # this is ase < r3431
                ncalcs = world.size / parallel
            self.parallel = {'world': world, 'mycomm': mycomm,
                             'ncalcs': ncalcs, 'icalc': icalc}
            self.calculator.set(communicator=mycomm)
Пример #13
0
    def __init__(
        self,
        atoms,
        Excitations,
        indices=None,
        gsname='rraman',  # name for ground state calculations
        exname=None,  # name for excited state calculations
        delta=0.01,
        nfree=2,
        directions=None,
        approximation='Profeta',
        observation={'geometry': '-Z(XX)Z'},
        exkwargs={},  # kwargs to be passed to Excitations
        exext='.ex.gz',  # extension for Excitation names
        txt='-',
        verbose=False,
    ):
        assert (nfree == 2)
        Vibrations.__init__(self, atoms, indices, gsname, delta, nfree)
        self.name = gsname + '-d%.3f' % delta
        if exname is None:
            exname = gsname
        self.exname = exname + '-d%.3f' % delta
        self.exext = exext

        if directions is None:
            self.directions = np.array([0, 1, 2])
        else:
            self.directions = np.array(directions)

        self.approximation = approximation
        self.observation = observation
        self.exobj = Excitations
        self.exkwargs = exkwargs

        self.timer = Timer()
        self.txt = convert_string_to_fd(txt)

        self.verbose = verbose
Пример #14
0
    def get_rpa(self):
        """Calculate RPA and Hartree-fock part of the A+-B matrices."""

        # shorthands
        kss = self.fullkss
        finegrid = self.finegrid
        yukawa = hasattr(self.xc, 'rsf') and (self.xc.rsf == 'Yukawa')

        # calculate omega matrix
        nij = len(kss)
        print('RPAhyb', nij, 'transitions', file=self.txt)

        AmB = np.zeros((nij, nij))
        ApB = self.ApB

        # storage place for Coulomb integrals
        integrals = {}
        if yukawa:
            rsf_integrals = {}
        # setup things for IVOs
        if self.xc.excitation is not None or self.xc.excited != 0:
            sin_tri_weight = 1
            if self.xc.excitation is not None:
                ex_type = self.xc.excitation.lower()
                if ex_type == 'singlet':
                    sin_tri_weight = 2
                elif ex_type == 'triplet':
                    sin_tri_weight = 0
            h**o = int(self.paw.get_number_of_electrons() // 2)
            ivo_l = h**o - self.xc.excited - 1
        else:
            ivo_l = None

        for ij in range(nij):
            print('RPAhyb kss[' + '%d' % ij + ']=', kss[ij], file=self.txt)

            timer = Timer()
            timer.start('init')
            timer2 = Timer()

            # smooth density including compensation charges
            timer2.start('with_compensation_charges 0')
            rhot_p = kss[ij].with_compensation_charges(finegrid != 0)
            timer2.stop()

            # integrate with 1/|r_1-r_2|
            timer2.start('poisson')
            phit_p = np.zeros(rhot_p.shape, rhot_p.dtype)
            self.poisson.solve(phit_p, rhot_p, charge=None)
            timer2.stop()

            timer.stop()
            t0 = timer.get_time('init')
            timer.start(ij)

            if finegrid == 1:
                rhot = kss[ij].with_compensation_charges()
                phit = self.gd.zeros()
                self.restrict(phit_p, phit)
            else:
                phit = phit_p
                rhot = rhot_p

            for kq in range(ij, nij):
                if kq != ij:
                    # smooth density including compensation charges
                    timer2.start('kq with_compensation_charges')
                    rhot = kss[kq].with_compensation_charges(finegrid == 2)
                    timer2.stop()
                pre = self.weight_Kijkq(ij, kq)

                timer2.start('integrate')
                I = self.Coulomb_integral_kss(kss[ij], kss[kq], phit, rhot)
                if kss[ij].spin == kss[kq].spin:
                    name = self.Coulomb_integral_name(kss[ij].i, kss[ij].j,
                                                      kss[kq].i, kss[kq].j,
                                                      kss[ij].spin)
                    integrals[name] = I
                ApB[ij, kq] = pre * I
                timer2.stop()

                if ij == kq:
                    epsij = kss[ij].get_energy() / kss[ij].get_weight()
                    AmB[ij, kq] += epsij
                    ApB[ij, kq] += epsij

            timer.stop()
            # timer2.write()
            if ij < (nij - 1):
                print('RPAhyb estimated time left',
                      self.time_left(timer, t0, ij, nij),
                      file=self.txt)

        # add HF parts and apply symmetry
        if hasattr(self.xc, 'hybrid'):
            weight = self.xc.hybrid
        else:
            weight = 0.0
        for ij in range(nij):
            print('HF kss[' + '%d' % ij + ']', file=self.txt)
            timer = Timer()
            timer.start('init')
            timer.stop()
            t0 = timer.get_time('init')
            timer.start(ij)

            i = kss[ij].i
            j = kss[ij].j
            s = kss[ij].spin
            for kq in range(ij, nij):
                if kss[ij].pspin == kss[kq].pspin:
                    k = kss[kq].i
                    q = kss[kq].j
                    ikjq = self.Coulomb_integral_ijkq(i, k, j, q, s, integrals)
                    iqkj = self.Coulomb_integral_ijkq(i, q, k, j, s, integrals)
                    if yukawa:  # Yukawa integrals might be caches
                        ikjq -= self.Coulomb_integral_ijkq(
                            i, k, j, q, s, rsf_integrals, yukawa)
                        iqkj -= self.Coulomb_integral_ijkq(
                            i, q, k, j, s, rsf_integrals, yukawa)
                    ApB[ij, kq] -= weight * (ikjq + iqkj)
                    AmB[ij, kq] -= weight * (ikjq - iqkj)

                ApB[kq, ij] = ApB[ij, kq]
                AmB[kq, ij] = AmB[ij, kq]

            timer.stop()
            if ij < (nij - 1):
                print('HF estimated time left',
                      self.time_left(timer, t0, ij, nij),
                      file=self.txt)

        if ivo_l is not None:
            # IVO RPA after Berman, Kaldor, Chem. Phys. 43 (3) 1979
            # doi: 10.1016/0301-0104(79)85205-2
            l = ivo_l
            for ij in range(nij):
                i = kss[ij].i
                j = kss[ij].j
                s = kss[ij].spin
                for kq in range(ij, nij):
                    if kss[kq].i == i and kss[ij].pspin == kss[kq].pspin:
                        k = kss[kq].i
                        q = kss[kq].j
                        jqll = self.Coulomb_integral_ijkq(
                            j, q, l, l, s, integrals)
                        jllq = self.Coulomb_integral_ijkq(
                            j, l, l, q, s, integrals)
                        if yukawa:
                            jqll -= self.Coulomb_integral_ijkq(
                                j, q, l, l, s, rsf_integrals, yukawa)
                            jllq -= self.Coulomb_integral_ijkq(
                                j, l, l, q, s, rsf_integrals, yukawa)
                        jllq *= sin_tri_weight
                        ApB[ij, kq] += weight * (jqll - jllq)
                        AmB[ij, kq] += weight * (jqll - jllq)
                        ApB[kq, ij] = ApB[ij, kq]
                        AmB[kq, ij] = AmB[ij, kq]
        return AmB
Пример #15
0
    def __init__(self, atoms, Excitations,
                 indices=None,
                 gsname='rraman',  # name for ground state calculations
                 exname=None,      # name for excited state calculations
                 delta=0.01,
                 nfree=2,
                 directions=None,
                 observation={'geometry': '-Z(XX)Z'},
                 form='v',         # form of the dipole operator
                 exkwargs={},      # kwargs to be passed to Excitations
                 exext='.ex.gz',   # extension for Excitation names
                 txt='-',
                 verbose=False,
                 overlap=False,
                 minoverlap=0.02,
                 minrep=0.8,
                 comm=world,
    ):
        """
        Parameters
        ----------
        atoms: ase Atoms object
        Excitations: class
            Type of the excitation list object. The class object is
            initialized as::

                Excitations(atoms.get_calculator())

            or by reading form a file as::

                Excitations('filename', **exkwargs)

            The file is written by calling the method
            Excitations.write('filename').

            Excitations should work like a list of ex obejects, where:
                ex.get_dipole_me(form='v'):
                    gives the velocity form dipole matrix element in
                    units |e| * Angstrom
                ex.energy:
                    is the transition energy in Hartrees
        indices: list
        gsname: string
            name for ground state calculations
        exname: string
            name for excited state calculations
        delta: float
            Finite difference displacement in Angstrom.
        nfree: float
        directions:
        approximation: string
            Level of approximation used.
        observation: dict
            Polarization settings
        form: string
            Form of the dipole operator, 'v' for velocity form (default)
            and 'r' for length form.
        exkwargs: dict
            Arguments given to the Excitations objects in reading.
        exext: string
            Extension for filenames of Excitation lists.
        txt:
            Output stream
        verbose:
            Verbosity level of output
        overlap: bool or function
            Use wavefunction overlaps.
        minoverlap: float ord dict
            Minimal absolute overlap to consider. Defaults to 0.02 to avoid
            numerical garbage.
        minrep: float
            Minimal represention to consider derivative, defaults to 0.8
        """
        assert(nfree == 2)
        Vibrations.__init__(self, atoms, indices, gsname, delta, nfree)
        self.name = gsname + '-d%.3f' % delta
        if exname is None:
            exname = gsname
        self.exname = exname + '-d%.3f' % delta
        self.exext = exext

        if directions is None:
            self.directions = np.array([0, 1, 2])
        else:
            self.directions = np.array(directions)

        self.observation = observation
        self.exobj = Excitations
        self.exkwargs = exkwargs
        self.dipole_form = form

        self.timer = Timer()
        self.txt = convert_string_to_fd(txt)

        self.verbose = verbose
        self.overlap = overlap
        if not isinstance(minoverlap, dict):
            # assume it's a number
            self.minoverlap = {'orbitals': minoverlap,
                               'excitations': minoverlap}
        else:
            self.minoverlap = minoverlap
        self.minrep = minrep

        self.comm = comm
Пример #16
0
    def __init__(self, calc, xc='RPA', filename=None,
                 skip_gamma=False, qsym=True, nlambda=None,
                 nfrequencies=16, frequency_max=800.0, frequency_scale=2.0,
                 frequencies=None, weights=None, truncation=None,
                 world=mpi.world, nblocks=1, txt=sys.stdout):
        """Creates the RPACorrelation object
        
        calc: str or calculator object
            The string should refer to the .gpw file contaning KS orbitals
        xc: str
            Exchange-correlation kernel. This is only different from RPA when
            this object is constructed from a different module - e.g. fxc.py
        filename: str
            txt output
        skip_gamme: bool
            If True, skip q = [0,0,0] from the calculation
        qsym: bool
            Use symmetry to reduce q-points
        nlambda: int
            Number of lambda points. Only used for numerical coupling
            constant integration involved when called from fxc.py
        nfrequencies: int
            Number of frequency points used in the Gauss-Legendre integration
        frequency_max: float
            Largest frequency point in Gauss-Legendre integration
        frequency_scale: float
            Determines density of frequency points at low frequencies. A slight
            increase to e.g. 2.5 or 3.0 improves convergence wth respect to
            frequency points for metals
        frequencies: list
            List of frequancies for user-specified frequency integration
        weights: list
            list of weights (integration measure) for a user specified
            frequency grid. Must be specified and have the same length as
            frequencies if frequencies is not None
        truncation: str
            Coulomb truncation scheme. Can be either wigner-seitz,
            2D, 1D, or 0D
        world: communicator
        nblocks: int
            Number of parallelization blocks. Frequency parallelization
            can be specified by setting nblocks=nfrequencies and is useful
            for memory consuming calculations
        txt: str
            txt file for saving and loading contributions to the correlation
            energy from different q-points
        """

        if isinstance(calc, str):
            calc = GPAW(calc, txt=None, communicator=mpi.serial_comm)
        self.calc = calc

        if world.rank != 0:
            txt = devnull
        elif isinstance(txt, str):
            txt = open(txt, 'w', 1)
        self.fd = txt

        self.timer = Timer()
        
        if frequencies is None:
            frequencies, weights = get_gauss_legendre_points(nfrequencies,
                                                             frequency_max,
                                                             frequency_scale)
            user_spec = False
        else:
            assert weights is not None
            user_spec = True
            
        self.omega_w = frequencies / Hartree
        self.weight_w = weights / Hartree

        if nblocks > 1:
            assert len(self.omega_w) % nblocks == 0

        self.nblocks = nblocks
        self.world = world

        self.truncation = truncation
        self.skip_gamma = skip_gamma
        self.ibzq_qc = None
        self.weight_q = None
        self.initialize_q_points(qsym)

        # Energies for all q-vetors and cutoff energies:
        self.energy_qi = []

        self.filename = filename

        self.print_initialization(xc, frequency_scale, nlambda, user_spec)
Пример #17
0
 def __init__(self):
     self.timer = Timer()
Пример #18
0
from __future__ import print_function

from ase import Atoms
from ase.parallel import parprint
from ase.utils.timing import Timer

from gpaw import GPAW
from gpaw.test import equal
from gpaw.xc.hybrid import HybridXC

timer = Timer()

loa = Atoms('Be2', [(0, 0, 0), (2.45, 0, 0)], cell=[5.9, 4.8, 5.0])
loa.center()

txt = None
xc = 'PBE0'
nbands = 4

unocc = True
load = False

# usual calculation
fname = 'Be2.gpw'
if not load:
    xco = HybridXC(xc)
    cocc = GPAW(h=0.3,
                eigensolver='rmm-diis',
                xc=xco,
                nbands=nbands,
                convergence={'eigenstates': 1e-4},
Пример #19
0
    def __init__(self,
                 calc,
                 response='density',
                 frequencies=None,
                 domega0=0.1,
                 omega2=10.0,
                 omegamax=None,
                 ecut=50,
                 gammacentered=False,
                 hilbert=True,
                 nbands=None,
                 timeordered=False,
                 eta=0.2,
                 ftol=1e-6,
                 threshold=1,
                 real_space_derivatives=False,
                 intraband=True,
                 world=mpi.world,
                 txt='-',
                 timer=None,
                 nblocks=1,
                 gate_voltage=None,
                 disable_point_group=False,
                 disable_time_reversal=False,
                 disable_non_symmorphic=True,
                 scissor=None,
                 integrationmode=None,
                 pbc=None,
                 rate=0.0,
                 eshift=0.0):
        """Construct Chi0 object.
        
        Parameters
        ----------
        calc : str
            The groundstate calculation file that the linear response
            calculation is based on.
        response : str
            Type of response function. Currently collinear, scalar options
            'density', '+-' and '-+' are implemented.
        frequencies : ndarray or None
            Array of frequencies to evaluate the response function at. If None,
            frequencies are determined using the frequency_grid function in
            gpaw.response.chi0.
        domega0, omega2, omegamax : float
            Input parameters for frequency_grid.
        ecut : float
            Energy cutoff.
        gammacentered : bool
            Center the grid of plane waves around the gamma point or q-vector
        hilbert : bool
            Switch for hilbert transform. If True, the full density response
            is determined from a hilbert transform of its spectral function.
            This is typically much faster, but does not work for imaginary
            frequencies.
        nbands : int
            Maximum band index to include.
        timeordered : bool
            Switch for calculating the time ordered density response function.
            In this case the hilbert transform cannot be used.
        eta : float
            Artificial broadening of spectra.
        ftol : float
            Threshold determining whether a band is completely filled
            (f > 1 - ftol) or completely empty (f < ftol).
        threshold : float
            Numerical threshold for the optical limit k dot p perturbation
            theory expansion (used in gpaw/response/pair.py).
        real_space_derivatives : bool
            Switch for calculating nabla matrix elements (in the optical limit)
            using a real space finite difference approximation.
        intraband : bool
            Switch for including the intraband contribution to the density
            response function.
        world : MPI comm instance
            MPI communicator.
        txt : str
            Output file.
        timer : gpaw.utilities.timing.timer instance
        nblocks : int
            Divide the response function into nblocks. Useful when the response
            function is large.
        gate_voltage : float
            Shift the fermi level by gate_voltage [Hartree].
        disable_point_group : bool
            Do not use the point group symmetry operators.
        disable_time_reversal : bool
            Do not use time reversal symmetry.
        disable_non_symmorphic : bool
            Do no use non symmorphic symmetry operators.
        scissor : tuple ([bands], shift [eV])
            Use scissor operator on bands.
        integrationmode : str
            Integrator for the kpoint integration.
            If == 'tetrahedron integration' then the kpoint integral is
            performed using the linear tetrahedron method.
        pbc : list
            Periodic directions of the system. Defaults to [True, True, True].
        eshift : float
            Shift unoccupied bands

        Attributes
        ----------
        pair : gpaw.response.pair.PairDensity instance
            Class for calculating matrix elements of pairs of wavefunctions.

        """

        self.response = response

        self.timer = timer or Timer()

        self.pair = PairDensity(calc,
                                ecut,
                                self.response,
                                ftol,
                                threshold,
                                real_space_derivatives,
                                world,
                                txt,
                                self.timer,
                                nblocks=nblocks,
                                gate_voltage=gate_voltage)

        self.disable_point_group = disable_point_group
        self.disable_time_reversal = disable_time_reversal
        self.disable_non_symmorphic = disable_non_symmorphic
        self.integrationmode = integrationmode
        self.eshift = eshift / Hartree

        calc = self.pair.calc
        self.calc = calc

        if world.rank != 0:
            txt = devnull
        elif isinstance(txt, str):
            txt = open(txt, 'w')
        self.fd = txt

        self.vol = abs(np.linalg.det(calc.wfs.gd.cell_cv))

        self.world = world

        if nblocks == 1:
            self.blockcomm = self.world.new_communicator([world.rank])
            self.kncomm = world
        else:
            assert world.size % nblocks == 0, world.size
            rank1 = world.rank // nblocks * nblocks
            rank2 = rank1 + nblocks
            self.blockcomm = self.world.new_communicator(range(rank1, rank2))
            ranks = range(world.rank % nblocks, world.size, nblocks)
            self.kncomm = self.world.new_communicator(ranks)

        self.nblocks = nblocks

        if world.rank != 0:
            txt = devnull
        elif isinstance(txt, str):
            txt = open(txt, 'w')
        self.fd = txt

        if ecut is not None:
            ecut /= Hartree

        self.ecut = ecut
        self.gammacentered = gammacentered

        self.eta = eta / Hartree
        if rate == 'eta':
            self.rate = self.eta
        else:
            self.rate = rate / Hartree
        self.domega0 = domega0 / Hartree
        self.omega2 = omega2 / Hartree
        self.omegamax = None if omegamax is None else omegamax / Hartree
        self.nbands = nbands or self.calc.wfs.bd.nbands
        self.include_intraband = intraband

        omax = self.find_maximum_frequency()

        if frequencies is None:
            if self.omegamax is None:
                self.omegamax = omax
            print('Using nonlinear frequency grid from 0 to %.3f eV' %
                  (self.omegamax * Hartree),
                  file=self.fd)
            self.wd = FrequencyDescriptor(self.domega0, self.omega2,
                                          self.omegamax)
        else:
            self.wd = ArrayDescriptor(np.asarray(frequencies) / Hartree)
            assert not hilbert

        self.omega_w = self.wd.get_data()
        self.hilbert = hilbert
        self.timeordered = bool(timeordered)

        if self.eta == 0.0:
            assert not hilbert
            assert not timeordered
            assert not self.omega_w.real.any()

        self.nocc1 = self.pair.nocc1  # number of completely filled bands
        self.nocc2 = self.pair.nocc2  # number of non-empty bands

        self.Q_aGii = None

        if pbc is not None:
            self.pbc = np.array(pbc)
        else:
            self.pbc = np.array([True, True, True])

        if self.pbc is not None and (~self.pbc).any():
            assert np.sum((~self.pbc).astype(int)) == 1, \
                print('Only one non-periodic direction supported atm.')
            print('Nonperiodic BC\'s: ', (~self.pbc), file=self.fd)

        if integrationmode is not None:
            print('Using integration method: ' + self.integrationmode,
                  file=self.fd)
        else:
            print('Using integration method: PointIntegrator', file=self.fd)
Пример #20
0
    def get_rpa(self):
        """calculate RPA part of the omega matrix"""

        # shorthands
        kss = self.fullkss
        finegrid = self.finegrid
        wfs = self.paw.wfs
        eh_comm = self.eh_comm

        # calculate omega matrix
        nij = len(kss)
        print('RPA', nij, 'transitions', file=self.txt)

        Om = self.Om

        for ij in range(eh_comm.rank, nij, eh_comm.size):
            print('RPA kss[' + '%d' % ij + ']=', kss[ij], file=self.txt)

            timer = Timer()
            timer.start('init')
            timer2 = Timer()

            # smooth density including compensation charges
            timer2.start('with_compensation_charges 0')
            rhot_p = kss[ij].with_compensation_charges(
                finegrid is not 0)
            timer2.stop()

            # integrate with 1/|r_1-r_2|
            timer2.start('poisson')
            phit_p = np.zeros(rhot_p.shape, rhot_p.dtype.char)
            self.poisson.solve(phit_p, rhot_p, charge=None)
            timer2.stop()

            timer.stop()
            t0 = timer.get_time('init')
            timer.start(ij)

            if finegrid == 1:
                rhot = kss[ij].with_compensation_charges()
                phit = self.gd.zeros()
# print "shapes 0=",phit.shape,rhot.shape
                self.restrict(phit_p, phit)
            else:
                phit = phit_p
                rhot = rhot_p

            for kq in range(ij, nij):
                if kq != ij:
                    # smooth density including compensation charges
                    timer2.start('kq with_compensation_charges')
                    rhot = kss[kq].with_compensation_charges(
                        finegrid is 2)
                    timer2.stop()

                pre = 2 * sqrt(kss[ij].get_energy() * kss[kq].get_energy() *
                               kss[ij].get_weight() * kss[kq].get_weight())
                I = self.Coulomb_integral_kss(kss[ij], kss[kq],
                                              rhot, phit, timer2)
                Om[ij, kq] = pre * I

                if ij == kq:
                    Om[ij, kq] += kss[ij].get_energy() ** 2
                else:
                    Om[kq, ij] = Om[ij, kq]

            timer.stop()
# timer2.write()
            if ij < (nij - 1):
                t = timer.get_time(ij)  # time for nij-ij calculations
                t = .5 * t * \
                    (nij - ij)  # estimated time for n*(n+1)/2, n=nij-(ij+1)
                print('RPA estimated time left',
                      self.timestring(t0 * (nij - ij - 1) + t), file=self.txt)
Пример #21
0
    def get_xc(self):
        """Add xc part of the coupling matrix"""

        # shorthands
        paw = self.paw
        wfs = paw.wfs
        gd = paw.density.finegd
        comm = gd.comm
        eh_comm = self.eh_comm

        fg = self.finegrid is 2
        kss = self.fullkss
        nij = len(kss)

        Om_xc = self.Om
        # initialize densities
        # nt_sg is the smooth density on the fine grid with spin index

        if kss.nvspins == 2:
            # spin polarised ground state calc.
            nt_sg = paw.density.nt_sg
        else:
            # spin unpolarised ground state calc.
            if kss.npspins == 2:
                # construct spin polarised densities
                nt_sg = np.array([.5 * paw.density.nt_sg[0],
                                  .5 * paw.density.nt_sg[0]])
            else:
                nt_sg = paw.density.nt_sg
        # check if D_sp have been changed before
        D_asp = self.paw.density.D_asp
        for a, D_sp in D_asp.items():
            if len(D_sp) != kss.npspins:
                if len(D_sp) == 1:
                    D_asp[a] = np.array([0.5 * D_sp[0], 0.5 * D_sp[0]])
                else:
                    D_asp[a] = np.array([D_sp[0] + D_sp[1]])

        # restrict the density if needed
        if fg:
            nt_s = nt_sg
        else:
            nt_s = self.gd.zeros(nt_sg.shape[0])
            for s in range(nt_sg.shape[0]):
                self.restrict(nt_sg[s], nt_s[s])
            gd = paw.density.gd

        # initialize vxc or fxc

        if self.derivativeLevel == 0:
            raise NotImplementedError
            if kss.npspins == 2:
                v_g = nt_sg[0].copy()
            else:
                v_g = nt_sg.copy()
        elif self.derivativeLevel == 1:
            pass
        elif self.derivativeLevel == 2:
            fxc_sg = np.zeros(nt_sg.shape)
            self.xc.calculate_fxc(gd, nt_sg, fxc_sg)
        else:
            raise ValueError('derivativeLevel can only be 0,1,2')

# self.paw.my_nuclei = []

        ns = self.numscale
        xc = self.xc
        print('XC', nij, 'transitions', file=self.txt)
        for ij in range(eh_comm.rank, nij, eh_comm.size):
            print('XC kss[' + '%d' % ij + ']', file=self.txt)

            timer = Timer()
            timer.start('init')
            timer2 = Timer()

            if self.derivativeLevel >= 1:
                # vxc is available
                # We use the numerical two point formula for calculating
                # the integral over fxc*n_ij. The results are
                # vvt_s        smooth integral
                # nucleus.I_sp atom based correction matrices (pack2)
                #              stored on each nucleus
                timer2.start('init v grids')
                vp_s = np.zeros(nt_s.shape, nt_s.dtype.char)
                vm_s = np.zeros(nt_s.shape, nt_s.dtype.char)
                if kss.npspins == 2:  # spin polarised
                    nv_s = nt_s.copy()
                    nv_s[kss[ij].pspin] += ns * kss[ij].get(fg)
                    xc.calculate(gd, nv_s, vp_s)
                    nv_s = nt_s.copy()
                    nv_s[kss[ij].pspin] -= ns * kss[ij].get(fg)
                    xc.calculate(gd, nv_s, vm_s)
                else:  # spin unpolarised
                    nv = nt_s + ns * kss[ij].get(fg)
                    xc.calculate(gd, nv, vp_s)
                    nv = nt_s - ns * kss[ij].get(fg)
                    xc.calculate(gd, nv, vm_s)
                vvt_s = (0.5 / ns) * (vp_s - vm_s)
                timer2.stop()

                # initialize the correction matrices
                timer2.start('init v corrections')
                I_asp = {}
                for a, P_ni in wfs.kpt_u[kss[ij].spin].P_ani.items():
                    # create the modified density matrix
                    Pi_i = P_ni[kss[ij].i]
                    Pj_i = P_ni[kss[ij].j]
                    P_ii = np.outer(Pi_i, Pj_i)
                    # we need the symmetric form, hence we can pack
                    P_p = pack(P_ii)
                    D_sp = self.paw.density.D_asp[a].copy()
                    D_sp[kss[ij].pspin] -= ns * P_p
                    setup = wfs.setups[a]
                    I_sp = np.zeros_like(D_sp)
                    self.xc.calculate_paw_correction(setup, D_sp, I_sp)
                    I_sp *= -1.0
                    D_sp = self.paw.density.D_asp[a].copy()
                    D_sp[kss[ij].pspin] += ns * P_p
                    self.xc.calculate_paw_correction(setup, D_sp, I_sp)
                    I_sp /= 2.0 * ns
                    I_asp[a] = I_sp
                timer2.stop()

            timer.stop()
            t0 = timer.get_time('init')
            timer.start(ij)

            for kq in range(ij, nij):
                weight = self.weight_Kijkq(ij, kq)

                if self.derivativeLevel == 0:
                    # only Exc is available

                    if kss.npspins == 2:  # spin polarised
                        nv_g = nt_sg.copy()
                        nv_g[kss[ij].pspin] += kss[ij].get(fg)
                        nv_g[kss[kq].pspin] += kss[kq].get(fg)
                        Excpp = xc.get_energy_and_potential(
                            nv_g[0], v_g, nv_g[1], v_g)
                        nv_g = nt_sg.copy()
                        nv_g[kss[ij].pspin] += kss[ij].get(fg)
                        nv_g[kss[kq].pspin] -= kss[kq].get(fg)
                        Excpm = xc.get_energy_and_potential(
                            nv_g[0], v_g, nv_g[1], v_g)
                        nv_g = nt_sg.copy()
                        nv_g[kss[ij].pspin] -=\
                            kss[ij].get(fg)
                        nv_g[kss[kq].pspin] +=\
                            kss[kq].get(fg)
                        Excmp = xc.get_energy_and_potential(
                            nv_g[0], v_g, nv_g[1], v_g)
                        nv_g = nt_sg.copy()
                        nv_g[kss[ij].pspin] -= \
                            kss[ij].get(fg)
                        nv_g[kss[kq].pspin] -=\
                            kss[kq].get(fg)
                        Excpp = xc.get_energy_and_potential(
                            nv_g[0], v_g, nv_g[1], v_g)
                    else:  # spin unpolarised
                        nv_g = nt_sg + ns * kss[ij].get(fg)\
                            + ns * kss[kq].get(fg)
                        Excpp = xc.get_energy_and_potential(nv_g, v_g)
                        nv_g = nt_sg + ns * kss[ij].get(fg)\
                            - ns * kss[kq].get(fg)
                        Excpm = xc.get_energy_and_potential(nv_g, v_g)
                        nv_g = nt_sg - ns * kss[ij].get(fg)\
                            + ns * kss[kq].get(fg)
                        Excmp = xc.get_energy_and_potential(nv_g, v_g)
                        nv_g = nt_sg - ns * kss[ij].get(fg)\
                            - ns * kss[kq].get(fg)
                        Excmm = xc.get_energy_and_potential(nv_g, v_g)

                    Om_xc[ij, kq] += weight *\
                        0.25 * \
                        (Excpp - Excmp - Excpm + Excmm) / (ns * ns)

                elif self.derivativeLevel == 1:
                    # vxc is available

                    timer2.start('integrate')
                    Om_xc[ij, kq] += weight *\
                        self.gd.integrate(kss[kq].get(fg) *
                                          vvt_s[kss[kq].pspin])
                    timer2.stop()

                    timer2.start('integrate corrections')
                    Exc = 0.
                    for a, P_ni in wfs.kpt_u[kss[kq].spin].P_ani.items():
                        # create the modified density matrix
                        Pk_i = P_ni[kss[kq].i]
                        Pq_i = P_ni[kss[kq].j]
                        P_ii = np.outer(Pk_i, Pq_i)
                        # we need the symmetric form, hence we can pack
                        # use pack as I_sp used pack2
                        P_p = pack(P_ii)
                        Exc += np.dot(I_asp[a][kss[kq].pspin], P_p)
                    Om_xc[ij, kq] += weight * self.gd.comm.sum(Exc)
                    timer2.stop()

                elif self.derivativeLevel == 2:
                    # fxc is available
                    if kss.npspins == 2:  # spin polarised
                        Om_xc[ij, kq] += weight *\
                            gd.integrate(kss[ij].get(fg) *
                                         kss[kq].get(fg) *
                                         fxc_sg[kss[ij].pspin, kss[kq].pspin])
                    else:  # spin unpolarised
                        Om_xc[ij, kq] += weight *\
                            gd.integrate(kss[ij].get(fg) *
                                         kss[kq].get(fg) *
                                         fxc_sg)

                    # XXX still numeric derivatives for local terms
                    timer2.start('integrate corrections')
                    Exc = 0.
                    for a, P_ni in wfs.kpt_u[kss[kq].spin].P_ani.items():
                        # create the modified density matrix
                        Pk_i = P_ni[kss[kq].i]
                        Pq_i = P_ni[kss[kq].j]
                        P_ii = np.outer(Pk_i, Pq_i)
                        # we need the symmetric form, hence we can pack
                        # use pack as I_sp used pack2
                        P_p = pack(P_ii)
                        Exc += np.dot(I_asp[a][kss[kq].pspin], P_p)
                    Om_xc[ij, kq] += weight * self.gd.comm.sum(Exc)
                    timer2.stop()

                if ij != kq:
                    Om_xc[kq, ij] = Om_xc[ij, kq]

            timer.stop()
# timer2.write()
            if ij < (nij - 1):
                print('XC estimated time left',
                      self.time_left(timer, t0, ij, nij), file=self.txt)
Пример #22
0
    def __init__(self,
                 name,
                 hybrid=None,
                 xc=None,
                 alpha=None,
                 gamma_point=1,
                 method='standard',
                 bandstructure=False,
                 logfilename='-',
                 bands=None,
                 fcut=1e-10,
                 molecule=False,
                 qstride=1,
                 world=None):
        """Mix standard functionals with exact exchange.

        name: str
            Name of functional: EXX, PBE0, HSE03, HSE06
        hybrid: float
            Fraction of exact exchange.
        xc: str or XCFunctional object
            Standard DFT functional with scaled down exchange.
        method: str
            Use 'standard' standard formula and 'acdf for
            adiabatic-connection dissipation fluctuation formula.
        alpha: float
            XXX describe
        gamma_point: bool
            0: Skip k2-k1=0 interactions.
            1: Use the alpha method.
            2: Integrate the gamma point.
        bandstructure: bool
            Calculate bandstructure instead of just the total energy.
        bands: list of int
            List of bands to calculate bandstructure for.  Default is
            all bands.
        molecule: bool
            Decouple electrostatic interactions between periodically
            repeated images.
        fcut: float
            Threshold for empty band.
        """

        self.alpha = alpha
        self.fcut = fcut

        self.gamma_point = gamma_point
        self.method = method
        self.bandstructure = bandstructure
        self.bands = bands

        self.fd = logfilename
        self.write_timing_information = True

        HybridXCBase.__init__(self, name, hybrid, xc)

        # EXX energies:
        self.exx = None  # total
        self.evv = None  # valence-valence (pseudo part)
        self.evvacdf = None  # valence-valence (pseudo part)
        self.devv = None  # valence-valence (PAW correction)
        self.evc = None  # valence-core
        self.ecc = None  # core-core

        self.exx_skn = None  # bandstructure

        self.qlatest = None

        if world is None:
            world = mpi.world
        self.world = world

        self.molecule = molecule

        if isinstance(qstride, int):
            qstride = [qstride] * 3
        self.qstride_c = np.asarray(qstride)

        self.timer = Timer()
Пример #23
0
    def get_rpa(self):
        """Calculate RPA and Hartree-fock part of the A+-B matrices."""

        # shorthands
        kss = self.fullkss
        finegrid = self.finegrid

        # calculate omega matrix
        nij = len(kss)
        print('RPAhyb', nij, 'transitions', file=self.txt)

        AmB = np.zeros((nij, nij))
        ApB = self.ApB

        # storage place for Coulomb integrals
        integrals = {}

        for ij in range(nij):
            print('RPAhyb kss[' + '%d' % ij + ']=', kss[ij], file=self.txt)

            timer = Timer()
            timer.start('init')
            timer2 = Timer()

            # smooth density including compensation charges
            timer2.start('with_compensation_charges 0')
            rhot_p = kss[ij].with_compensation_charges(finegrid is not 0)
            timer2.stop()

            # integrate with 1/|r_1-r_2|
            timer2.start('poisson')
            phit_p = np.zeros(rhot_p.shape, rhot_p.dtype)
            self.poisson.solve(phit_p, rhot_p, charge=None)
            timer2.stop()

            timer.stop()
            t0 = timer.get_time('init')
            timer.start(ij)

            if finegrid == 1:
                rhot = kss[ij].with_compensation_charges()
                phit = self.gd.zeros()
                self.restrict(phit_p, phit)
            else:
                phit = phit_p
                rhot = rhot_p

            for kq in range(ij, nij):
                if kq != ij:
                    # smooth density including compensation charges
                    timer2.start('kq with_compensation_charges')
                    rhot = kss[kq].with_compensation_charges(finegrid is 2)
                    timer2.stop()
                pre = self.weight_Kijkq(ij, kq)

                timer2.start('integrate')
                I = self.Coulomb_integral_kss(kss[ij], kss[kq], phit, rhot)
                if kss[ij].spin == kss[kq].spin:
                    name = self.Coulomb_integral_name(kss[ij].i, kss[ij].j,
                                                      kss[kq].i, kss[kq].j,
                                                      kss[ij].spin)
                    integrals[name] = I
                ApB[ij, kq] = pre * I
                timer2.stop()

                if ij == kq:
                    epsij = kss[ij].get_energy() / kss[ij].get_weight()
                    AmB[ij, kq] += epsij
                    ApB[ij, kq] += epsij

            timer.stop()
            # timer2.write()
            if ij < (nij - 1):
                print('RPAhyb estimated time left',
                      self.time_left(timer, t0, ij, nij),
                      file=self.txt)

        # add HF parts and apply symmetry
        if hasattr(self.xc, 'hybrid'):
            weight = self.xc.hybrid
        else:
            weight = 0.0
        for ij in range(nij):
            print('HF kss[' + '%d' % ij + ']', file=self.txt)
            timer = Timer()
            timer.start('init')
            timer.stop()
            t0 = timer.get_time('init')
            timer.start(ij)

            i = kss[ij].i
            j = kss[ij].j
            s = kss[ij].spin
            for kq in range(ij, nij):
                if kss[ij].pspin == kss[kq].pspin:
                    k = kss[kq].i
                    q = kss[kq].j
                    ikjq = self.Coulomb_integral_ijkq(i, k, j, q, s, integrals)
                    iqkj = self.Coulomb_integral_ijkq(i, q, k, j, s, integrals)
                    ApB[ij, kq] -= weight * (ikjq + iqkj)
                    AmB[ij, kq] -= weight * (ikjq - iqkj)

                ApB[kq, ij] = ApB[ij, kq]
                AmB[kq, ij] = AmB[ij, kq]

            timer.stop()
            if ij < (nij - 1):
                print('HF estimated time left',
                      self.time_left(timer, t0, ij, nij),
                      file=self.txt)

        return AmB
Пример #24
0
    def __init__(self,
                 calc,
                 ecut=50,
                 ftol=1e-6,
                 threshold=1,
                 real_space_derivatives=False,
                 world=mpi.world,
                 txt=sys.stdout,
                 timer=None,
                 nblocks=1,
                 gate_voltage=None):
        if ecut is not None:
            ecut /= Hartree

        if gate_voltage is not None:
            gate_voltage /= Hartree

        self.ecut = ecut
        self.ftol = ftol
        self.threshold = threshold
        self.real_space_derivatives = real_space_derivatives
        self.world = world
        self.gate_voltage = gate_voltage

        if nblocks == 1:
            self.blockcomm = self.world.new_communicator([world.rank])
            self.kncomm = world
        else:
            assert world.size % nblocks == 0, world.size
            rank1 = world.rank // nblocks * nblocks
            rank2 = rank1 + nblocks
            self.blockcomm = self.world.new_communicator(range(rank1, rank2))
            ranks = range(world.rank % nblocks, world.size, nblocks)
            self.kncomm = self.world.new_communicator(ranks)

        if world.rank != 0:
            txt = devnull
        elif isinstance(txt, str):
            txt = open(txt, 'w')
        self.fd = txt

        self.timer = timer or Timer()

        if isinstance(calc, str):
            print('Reading ground state calculation:\n  %s' % calc,
                  file=self.fd)
            if not calc.split('.')[-1] == 'gpw':
                calc = calc + '.gpw'
            self.reader = io.Reader(calc, comm=mpi.serial_comm)
            calc = GPAW(calc,
                        txt=None,
                        communicator=mpi.serial_comm,
                        read_projections=False)
        else:
            self.reader = None
            assert calc.wfs.world.size == 1

        assert calc.wfs.kd.symmetry.symmorphic
        self.calc = calc

        if gate_voltage is not None:
            self.add_gate_voltage(gate_voltage)

        self.spos_ac = calc.atoms.get_scaled_positions()

        self.nocc1 = None  # number of completely filled bands
        self.nocc2 = None  # number of non-empty bands
        self.count_occupied_bands()

        self.vol = abs(np.linalg.det(calc.wfs.gd.cell_cv))

        self.ut_sKnvR = None  # gradient of wave functions for optical limit

        print('Number of blocks:', nblocks, file=self.fd)
Пример #25
0
    def __init__(self,
                 filename=None,
                 timer=None,
                 read_projections=True,
                 **kwargs):
        """ASE-calculator interface.

        The following parameters can be used: nbands, xc, kpts,
        spinpol, gpts, h, charge, symmetry, width, mixer,
        hund, lmax, fixdensity, convergence, txt, parallel,
        communicator, dtype, softgauss and stencils.

        If you don't specify any parameters, you will get:

        Defaults: neutrally charged, LDA, gamma-point calculation, a
        reasonable grid-spacing, zero Kelvin electronic temperature,
        and the number of bands will be equal to the number of atomic
        orbitals present in the setups. Only occupied bands are used
        in the convergence decision. The calculation will be
        spin-polarized if and only if one or more of the atoms have
        non-zero magnetic moments. Text output will be written to
        standard output.

        For a non-gamma point calculation, the electronic temperature
        will be 0.1 eV (energies are extrapolated to zero Kelvin) and
        all symmetries will be used to reduce the number of
        **k**-points."""

        PAWTextOutput.__init__(self)
        self.grid_descriptor_class = GridDescriptor
        self.input_parameters = InputParameters()

        if timer is None:
            self.timer = Timer()
        else:
            self.timer = timer

        self.scf = None
        self.forces = ForceCalculator(self.timer)
        self.stress_vv = None
        self.dipole_v = None
        self.magmom_av = None
        self.wfs = EmptyWaveFunctions()
        self.occupations = None
        self.density = None
        self.hamiltonian = None
        self.atoms = None
        self.iter = 0

        self.initialized = False
        self.nbands_parallelization_adjustment = None  # Somehow avoid this?

        # Possibly read GPAW keyword arguments from file:
        if filename is not None and filename.endswith('.gkw'):
            from gpaw.utilities.kwargs import load
            parameters = load(filename)
            parameters.update(kwargs)
            kwargs = parameters
            filename = None  # XXX

        if filename is not None:
            comm = kwargs.get('communicator', mpi.world)
            reader = gpaw.io.open(filename, 'r', comm)
            self.atoms = gpaw.io.read_atoms(reader)
            par = self.input_parameters
            par.read(reader)

        # _changed_keywords contains those keywords that have been
        # changed by set() since last time initialize() was called.
        self._changed_keywords = set()
        self.set(**kwargs)
        # Here in the beginning, effectively every keyword has been changed.
        self._changed_keywords.update(self.input_parameters)

        if filename is not None:
            # Setups are not saved in the file if the setups were not loaded
            # *from* files in the first place
            if par.setups is None:
                if par.idiotproof:
                    raise RuntimeError('Setups not specified in file. Use '
                                       'idiotproof=False to proceed anyway.')
                else:
                    par.setups = {None: 'paw'}
            if par.basis is None:
                if par.idiotproof:
                    raise RuntimeError('Basis not specified in file. Use '
                                       'idiotproof=False to proceed anyway.')
                else:
                    par.basis = {}

            self.initialize()
            self.read(reader, read_projections)
            if self.hamiltonian.xc.type == 'GLLB':
                self.occupations.calculate(self.wfs)

            self.print_cell_and_parameters()

        self.observers = []