Example #1
0
    def calculate(self, ecut):
        if self.xc != 'RPA':
            if isinstance(ecut, (float, int)):
                self.ecut_max = ecut
            else:
                self.ecut_max = max(ecut)

            if not os.path.isfile('fhxc_%s_%s_%s_0.gpw' %
                                  (self.tag, self.xc, self.ecut_max)):
                kernel = Kernel(self.calc, self.xc, self.ibzq_qc, self.fd,
                                self.unit_cells, self.density_cut,
                                self.ecut_max, self.tag, self.timer)
                kernel.calculate_fhxc()
                del kernel
            else:
                prnt('%s kernel already calculated' % self.xc, file=self.fd)
                prnt(file=self.fd)

        if self.calc.wfs.nspins == 1:
            spin = False
        else:
            spin = True

        e = RPACorrelation.calculate(self, ecut, spin=spin)

        return e
Example #2
0
    def calculate_q(self, chi0, pd, chi0_swGG, chi0_swxvG, chi0_swvv, Q_aGii,
                    m1, m2, cut_G, A2_x):
        if chi0_swxvG is None:
            chi0_swxvG = range(2)  # Not used
            chi0_swvv = range(2)  # Not used
        chi0._calculate(pd, chi0_swGG[0], chi0_swxvG[0], chi0_swvv[0], Q_aGii,
                        m1, m2, [0])
        if len(chi0_swGG) == 2:
            chi0._calculate(pd, chi0_swGG[1], chi0_swxvG[1], chi0_swvv[1],
                            Q_aGii, m1, m2, [1])
        prnt('E_c(q) = ', end='', file=self.fd)

        chi0_swGG = chi0.redistribute(chi0_swGG, A2_x)

        if not pd.kd.gamma:
            e = self.calculate_energy(pd, chi0_swGG, cut_G)
            prnt('%.3f eV' % (e * Hartree), file=self.fd)
            self.fd.flush()
        else:
            e = 0.0
            for v in range(3):
                chi0_swGG[:, :, 0] = chi0_swxvG[:, :, 0, v]
                chi0_swGG[:, :, :, 0] = chi0_swxvG[:, :, 1, v]
                chi0_swGG[:, :, 0, 0] = chi0_swvv[:, :, v, v]
                ev = self.calculate_energy(pd, chi0_swGG, cut_G)
                e += ev
                prnt('%.3f' % (ev * Hartree), end='', file=self.fd)
                if v < 2:
                    prnt('/', end='', file=self.fd)
                else:
                    prnt('eV', file=self.fd)
                    self.fd.flush()
            e /= 3

        return e
Example #3
0
    def calculate(self, ecut):

        if self.xc != 'RPA':
            if isinstance(ecut, (float, int)):
                self.ecut_max = ecut
            else:
                self.ecut_max = max(ecut)

            if not os.path.isfile('fhxc_%s_%s_%s_0.gpw'
                                  % (self.tag, self.xc, self.ecut_max)):
                kernel = Kernel(self.calc, self.xc, self.ibzq_qc,
                                self.fd, self.unit_cells, self.density_cut,
                                self.ecut_max, self.tag)
                kernel.calculate_fhxc()
                del kernel
            else:
                prnt('%s kernel already calculated' % self.xc, file=self.fd)
                prnt(file=self.fd)

        if self.calc.wfs.nspins == 1:
            spin = False
        else:
            spin = True

        e = RPACorrelation.calculate(self, ecut, spin=spin)

        return e
Example #4
0
    def calculate_q(self, chi0, pd,
                    chi0_swGG, chi0_swxvG, chi0_swvv,
                    Q_aGii, m1, m2, cut_G):
        if chi0_swxvG is None:
            chi0_swxvG = range(2)  # Not used
            chi0_swvv = range(2)  # Not used
        chi0._calculate(pd, chi0_swGG[0], chi0_swxvG[0], chi0_swvv[0],
                        Q_aGii, m1, m2, [0])
        if len(chi0_swGG) == 2:
            chi0._calculate(pd, chi0_swGG[1], chi0_swxvG[1], chi0_swvv[1],
                            Q_aGii, m1, m2, [1])
        prnt('E_c(q) = ', end='', file=self.fd)

        if not pd.kd.gamma:
            e = self.calculate_energy(pd, chi0_swGG, cut_G)
            prnt('%.3f eV' % (e * Hartree), file=self.fd)
            self.fd.flush()
        else:
            e = 0.0
            for v in range(3):
                chi0_swGG[:, :, 0] = chi0_swxvG[:, :, 0, v]
                chi0_swGG[:, :, :, 0] = chi0_swxvG[:, :, 1, v]
                chi0_swGG[:, :, 0, 0] = chi0_swvv[:, :, v, v]
                ev = self.calculate_energy(pd, chi0_swGG, cut_G)
                e += ev
		prnt('%.3f' % (ev * Hartree), end='', file=self.fd)
                if v < 2:
                    prnt('/', end='', file=self.fd)
                else:
                    prnt('eV', file=self.fd)
		    self.fd.flush()
            e /= 3

        return e
Example #5
0
    def calculate_fhxc(self):

        prnt('Calculating %s kernel at %d eV cutoff' %
             (self.xc, self.ecut), file=self.fd)
        if self.xc[0] == 'r':
            self.calculate_rkernel()
        else:
            assert self.xc[0] == 'A'
            self.calculate_local_kernel()
Example #6
0
    def calculate_fhxc(self):

        prnt('Calculating %s kernel at %d eV cutoff' % (self.xc, self.ecut),
             file=self.fd)
        if self.xc[0] == 'r':
            self.calculate_rkernel()
        else:
            assert self.xc[0] == 'A'
            self.calculate_local_kernel()
Example #7
0
 def write(self):
     if self.world.rank == 0 and self.filename:
         fd = open(self.filename, 'w')
         prnt('#%9s %10s %10s %8s %12s' %
              ('q1', 'q2', 'q3', 'E_cut', 'E_c(q)'), file=fd)
         for energy_i, q_c in zip(self.energy_qi, self.ibzq_qc):
             for energy, ecut in zip(energy_i, self.ecut_i):
                 prnt('%10.4f %10.4f %10.4f %8d   %r' %
                      (tuple(q_c) + (ecut * Hartree, energy * Hartree)),
                      file=fd)
Example #8
0
    def calculate_local_kernel(self):
        # Standard ALDA exchange kernel
        # Use with care. Results are very difficult to converge
        # Sensitive to density_cut
        ns = self.calc.wfs.nspins
        gd = self.gd
        pd = self.pd
        cell_cv = gd.cell_cv
        icell_cv = 2 * np.pi * np.linalg.inv(cell_cv)
        vol = np.linalg.det(cell_cv)

        fxc_sg = ns * self.get_fxc_g(ns * self.n_g)
        fxc_sg[np.where(self.n_g < self.density_cut)] = 0.0

        r_vg = gd.get_grid_point_coordinates()

        for iq in range(len(self.ibzq_qc)):
            Gvec_Gc = np.dot(pd.get_reciprocal_vectors(q=iq, add_q=False),
                             cell_cv / (2 * np.pi))
            npw = len(Gvec_Gc)
            l_pw_size = -(-npw // mpi.world.size)
            l_pw_range = range(mpi.world.rank * l_pw_size,
                               min((mpi.world.rank + 1) * l_pw_size, npw))
            fhxc_sGsG = np.zeros((ns * npw, ns * npw), dtype=complex)
            for s in range(ns):
                for iG in l_pw_range:
                    for jG in range(npw):
                        fxc = fxc_sg[s].copy()
                        dG_c = Gvec_Gc[iG] - Gvec_Gc[jG]
                        dG_v = np.dot(dG_c, icell_cv)
                        dGr_g = gemmdot(dG_v, r_vg, beta=0.0)
                        ft_fxc = gd.integrate(np.exp(-1j * dGr_g) * fxc)
                        fhxc_sGsG[s * npw + iG, s * npw + jG] = ft_fxc

            mpi.world.sum(fhxc_sGsG)
            fhxc_sGsG /= vol

            Gq2_G = self.pd.G2_qG[iq]
            if (self.ibzq_qc[iq] == 0).all():
                Gq2_G[0] = 1.
            vq_G = 4 * np.pi / Gq2_G
            fhxc_sGsG += np.tile(np.eye(npw) * vq_G, (ns, ns))

            if mpi.rank == 0:
                w = Writer('fhxc_%s_%s_%s_%s.gpw' %
                           (self.tag, self.xc, self.ecut, iq))
                w.dimension('sG', ns * npw)
                w.add('fhxc_sGsG', ('sG', 'sG'), dtype=complex)
                w.fill(fhxc_sGsG)
                w.close()
            mpi.world.barrier()
        prnt(file=self.fd)
Example #9
0
    def calculate_local_kernel(self):
        # Standard ALDA exchange kernel
        # Use with care. Results are very difficult to converge
        # Sensitive to density_cut
        ns = self.calc.wfs.nspins
        gd = self.gd
        pd = self.pd
        cell_cv = gd.cell_cv
        icell_cv = 2 * np.pi * np.linalg.inv(cell_cv)
        vol = np.linalg.det(cell_cv)

        fxc_sg = ns * self.get_fxc_g(ns * self.n_g)
        fxc_sg[np.where(self.n_g < self.density_cut)] = 0.0

        r_vg = gd.get_grid_point_coordinates()

        for iq in range(len(self.ibzq_qc)):
            Gvec_Gc = np.dot(pd.get_reciprocal_vectors(q=iq, add_q=False),
                             cell_cv / (2 * np.pi))
            npw = len(Gvec_Gc)
            l_pw_size = -(-npw // mpi.world.size)
            l_pw_range = range(mpi.world.rank * l_pw_size,
                               min((mpi.world.rank + 1) * l_pw_size, npw))
            fhxc_sGsG = np.zeros((ns * npw, ns * npw), dtype=complex)
            for s in range(ns):
                for iG in l_pw_range:
                    for jG in range(npw):
                        fxc = fxc_sg[s].copy()
                        dG_c = Gvec_Gc[iG] - Gvec_Gc[jG]
                        dG_v = np.dot(dG_c, icell_cv)
                        dGr_g = gemmdot(dG_v, r_vg, beta=0.0)
                        ft_fxc = gd.integrate(np.exp(-1j * dGr_g) * fxc)
                        fhxc_sGsG[s * npw + iG, s * npw + jG] = ft_fxc

            mpi.world.sum(fhxc_sGsG)
            fhxc_sGsG /= vol

            Gq2_G = self.pd.G2_qG[iq]
            if (self.ibzq_qc[iq] == 0).all():
                Gq2_G[0] = 1.
            vq_G = 4 * np.pi / Gq2_G
            fhxc_sGsG += np.tile(np.eye(npw) * vq_G, (ns, ns))

            if mpi.rank == 0:
                w = Writer('fhxc_%s_%s_%s_%s.gpw' %
                           (self.tag, self.xc, self.ecut, iq))
                w.dimension('sG', ns * npw)
                w.add('fhxc_sGsG', ('sG', 'sG'), dtype=complex)
                w.fill(fhxc_sGsG)
                w.close()
            mpi.world.barrier()
        prnt(file=self.fd)
    def __init__(self, lrtddft, index, d=0.001, txt=None,
                 parallel=None, name=None):
        """ExcitedState object.

        parallel: Can be used to parallelize the numerical force calculation
        over images.
        """
        FiniteDifferenceCalculator.__init__(self, lrtddft, d, txt, parallel)

        if type(index) == type(1):
            self.index = UnconstraintIndex(index)
        else:
            self.index = index
        self.name = name

        self.energy = None
        self.F_av = None

        prnt('#', self.index, file=self.txt)
        if name:
            prnt(('name=' + name), file=self.txt)
        prnt('# Force displacement:', self.d, file=self.txt)
        if self.parallel:
            prnt('#', self.parallel['world'].size,
                 'cores in total, ', self.parallel['mycomm'].size,
                 'cores per energy evaluation',
                 file=self.txt)
Example #11
0
    def __init__(self, lrtddft, index, d=0.001, txt=None,
                 parallel=None, name=None):
        """ExcitedState object.

        parallel: Can be used to parallelize the numerical force calculation 
        over images.
        """
        FiniteDifferenceCalculator.__init__(self, lrtddft, d, txt, parallel)

        if type(index) == type(1):
            self.index = UnconstraintIndex(index)
        else:
            self.index = index
        self.name = name

        self.energy = None
        self.F_av = None

        prnt('#', self.index, file=self.txt)
        if name:
            prnt(('name=' + name), file=self.txt)
        prnt('# Force displacement:', self.d, file=self.txt)
        if self.parallel:
            prnt('#', self.parallel['world'].size, 
                 'cores in total, ', self.parallel['mycomm'].size, 
                 'cores per energy evaluation', 
                 file=self.txt)
    def get_forces(self, atoms=None):
        """Get finite-difference forces"""
        if atoms is None:
            atoms = self.atoms

        if self.calculation_required(atoms, ['F_av']):
            atoms.set_calculator(self)

            # do the ground state calculation to set all
            # ranks to the same density to start with
            self.calculator.calculate(atoms)

            world = self.parallel['world']
            txt = self.txt
            if world.rank > 0:
                txt = sys.stdout

            mycomm = self.parallel['mycomm']
            ncalcs = self.parallel['ncalcs']
            icalc = self.parallel['icalc']
            F_av = np.zeros((len(atoms), 3))
            i = 0
            for ia, a in enumerate(self.atoms):
                for ic in range(3):
# print "ncalcs", ncalcs, "i", i, "icalc",icalc
                    if (i % ncalcs) == icalc:
                        F_av[ia, ic] = numeric_force(
                            atoms, ia, ic, self.d) / mycomm.size
                        prnt('# rank', world.rank, '-> force',
                             (str(ia) + 'xyz'[ic]), file=txt)
                    i += 1
            energy = np.array([0.])  # array needed for world.sum()
            if (i % ncalcs) == icalc:
                self.energy = None
                energy[0] = self.get_potential_energy(atoms) / mycomm.size
                prnt('# rank', world.rank, '-> energy',
                     energy[0] * mycomm.size, file=txt)
            self.set_positions(atoms)
            world.sum(F_av)
            world.sum(energy)
            self.energy = energy[0]
            self.F_av = F_av

            if self.txt:
                prnt('Excited state forces in eV/Ang:', file=self.txt)
                symbols = self.atoms.get_chemical_symbols()
                for a, symbol in enumerate(symbols):
                    prnt(('%3d %-2s %10.5f %10.5f %10.5f' %
                          ((a, symbol) + tuple(self.F_av[a]))),
                         file=self.txt)
        return self.F_av
Example #13
0
    def read(self):
        lines = open(self.filename).readlines()[1:]
        n = 0
        self.energy_qi = []
        nq = len(lines) // len(self.ecut_i)
        for q_c in self.ibzq_qc[:nq]:
            self.energy_qi.append([])
            for ecut in self.ecut_i:
                q1, q2, q3, ec, energy = [float(x)
                                          for x in lines[n].split()]
                self.energy_qi[-1].append(energy / Hartree)
                n += 1

                if (abs(q_c - (q1, q2, q3)).max() > 1e-4 or
                                   abs(int(ecut * Hartree) - ec) > 0):
                    self.energy_qi = []
                    return
                    
        prnt('Read %d q-points from file: %s' % (nq, self.filename),
             file=self.fd)
        prnt(file=self.fd)
Example #14
0
    def __init__(self, cell_cv, nk_c, txt=sys.stdout):
        self.nk_c = nk_c
        bigcell_cv = cell_cv * nk_c[:, np.newaxis]
        L_c = (np.linalg.inv(bigcell_cv)**2).sum(0)**-0.5

        rc = 0.5 * L_c.min()
        prnt('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' %
             (tuple(nk_c) + (rc * Bohr, )),
             file=txt)

        self.a = 5 / rc
        prnt('Range-separation parameter: %.3f Ang^-1' % (self.a / Bohr),
             file=txt)

        #        nr_c = [get_efficient_fft_size(2 * int(L * self.a * 1.5))
        nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0)) for L in L_c]
        prnt('FFT size for calculating truncated Coulomb: %dx%dx%d' %
             tuple(nr_c),
             file=txt)

        self.gd = GridDescriptor(nr_c, bigcell_cv, comm=mpi.serial_comm)
        v_R = self.gd.empty()
        v_i = v_R.ravel()

        pos_iv = self.gd.get_grid_point_coordinates().reshape((3, -1)).T
        corner_jv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv)
        for i, pos_v in enumerate(pos_iv):
            r = ((pos_v - corner_jv)**2).sum(axis=1).min()**0.5
            if r == 0:
                v_i[i] = 2 * self.a / pi**0.5
            else:
                v_i[i] = erf(self.a * r) / r

        self.K_Q = np.fft.fftn(v_R) * self.gd.dv
Example #15
0
    def get_forces(self, atoms=None):
        """Get finite-difference forces"""
        if atoms is None:
            atoms = self.atoms

        if self.calculation_required(atoms, ['F_av']):
            atoms.set_calculator(self)

            # do the ground state calculation to set all
            # ranks to the same density to start with
            self.calculator.calculate(atoms)

            world = self.parallel['world']
            txt = self.txt
            if world.rank > 0:
                txt = sys.stdout

            mycomm = self.parallel['mycomm']
            ncalcs = self.parallel['ncalcs']
            icalc = self.parallel['icalc']
            F_av = np.zeros((len(atoms), 3))
            i = 0
            for ia, a in enumerate(self.atoms):
                for ic in range(3):
                    if (i % ncalcs) == icalc:
                        F_av[ia, ic] = numeric_force(
                            atoms, ia, ic, self.d) / mycomm.size
                        prnt('# rank', world.rank, '-> force',
                             (str(ia) + 'xyz'[ic]), file=txt)
                    i += 1
            energy = np.array([0.]) # array needed for world.sum()
            if (i % ncalcs) == icalc:
                self.energy = None
                energy[0] = self.get_potential_energy(atoms) / mycomm.size
                prnt('# rank', world.rank, '-> energy', 
                     energy[0] * mycomm.size, file=txt)
            self.set_positions(atoms)
            world.sum(F_av)
            world.sum(energy)
            self.energy = energy[0]
            self.F_av = F_av

            if self.txt:
                prnt('Excited state forces in eV/Ang:', file=self.txt)
                symbols = self.atoms.get_chemical_symbols()
                for a, symbol in enumerate(symbols):
                    prnt(('%3d %-2s %10.5f %10.5f %10.5f' %
                          ((a, symbol) + tuple(self.F_av[a]))), 
                         file=self.txt)
        return self.F_av
Example #16
0
    def __init__(self, cell_cv, nk_c, txt=sys.stdout):
        self.nk_c = nk_c
        bigcell_cv = cell_cv * nk_c[:, np.newaxis]
        L_c = (np.linalg.inv(bigcell_cv)**2).sum(0)**-0.5
        
        rc = 0.5 * L_c.min()
        prnt('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' %
             (tuple(nk_c) + (rc * Bohr,)), file=txt)
        
        self.a = 5 / rc
        prnt('Range-separation parameter: %.3f Ang^-1' % (self.a / Bohr),
             file=txt)
        
#        nr_c = [get_efficient_fft_size(2 * int(L * self.a * 1.5))
        nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0))
                for L in L_c]
        prnt('FFT size for calculating truncated Coulomb: %dx%dx%d' %
             tuple(nr_c), file=txt)
        
        self.gd = GridDescriptor(nr_c, bigcell_cv, comm=mpi.serial_comm)
        v_R = self.gd.empty()
        v_i = v_R.ravel()
        
        pos_iv = self.gd.get_grid_point_coordinates().reshape((3, -1)).T
        corner_jv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv)
        for i, pos_v in enumerate(pos_iv):
            r = ((pos_v - corner_jv)**2).sum(axis=1).min()**0.5
            if r == 0:
                v_i[i] = 2 * self.a / pi**0.5
            else:
                v_i[i] = erf(self.a * r) / r
                
        self.K_Q = np.fft.fftn(v_R) * self.gd.dv
Example #17
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, firsttime = initialize_text_stream(
                    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)
    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)
Example #19
0
    def calculate_q(self, chi0, pd,
                    chi0_wGG, chi0_wxvG, Q_aGii, m1, m2, cut_G):
        chi0._calculate(pd, chi0_wGG, chi0_wxvG, Q_aGii, m1, m2)
        prnt('E_c(q) = ', end='', file=self.fd)

        if not pd.kd.gamma:
            e = self.calculate_energy(pd, chi0_wGG, cut_G)
            prnt('%.3f eV' % (e * Hartree), flush=True, file=self.fd)
        else:
            e = 0.0
            for v in range(3):
                chi0_wGG[:, 0] = chi0_wxvG[:, 0, v]
                chi0_wGG[:, :, 0] = chi0_wxvG[:, 1, v]
                ev = self.calculate_energy(pd, chi0_wGG, cut_G)
                e += ev
                prnt('%.3f' % (ev * Hartree), end='', file=self.fd)
                if v < 2:
                    prnt('/', end='', file=self.fd)
                else:
                    prnt(' eV', flush=True, file=self.fd)
            e /= 3

        return e
Example #20
0
    def calculate(self):
        kd = self.calc.wfs.kd
        nspins = self.calc.wfs.nspins
        
        for s in range(nspins):
            for i, k1 in enumerate(self.kpts):
                K1 = kd.ibz2bz_k[k1]
                kpt1 = self.get_k_point(s, K1, *self.bands)
                self.f_sin[s, i] = kpt1.f_n
                for kpt2 in self.mykpts:
                    if kpt2.s == s:
                        self.calculate_q(i, kpt1, kpt2)
                
                self.calculate_paw_exx_corrections(i, kpt1)

        self.world.sum(self.exxvv_sin)
        
        # Calculate total energy if we have everything needed:
        if (len(self.kpts) == kd.nibzkpts and
            self.bands[0] == 0 and
            self.bands[1] >= self.nocc2):
            exxvv_i = (self.exxvv_sin * self.f_sin).sum(axis=2).sum(axis=0)
            exxvc_i = 2 * (self.exxvc_sin * self.f_sin).sum(axis=2).sum(axis=0)
            self.exxvv = np.dot(kd.weight_k[self.kpts], exxvv_i) / nspins
            self.exxvc = np.dot(kd.weight_k[self.kpts], exxvc_i) / nspins
            self.exx = self.exxvv + self.exxvc + self.exxcc
            prnt('Exact exchange energy:', file=self.fd)
            for kind, exx in [('valence-valence', self.exxvv),
                              ('valence-core', self.exxvc),
                              ('core-core', self.exxcc),
                              ('total', self.exx)]:
                prnt('%16s%11.3f eV' % (kind + ':', exx * Hartree),
                     file=self.fd)
            
            self.exc = self.calculate_hybrid_correction()

        exx_sin = self.exxvv_sin + self.exxvc_sin
        prnt('EXX eigenvalue contributions in eV:', file=self.fd)
        prnt(np.array_str(exx_sin * Hartree, precision=3), file=self.fd)
Example #21
0
    def extrapolate(self, e_i):
        prnt('Extrapolated energies:', file=self.fd)
        ex_i = []
        for i in range(len(e_i) - 1):
            e1, e2 = e_i[i:i + 2]
            x1, x2 = self.ecut_i[i:i + 2]**-1.5
            ex = (e1 * x2 - e2 * x1) / (x2 - x1)
            ex_i.append(ex)

            prnt('  %4.0f -%4.0f:  %5.3f eV' % (self.ecut_i[i] * Hartree,
                                                self.ecut_i[i + 1] * Hartree,
                                                ex * Hartree),
                 file=self.fd, flush=True)
        prnt(file=self.fd)

        return e_i * Hartree
Example #22
0
    def calculate(self):
        kd = self.calc.wfs.kd
        nspins = self.calc.wfs.nspins

        for s in range(nspins):
            for i, k1 in enumerate(self.kpts):
                K1 = kd.ibz2bz_k[k1]
                kpt1 = self.get_k_point(s, K1, *self.bands)
                self.f_sin[s, i] = kpt1.f_n
                for kpt2 in self.mykpts:
                    if kpt2.s == s:
                        self.calculate_q(i, kpt1, kpt2)

                self.calculate_paw_exx_corrections(i, kpt1)

        self.world.sum(self.exxvv_sin)

        # Calculate total energy if we have everything needed:
        if (len(self.kpts) == kd.nibzkpts and self.bands[0] == 0
                and self.bands[1] >= self.nocc2):
            exxvv_i = (self.exxvv_sin * self.f_sin).sum(axis=2).sum(axis=0)
            exxvc_i = 2 * (self.exxvc_sin * self.f_sin).sum(axis=2).sum(axis=0)
            self.exxvv = np.dot(kd.weight_k[self.kpts], exxvv_i) / nspins
            self.exxvc = np.dot(kd.weight_k[self.kpts], exxvc_i) / nspins
            self.exx = self.exxvv + self.exxvc + self.exxcc
            prnt('Exact exchange energy:', file=self.fd)
            for kind, exx in [('valence-valence', self.exxvv),
                              ('valence-core', self.exxvc),
                              ('core-core', self.exxcc), ('total', self.exx)]:
                prnt('%16s%11.3f eV' % (kind + ':', exx * Hartree),
                     file=self.fd)

            self.exc = self.calculate_hybrid_correction()

        exx_sin = self.exxvv_sin + self.exxvc_sin
        prnt('EXX eigenvalue contributions in eV:', file=self.fd)
        prnt(np.array_str(exx_sin * Hartree, precision=3), file=self.fd)
Example #23
0
 def log(self, *args, **kwargs):
     prnt(file=self.fd, *args, **kwargs)
     self.fd.flush()
        try:
            ea = data[name].get('dissociation energy', np.nan) * kcal / mol
            dist = molecule(name, data=data).get_distance(0, 1)
            freq = data[name].get('harmonic frequency', np.nan)
            t = np.nan
        except KeyError:
            ea = np.nan
            dist = np.nan
            freq = np.nan
            t = np.nan
        A.append((ea, dist, freq, t))
    return np.array(A).T


E0, D0, F0, T0 = analyse()
try:
    E1, D1, F1, T1 = analyse()
except KeyError:
    E1 = E0
    D1 = D0
    F1 = F0
    T1 = T0

fd = open('%s.csv' % db, 'w')
prnt('# Atomization energies (E), distances (d), frequencies (f) and time (t): %s' % db, file=fd)
prnt('# name (N), E(N; not relaxed), E(N), d(N), F(N; not relaxed), F(N),  t(N; not relaxed) [sec]', file=fd)
for name, e0, e1, d1, f0, f1, t0, in zip(molecule_names,
                                 E0, E1, D1, F0, F1, T0):
    prnt('%11s, %7.3f, %7.3f, %7.3f, %7.1f, %7.1f, %7.1f' %
         (name, e0, e1, d1, f0, f1, t0), file=fd)
Example #25
0
    def __init__(self,
                 calc,
                 xc=None,
                 kpts=None,
                 bands=None,
                 ecut=None,
                 omega=None,
                 world=mpi.world,
                 txt=sys.stdout,
                 timer=None):

        PairDensity.__init__(self,
                             calc,
                             ecut,
                             world=world,
                             txt=txt,
                             timer=timer)

        if xc is None or xc == 'EXX':
            self.exx_fraction = 1.0
            xc = XC(XCNull())
        elif xc == 'PBE0':
            self.exx_fraction = 0.25
            xc = XC('HYB_GGA_XC_PBEH')
        elif xc == 'HSE03':
            omega = 0.106
            self.exx_fraction = 0.25
            xc = XC('HYB_GGA_XC_HSE03')
        elif xc == 'HSE06':
            omega = 0.11
            self.exx_fraction = 0.25
            xc = XC('HYB_GGA_XC_HSE06')
        elif xc == 'B3LYP':
            self.exx_fraction = 0.2
            xc = XC('HYB_GGA_XC_B3LYP')

        self.xc = xc
        self.omega = omega
        self.exc = np.nan  # density dependent part of xc-energy

        self.kpts = select_kpts(kpts, self.calc)

        if bands is None:
            # Do all occupied bands:
            bands = [0, self.nocc2]

        prnt('Calculating exact exchange contributions for band index',
             '%d-%d' % (bands[0], bands[1] - 1),
             file=self.fd)
        prnt('for IBZ k-points with indices:',
             ', '.join(str(i) for i in self.kpts),
             file=self.fd)

        self.bands = bands

        if self.ecut is None:
            self.ecut = self.calc.wfs.pd.ecut
        prnt('Plane-wave cutoff: %.3f eV' % (self.ecut * Hartree),
             file=self.fd)

        shape = (self.calc.wfs.nspins, len(self.kpts), bands[1] - bands[0])
        self.exxvv_sin = np.zeros(shape)  # valence-valence exchange energies
        self.exxvc_sin = np.zeros(shape)  # valence-core exchange energies
        self.f_sin = np.empty(shape)  # occupation numbers

        # The total EXX energy will not be calculated if we are only
        # interested in a few eigenvalues for a few k-points
        self.exx = np.nan  # total EXX energy
        self.exxvv = np.nan  # valence-valence
        self.exxvc = np.nan  # valence-core
        self.exxcc = 0.0  # core-core

        self.mysKn1n2 = None  # my (s, K, n1, n2) indices
        self.distribute_k_points_and_bands(0, self.nocc2)

        # All occupied states:
        self.mykpts = [
            self.get_k_point(s, K, n1, n2) for s, K, n1, n2 in self.mysKn1n2
        ]

        prnt('Using Wigner-Seitz truncated coulomb interaction.', file=self.fd)
        self.wstc = WignerSeitzTruncatedCoulomb(self.calc.wfs.gd.cell_cv,
                                                self.calc.wfs.kd.N_c, self.fd)
        self.iG_qG = {}  # cache

        # PAW matrices:
        self.V_asii = []  # valence-valence correction
        self.C_aii = []  # valence-core correction
        self.initialize_paw_exx_corrections()
collection = Collection()

if len(sys.argv) == 1:
    category = 'fcc'
    collection = Collection()
    names = collection.names
elif len(sys.argv) == 2:
    category = sys.argv[1]
    collection = Collection(category=category) 
    names = collection.names
else:
    category = sys.argv[1]
    collection = Collection(category=category) 
    names = [sys.argv[2]]

fd = open('doi_' + category + '_raw.csv', 'w')

for name in names:
    e = 0.0
    e0 = 0.0
    b0 = 0.0
    b1 = 0.0
    if name in ['N', 'Hg']:
        e = np.nan
    # number of unit formulas per cell
    nufpc = len(collection[name]) / len(string2symbols(name))
    v = collection[name].get_volume()
    v = v / nufpc
    if not np.isnan(e):
        prnt('%s, %7.3f, %8.4f, %8.4f, %8.4f, %8.4f' % (name, e, e0, v, b0, b1), file=fd)
Example #27
0
 def log(self, *args, **kwargs):
     prnt(file=self.logfile, *args, **kwargs)
Example #28
0
File: task.py Project: PHOTOX/fuase
 def log(self, *args, **kwargs):
     prnt(file=self.logfile, *args, **kwargs)
                    print 'bq', d.name
                    ea = ea + d.energy
                else:
                    print 'molecule', d.name
                    ea = - d.energy
                dist = ((d.positions[0] - d.positions[-1])**2).sum()**0.5
                t = d.time
            except (KeyError, ValueError):
                ea = np.nan
                dist = np.nan
                t = np.nan
        A.append((ea, dist, t))
    return np.array(A).T


E0, D0, T0 = analyse(calc, 0)
try:
    E1, D1, T1 = analyse(calc, 1)
except KeyError:
    E1 = E0
    D1 = D0
    T1 = T0

fd = open('%s.csv' % db, 'w')
prnt('# Atomization energies (E), distances (d) and time (t): %s %s' % (calc, db), file=fd)
prnt('# name (N), E(N; not relaxed), E(N), d(N), t(N; not relaxed) [sec]', file=fd)
for name, e0, e1, d1, t0, in zip(molecule_names,
                                 E0, E1, D1, T0):
    prnt('%21s, %7.3f, %7.3f, %7.3f, %7.1f' %
         (name, e0, e1, d1, t0), file=fd)
Example #30
0
    def calculate_rkernel(self):

        gd = self.gd
        ng_c = gd.N_c
        cell_cv = gd.cell_cv
        icell_cv = 2 * np.pi * np.linalg.inv(cell_cv)
        vol = np.linalg.det(cell_cv)

        ns = self.calc.wfs.nspins
        n_g = self.n_g  # density on rough grid

        fx_g = ns * self.get_fxc_g(n_g)  # local exchange kernel
        qc_g = (-4 * np.pi * ns / fx_g)**0.5  # cutoff functional
        flocal_g = qc_g**3 * fx_g / (6 * np.pi**2)  # ren. x-kernel for r=r'
        Vlocal_g = 2 * qc_g / np.pi  # ren. Hartree kernel for r=r'

        ng = np.prod(ng_c)  # number of grid points
        r_vg = gd.get_grid_point_coordinates()
        rx_g = r_vg[0].flatten()
        ry_g = r_vg[1].flatten()
        rz_g = r_vg[2].flatten()

        prnt('    %d grid points and %d plane waves at the Gamma point' %
             (ng, self.pd.ngmax),
             file=self.fd)

        # Unit cells
        R_Rv = []
        weight_R = []
        nR_v = self.unit_cells
        nR = np.prod(nR_v)
        for i in range(-nR_v[0] + 1, nR_v[0]):
            for j in range(-nR_v[1] + 1, nR_v[1]):
                for h in range(-nR_v[2] + 1, nR_v[2]):
                    R_Rv.append(i * cell_cv[0] + j * cell_cv[1] +
                                h * cell_cv[2])
                    weight_R.append((nR_v[0] - abs(i)) * (nR_v[1] - abs(j)) *
                                    (nR_v[2] - abs(h)) / float(nR))
        if nR > 1:
            # with more than one unit cell only the exchange kernel is
            # calculated on the grid. The bare Coulomb kernel is added
            # in PW basis and Vlocal_g only the exchange part
            dv = self.calc.density.gd.dv
            gc = (3 * dv / 4 / np.pi)**(1 / 3.)
            Vlocal_g -= 2 * np.pi * gc**2 / dv
            prnt('    Lattice point sampling: ' + '(%s x %s x %s)^2 ' %
                 (nR_v[0], nR_v[1], nR_v[2]) +
                 ' Reduced to %s lattice points' % len(R_Rv),
                 file=self.fd)

        l_g_size = -(-ng // mpi.world.size)
        l_g_range = range(mpi.world.rank * l_g_size,
                          min((mpi.world.rank + 1) * l_g_size, ng))

        fhxc_qsGr = {}
        for iq in range(len(self.ibzq_qc)):
            fhxc_qsGr[iq] = np.zeros(
                (ns, len(self.pd.G2_qG[iq]), len(l_g_range)), dtype=complex)

        inv_error = np.seterr()
        np.seterr(invalid='ignore')
        np.seterr(divide='ignore')

        t0 = time()
        # Loop over Lattice points
        for i, R_v in enumerate(R_Rv):
            # Loop over r'. f_rr and V_rr are functions of r (dim. as r_vg[0])
            if i == 1:
                prnt('      Finished 1 cell in %s seconds' % int(time() - t0) +
                     ' - estimated %s seconds left' % int(
                         (len(R_Rv) - 1) * (time() - t0)),
                     file=self.fd)
                self.fd.flush()
            if len(R_Rv) > 5:
                if (i + 1) % (len(R_Rv) / 5 + 1) == 0:
                    prnt('      Finished %s cells in %s seconds' %
                         (i, int(time() - t0)) +
                         ' - estimated %s seconds left' % int(
                             (len(R_Rv) - i) * (time() - t0) / i),
                         file=self.fd)
                    self.fd.flush()
            for g in l_g_range:
                rx = rx_g[g] + R_v[0]
                ry = ry_g[g] + R_v[1]
                rz = rz_g[g] + R_v[2]

                # |r-r'-R_i|
                rr = ((r_vg[0] - rx)**2 + (r_vg[1] - ry)**2 +
                      (r_vg[2] - rz)**2)**0.5

                n_av = (n_g + n_g.flatten()[g]) / 2.
                fx_g = ns * self.get_fxc_g(n_av, index=g)
                qc_g = (-4 * np.pi * ns / fx_g)**0.5
                x = qc_g * rr
                osc_x = np.sin(x) - x * np.cos(x)
                f_rr = fx_g * osc_x / (2 * np.pi**2 * rr**3)
                if nR > 1:  # include only exchange part of the kernel here
                    V_rr = (sici(x)[0] * 2 / np.pi - 1) / rr
                else:  # include the full kernel (also hartree part)
                    V_rr = (sici(x)[0] * 2 / np.pi) / rr

                # Terms with r = r'
                if (np.abs(R_v) < 0.001).all():
                    tmp_flat = f_rr.flatten()
                    tmp_flat[g] = flocal_g.flatten()[g]
                    f_rr = tmp_flat.reshape(ng_c)
                    tmp_flat = V_rr.flatten()
                    tmp_flat[g] = Vlocal_g.flatten()[g]
                    V_rr = tmp_flat.reshape(ng_c)
                    del tmp_flat

                f_rr[np.where(n_av < self.density_cut)] = 0.0
                V_rr[np.where(n_av < self.density_cut)] = 0.0

                f_rr *= weight_R[i]
                V_rr *= weight_R[i]

                # r-r'-R_i
                r_r = np.array([r_vg[0] - rx, r_vg[1] - ry, r_vg[2] - rz])

                # Fourier transform of r
                for iq, q in enumerate(self.ibzq_qc):
                    q_v = np.dot(q, icell_cv)
                    e_q = np.exp(-1j * gemmdot(q_v, r_r, beta=0.0))
                    f_q = self.pd.fft((f_rr + V_rr) * e_q, iq) * vol / ng
                    fhxc_qsGr[iq][0, :, g - l_g_range[0]] += f_q
                    if ns == 2:
                        f_q = self.pd.fft(V_rr * e_q, iq) * vol / ng
                        fhxc_qsGr[iq][1, :, g - l_g_range[0]] += f_q

        mpi.world.barrier()

        np.seterr(**inv_error)

        for iq, q in enumerate(self.ibzq_qc):
            npw = len(self.pd.G2_qG[iq])
            fhxc_sGsG = np.zeros((ns * npw, ns * npw), complex)
            l_pw_size = -(-npw // mpi.world.size)  # parallelize over PW below
            l_pw_range = range(mpi.world.rank * l_pw_size,
                               min((mpi.world.rank + 1) * l_pw_size, npw))

            if mpi.world.size > 1:
                # redistribute grid and plane waves in fhxc_qsGr[iq]
                bg1 = BlacsGrid(mpi.world, 1, mpi.world.size)
                bg2 = BlacsGrid(mpi.world, mpi.world.size, 1)
                bd1 = bg1.new_descriptor(npw, ng, npw, -(-ng / mpi.world.size))
                bd2 = bg2.new_descriptor(npw, ng, -(-npw / mpi.world.size), ng)

                fhxc_Glr = np.zeros((len(l_pw_range), ng), dtype=complex)
                if ns == 2:
                    Koff_Glr = np.zeros((len(l_pw_range), ng), dtype=complex)

                r = Redistributor(bg1.comm, bd1, bd2)
                r.redistribute(fhxc_qsGr[iq][0], fhxc_Glr, npw, ng)
                if ns == 2:
                    r.redistribute(fhxc_qsGr[iq][1], Koff_Glr, npw, ng)
            else:
                fhxc_Glr = fhxc_qsGr[iq][0]
                if ns == 2:
                    Koff_Glr = fhxc_qsGr[iq][1]

            # Fourier transform of r'
            for iG in range(len(l_pw_range)):
                f_g = fhxc_Glr[iG].reshape(ng_c)
                f_G = self.pd.fft(f_g.conj(), iq) * vol / ng
                fhxc_sGsG[l_pw_range[0] + iG, :npw] = f_G.conj()
                if ns == 2:
                    v_g = Koff_Glr[iG].reshape(ng_c)
                    v_G = self.pd.fft(v_g.conj(), iq) * vol / ng
                    fhxc_sGsG[npw + l_pw_range[0] + iG, :npw] = v_G.conj()

            if ns == 2:  # f_00 = f_11 and f_01 = f_10
                fhxc_sGsG[:npw, npw:] = fhxc_sGsG[npw:, :npw]
                fhxc_sGsG[npw:, npw:] = fhxc_sGsG[:npw, :npw]

            mpi.world.sum(fhxc_sGsG)
            fhxc_sGsG /= vol

            if mpi.rank == 0:
                w = Writer('fhxc_%s_%s_%s_%s.gpw' %
                           (self.tag, self.xc, self.ecut, iq))
                w.dimension('sG', ns * npw)
                w.add('fhxc_sGsG', ('sG', 'sG'), dtype=complex)
                if nR > 1:  # add Hartree kernel evaluated in PW basis
                    Gq2_G = self.pd.G2_qG[iq]
                    if (q == 0).all():
                        Gq2_G[0] = 1.
                    vq_G = 4 * np.pi / Gq2_G
                    fhxc_sGsG += np.tile(np.eye(npw) * vq_G, (ns, ns))
                w.fill(fhxc_sGsG)
                w.close()
            mpi.world.barrier()
        prnt(file=self.fd)
Example #31
0
    def update(self, atoms=None, properties=['energy', 'forces']):
        if not self.calculation_required(atoms, properties):
            return

        if atoms is None:
            atoms = self.calculator.get_atoms()
        self.results['energy'] = self.calculator.get_potential_energy(atoms)
        self.results['forces'] = self.calculator.get_forces(atoms)
        self.atoms = atoms.copy()

        if self.vdwradii is not None:
            # external vdW radii
            vdwradii = self.vdwradii
            assert(len(atoms) == len(vdwradii))
        else:
            vdwradii = []
            for atom in atoms:
                self.vdwradii.append(vdWDB_Grimme06jcc[atom.symbol][1])
 
        if self.hirshfeld == None:
            volume_ratios = [1.] * len(atoms)
        elif hasattr(self.hirshfeld,'__len__'): # a list
            assert(len(atoms) == len(self.hirshfeld))
            volume_ratios = self.hirshfeld
        else: # should be an object
            self.hirshfeld.initialize()
            volume_ratios = self.hirshfeld.get_effective_volume_ratios()

        # correction for effective C6
        na = len(atoms)
        C6eff_a = np.empty((na))
        alpha_a = np.empty((na))
        R0eff_a = np.empty((na))
        for a, atom in enumerate(atoms):
            # free atom values
            alpha_a[a], C6eff_a[a] = self.vdWDB_alphaC6[atom.symbol]
            # correction for effective C6
            C6eff_a[a] *= Hartree * volume_ratios[a]**2 * Bohr**6
            R0eff_a[a] = vdwradii[a] * volume_ratios[a]**(1./3.)
        C6eff_aa = np.empty((na, na))
        for a in range(na):
            for b in range(a, na):
                C6eff_aa[a, b] = (2 * C6eff_a[a] * C6eff_a[b] /
                                  (alpha_a[b] / alpha_a[a] * C6eff_a[a] +
                                   alpha_a[a] / alpha_a[b] * C6eff_a[b]   ))
                C6eff_aa[b, a] = C6eff_aa[a, b]

        # PBC
        pbc_c = atoms.get_pbc()
        cell_c = atoms.get_cell()
        Rcell_c = np.sqrt(np.sum(cell_c**2, axis=1))
        ncells_c = np.ceil(np.where(pbc_c, 1. + self.Rmax / Rcell_c, 1))
        ncells_c = np.array(ncells_c, dtype=int)

        positions = atoms.get_positions()
        EvdW = 0.0
        forces = 0. * self.results['forces']
        # loop over all atoms in the cell
        for ia, posa in enumerate(positions):
            # loop over all atoms in the cell (and neighbour cells for PBC)
            for ib, posb in enumerate(positions):
                # loops over neighbour cells
                for ix in range(-ncells_c[0] + 1, ncells_c[0]):
                    for iy in range(-ncells_c[1] + 1, ncells_c[1]):
                        for iz in range(-ncells_c[2] + 1, ncells_c[2]):
                            i_c = np.array([ix, iy, iz])
                            diff = posb + np.dot(i_c, cell_c) - posa
                            r2 = np.dot(diff, diff)
                            r6 = r2**3
                            r = np.sqrt(r2)
                            if r > 1.e-10 and r < self.Rmax:
                                Edamp, Fdamp = self.damping(r, 
                                                            R0eff_a[ia],
                                                            R0eff_a[ib],
                                                            d=self.d, 
                                                            sR=self.sR)
                                EvdW -= (Edamp *
                                         C6eff_aa[ia, ib] / r6 )
                                # we neglect the C6eff contribution to the
                                # forces
                                forces[ia] -= ((Fdamp - 6 * Edamp / r) *
                                               C6eff_aa[ia, ib] / r6 *
                                               diff / r                 )
        self.results['energy'] += EvdW / 2. # double counting
        self.results['forces'] += forces / 2. # double counting

        if self.txt:
            prnt(('\n' + self.__class__.__name__), file=self.txt)
            prnt('vdW correction: %g' % (EvdW / 2.), file=self.txt)
            prnt('Energy:         %g' % self.results['energy'], 
                 file=self.txt)
            prnt('\nForces in eV/Ang:', file=self.txt)
            c = Hartree / Bohr
            symbols = self.atoms.get_chemical_symbols()
            for ia, symbol in enumerate(symbols):
                prnt('%3d %-2s %10.5f %10.5f %10.5f' %
                     ((ia, symbol) + tuple(self.results['forces'][ia])), 
                     file=self.txt)
Example #32
0
        A.append((ea, dist))
    return np.array(A).T


En0, Dn0 = analyse('nwchem', 0)
En1, Dn1 = analyse('nwchem', 1)
Eg0, Dg0 = analyse('gpaw', 0)
Eg1, Dg1 = analyse('gpaw', 1)

print(abs(Eg0 - En0).max(), abs(Eg0 - En0).mean())
print(abs(Eg1 - En1).max(), abs(Eg1 - En1).mean())
print(abs(Dg0 - Dn0).max(), abs(Dg0 - Dn0).mean())
print(abs(Dg1 - Dn1).max(), abs(Dg1 - Dn1).mean())

fd = open('g2-1.csv', 'w')
prnt('# Atomization energies and distances.  N: NWChem, G: GPAW', file=fd)
prnt('# name, E(N, not relaxed), E(N), E(G)-E(N), d(N), d(G)-d(N)', file=fd)
for name, en0, en1, eg1, dn1, dg1 in zip(molecule_names,
                                         En0, En1, Eg1, Dn1, Dg1):
    prnt('%11s, %7.3f, %7.3f, %7.3f, %7.3f, %7.3f' %
         (name, en0, en1, eg1 - en1, dn1, dg1 - dn1), file=fd)
    

# these results are calculated at relaxed geometries
ref = {'distance': {'NH3': 1.0212028325017757, 'S2': 1.909226444930773, 'SiH2_s3B1d': 1.4959758117701643, 'CH3OH': 1.103031397032791, 'SiH4': 1.492599477296688, 'Si2H6': 3.1894770187147787, 'PH3': 1.4301222209112225, 'PH2': 1.4346717268375369, 'HF': 0.93024767766719751, 'O2': 1.2177518292845226, 'SiH3': 1.4944876788686847, 'NH': 1.0495566124276352, 'SH2': 1.3513837051001727, 'ClO': 1.5787435668567111, 'H2O2': 1.8958330716525236, 'NO': 1.156790619328925, 'ClF': 1.6500936428996131, 'LiH': 1.6056281159928836, 'HCO': 1.134630847589132, 'CH3': 1.0857934634048991, 'CH4': 1.0954690924956099, 'Cl2': 2.0044430187644329, 'HOCl': 1.7084164068894601, 'SiH2_s1A1d': 1.5369100463950582, 'SiO': 1.5267775155499548, 'F2': 1.4131037387967056, 'P2': 1.9038007151393095, 'Si2': 2.2844499935377716, 'CH': 1.135943649633214, 'CO': 1.1353228578574415, 'CN': 1.1734204501040257, 'LiF': 1.5781425105489659, 'Na2': 3.0849004417809258, 'SO2': 1.4536010904565573, 'NaCl': 2.375956045377166, 'Li2': 2.7269446448266184, 'NH2': 1.0360313462587714, 'CS': 1.5453598419904586, 'C2H6': 2.1839921464514007, 'N2': 1.1020010395108386, 'C2H4': 2.1196102605939493, 'HCN': 1.074902699795437, 'C2H2': 1.0701025663671189, 'CH2_s3B1d': 1.0846126602770281, 'CH3Cl': 1.0934062531916822, 'BeH': 1.3549994786114516, 'CO2': 1.1705025664593323, 'CH3SH': 1.0951914666413829, 'OH': 0.98302300558682143, 'N2H4': 1.9949378750277829, 'H2O': 0.9689957468077689, 'SO': 1.5015729306543228, 'CH2_s1A1d': 1.1216809054426011, 'H2CO': 2.0340405586023551, 'HCl': 1.2882940110553078}, 'energy': {'NH3': -1537.8943922528292, 'S2': -21662.654140653412, 'SiH2_s3B1d': -7903.3690892881705, 'Li': -203.05091256761085, 'CH3OH': -3146.7647944133632, 'SiH4': -7938.4648222008409, 'Si2H6': -15845.082177930506, 'PH3': -9333.4084018049416, 'PH2': -9316.1298787915111, 'HF': -2732.0742553639361, 'O2': -4088.7283614591165, 'SiH3': -7920.9111544133084, 'NH': -1501.4257523508722, 'Be': -398.09853859103947, 'SH2': -10863.938964816221, 'ClO': -14561.296690949923, 'H2O2': -4121.946252450156, 'NO': -3532.6917094247037, 'ClF': -15231.961288082202, 'LiH': -218.97262833348015, 'HCO': -3096.2005211539013, 'CH3': -1082.8017329696315, 'CH4': -1101.1776994482279, 'Cl2': -25035.886547435726, 'Na': -4412.8227996808337, 'HOCl': -14578.981322327132, 'SiH2_s1A1d': -7904.0726269700554, 'SiO': -9920.2118092650708, 'F2': -5426.9009851655201, 'P2': -18569.7100395737, 'Si2': -15744.418687547124, 'C': -1028.5471962651873, 'CH': -1045.8247164754753, 'CO': -3081.4550529867706, 'CN': -2521.0913000695346, 'F': -2712.30655836285, 'H': -13.60405569717515, 'LiF': -2921.3671571474624, 'O': -2041.2483769244884, 'N': -1483.981485107872, 'Na2': -8826.410126700297, 'P': -9282.2144876505899, 'Si': -7870.4445140229245, 'SO2': -14923.501322516569, 'NaCl': -16933.432926277521, 'Li2': -406.96985635618387, 'NH2': -1519.3756700462491, 'CS': -11865.161113573042, 'C2H6': -2169.7998017018276, 'N2': -2978.5280844918202, 'C2H4': -2136.2951883618102, 'HCN': -2540.2803982015039, 'C2H2': -2102.2901648364796, 'CH2_s3B1d': -1064.1920578821023, 'CH3Cl': -13603.223029214254, 'BeH': -414.1082135671578, 'CO2': -5129.0868582477142, 'CH3SH': -11932.535768470407, 'OH': -2059.6213922996608, 'Cl': -12516.517962625088, 'S': -10828.826656949115, 'N2H4': -3042.0346586048404, 'H2O': -2078.6212796010145, 'SO': -12876.201520592005, 'CH2_s1A1d': -1063.5161597336582, 'H2CO': -3113.7397623037459, 'HCl': -12534.742429020402}, 'ea': {'NH3': 13.100740053431537, 'S2': 5.0008267551820609, 'SiH2_s3B1d': 5.7164638708964048, 'CH3OH': 22.552998434986876, 'SiH4': 13.604085389217289, 'Si2H6': 22.568815701608401, 'PH3': 10.381747062827344, 'PH2': 6.7072797465716576, 'HF': 6.1636413039109357, 'O2': 6.2316076101396902, 'SiH3': 9.654473298859557, 'NH': 3.8402115458250137, 'SH2': 7.9041964727566665, 'ClO': 3.5303514003462624, 'H2O2': 12.241387206829131, 'NO': 7.4618473923433157, 'ClF': 3.1367670942636323, 'LiH': 2.3176600686941526, 'HCO': 12.800892267050585, 'CH3': 13.442369612918583, 'CH4': 18.214280394339767, 'Cl2': 2.8506221855495824, 'HOCl': 7.6109270803808613, 'SiH2_s1A1d': 6.4200015527812866, 'SiO': 8.5189183176571532, 'F2': 2.2878684398201585, 'P2': 5.2810642725198704, 'Si2': 3.5296595012750913, 'CH': 3.6734645131127763, 'CO': 11.659479797095173, 'CN': 8.5626186964755107, 'LiF': 6.009686217001672, 'Na2': 0.7645273386297049, 'SO2': 12.177911718477844, 'NaCl': 4.0921639715998026, 'Li2': 0.86803122096216612, 'NH2': 8.1860735440266126, 'CS': 7.7872603587384219, 'C2H6': 31.081074988401724, 'N2': 10.565114276076201, 'C2H4': 24.784573042734792, 'HCN': 14.147661131269615, 'C2H2': 17.987660911754574, 'CH2_s3B1d': 8.4367502225645694, 'CH3Cl': 17.345703232453161, 'BeH': 2.4056192789431634, 'CO2': 18.042908133550554, 'CH3SH': 20.745692467404297, 'OH': 4.7689596779973726, 'N2H4': 19.655465600395473, 'H2O': 10.164791282175884, 'SO': 6.126486718401793, 'CH2_s1A1d': 7.7608520741205211, 'H2CO': 16.736077719720015, 'HCl': 4.6204106981385848}}
En10 = [ref['ea'][name] for name in molecule_names]
Dn10 = [ref['distance'][name] for name in molecule_names]
print(abs(En1 - En10).max())
print(abs(Dn1 - Dn10).max())

Example #33
0
    def update(self, atoms=None):
        if not self.calculation_required(atoms, ['energy', 'forces']):
            return

        if atoms is None:
            atoms = self.calculator.get_atoms()
        self.energy = self.calculator.get_potential_energy(atoms)
        self.forces = self.calculator.get_forces(atoms)
        self.atoms = atoms.copy()

        if self.vdwradii is not None:
            # external vdW radii
            vdwradii = self.vdwradii
            assert (len(atoms) == len(vdwradii))
        else:
            vdwradii = []
            for atom in atoms:
                self.vdwradii.append(vdWDB_Grimme06jcc[atom.symbol][1])

        if self.hirshfeld == None:
            volume_ratios = [1.] * len(atoms)
        elif hasattr(self.hirshfeld, '__len__'):  # a list
            assert (len(atoms) == len(self.hirshfeld))
            volume_ratios = self.hirshfeld
        else:  # should be an object
            self.hirshfeld.initialize()
            volume_ratios = self.hirshfeld.get_effective_volume_ratios()

        # correction for effective C6
        na = len(atoms)
        C6eff_a = np.empty((na))
        alpha_a = np.empty((na))
        R0eff_a = np.empty((na))
        for a, atom in enumerate(atoms):
            # free atom values
            alpha_a[a], C6eff_a[a] = self.vdWDB_alphaC6[atom.symbol]
            # correction for effective C6
            C6eff_a[a] *= Hartree * volume_ratios[a]**2 * Bohr**6
            R0eff_a[a] = vdwradii[a] * volume_ratios[a]**(1. / 3.)
        C6eff_aa = np.empty((na, na))
        for a in range(na):
            for b in range(a, na):
                C6eff_aa[a, b] = (2 * C6eff_a[a] * C6eff_a[b] /
                                  (alpha_a[b] / alpha_a[a] * C6eff_a[a] +
                                   alpha_a[a] / alpha_a[b] * C6eff_a[b]))
                C6eff_aa[b, a] = C6eff_aa[a, b]

        # PBC
        pbc_c = atoms.get_pbc()
        cell_c = atoms.get_cell()
        Rcell_c = np.sqrt(np.sum(cell_c**2, axis=1))
        ncells_c = np.ceil(np.where(pbc_c, 1. + self.Rmax / Rcell_c, 1))
        ncells_c = np.array(ncells_c, dtype=int)

        positions = atoms.get_positions()
        EvdW = 0.0
        forces = 0. * self.forces
        # loop over all atoms in the cell
        for ia, posa in enumerate(positions):
            # loop over all atoms in the cell (and neighbour cells for PBC)
            for ib, posb in enumerate(positions):
                # loops over neighbour cells
                for ix in range(-ncells_c[0] + 1, ncells_c[0]):
                    for iy in range(-ncells_c[1] + 1, ncells_c[1]):
                        for iz in range(-ncells_c[2] + 1, ncells_c[2]):
                            i_c = np.array([ix, iy, iz])
                            diff = posb + np.dot(i_c, cell_c) - posa
                            r2 = np.dot(diff, diff)
                            r6 = r2**3
                            r = np.sqrt(r2)
                            if r > 1.e-10 and r < self.Rmax:
                                Edamp, Fdamp = self.damping(r,
                                                            R0eff_a[ia],
                                                            R0eff_a[ib],
                                                            d=self.d,
                                                            sR=self.sR)
                                EvdW -= (Edamp * C6eff_aa[ia, ib] / r6)
                                # we neglect the C6eff contribution to the
                                # forces
                                forces[ia] -= ((Fdamp - 6 * Edamp / r) *
                                               C6eff_aa[ia, ib] / r6 * diff /
                                               r)
        self.energy += EvdW / 2.  # double counting
        self.forces += forces / 2.  # double counting

        if self.txt:
            prnt(('\n' + self.__class__.__name__), file=self.txt)
            prnt('vdW correction: %g' % (EvdW / 2.), file=self.txt)
            prnt('Energy:         %g' % self.energy, file=self.txt)
            prnt('\nForces in eV/Ang:', file=self.txt)
            c = Hartree / Bohr
            symbols = self.atoms.get_chemical_symbols()
            for ia, symbol in enumerate(symbols):
                prnt('%3d %-2s %10.5f %10.5f %10.5f' %
                     ((ia, symbol) + tuple(self.forces[ia])),
                     file=self.txt)
Example #34
0
    def __init__(self, calc, xc=None, kpts=None, bands=None, ecut=None,
                 omega=None, world=mpi.world, txt=sys.stdout, timer=None):
    
        PairDensity.__init__(self, calc, ecut, world=world, txt=txt,
                             timer=timer)

        if xc is None or xc == 'EXX':
            self.exx_fraction = 1.0
            xc = XC(XCNull())
        elif xc == 'PBE0':
            self.exx_fraction = 0.25
            xc = XC('HYB_GGA_XC_PBEH')
        elif xc == 'HSE03':
            omega = 0.106
            self.exx_fraction = 0.25
            xc = XC('HYB_GGA_XC_HSE03')
        elif xc == 'HSE06':
            omega = 0.11
            self.exx_fraction = 0.25
            xc = XC('HYB_GGA_XC_HSE06')
        elif xc == 'B3LYP':
            self.exx_fraction = 0.2
            xc = XC('HYB_GGA_XC_B3LYP')
            
        self.xc = xc
        self.omega = omega
        self.exc = np.nan  # density dependent part of xc-energy
        
        self.kpts = select_kpts(kpts, self.calc)
        
        if bands is None:
            # Do all occupied bands:
            bands = [0, self.nocc2]
        
        prnt('Calculating exact exchange contributions for band index',
             '%d-%d' % (bands[0], bands[1] - 1), file=self.fd)
        prnt('for IBZ k-points with indices:',
             ', '.join(str(i) for i in self.kpts), file=self.fd)
        
        self.bands = bands

        if self.ecut is None:
            self.ecut = self.calc.wfs.pd.ecut
        prnt('Plane-wave cutoff: %.3f eV' % (self.ecut * Hartree),
             file=self.fd)
        
        shape = (self.calc.wfs.nspins, len(self.kpts), bands[1] - bands[0])
        self.exxvv_sin = np.zeros(shape)   # valence-valence exchange energies
        self.exxvc_sin = np.zeros(shape)   # valence-core exchange energies
        self.f_sin = np.empty(shape)       # occupation numbers

        # The total EXX energy will not be calculated if we are only
        # interested in a few eigenvalues for a few k-points
        self.exx = np.nan    # total EXX energy
        self.exxvv = np.nan  # valence-valence
        self.exxvc = np.nan  # valence-core
        self.exxcc = 0.0     # core-core

        self.mysKn1n2 = None  # my (s, K, n1, n2) indices
        self.distribute_k_points_and_bands(0, self.nocc2)
        
        # All occupied states:
        self.mykpts = [self.get_k_point(s, K, n1, n2)
                       for s, K, n1, n2 in self.mysKn1n2]

        prnt('Using Wigner-Seitz truncated coulomb interaction.',
             file=self.fd)
        self.wstc = WignerSeitzTruncatedCoulomb(self.calc.wfs.gd.cell_cv,
                                                self.calc.wfs.kd.N_c,
                                                self.fd)
        self.iG_qG = {}  # cache
            
        # PAW matrices:
        self.V_asii = []  # valence-valence correction
        self.C_aii = []   # valence-core correction
        self.initialize_paw_exx_corrections()
Example #35
0
    def __init__(self, calc, xc=None, kpts=None, bands=None, ecut=150.0,
                 alpha=0.0, skip_gamma=False,
                 world=mpi.world, txt=sys.stdout):
    
        alpha /= Bohr**2

        PairDensity.__init__(self, calc, ecut, world=world, txt=txt)

        ecut /= Hartree
        
        if xc is None:
            self.exx_fraction = 1.0
            xc = XC(XCNull())
        if xc == 'PBE0':
            self.exx_fraction = 0.25
            xc = XC('HYB_GGA_XC_PBEH')
        elif xc == 'B3LYP':
            self.exx_fraction = 0.2
            xc = XC('HYB_GGA_XC_B3LYP')
        self.xc = xc
        self.exc = np.nan  # density dependent part of xc-energy
        
        if kpts is None:
            # Do all k-points in the IBZ:
            kpts = range(self.calc.wfs.kd.nibzkpts)
        
        if bands is None:
            # Do all occupied bands:
            bands = [0, self.nocc2]
        
        prnt('Calculating exact exchange contributions for band index',
             '%d-%d' % (bands[0], bands[1] - 1), file=self.fd)
        prnt('for IBZ k-points with indices:',
             ', '.join(str(i) for i in kpts), file=self.fd)
        
        self.kpts = kpts
        self.bands = bands

        shape = (self.calc.wfs.nspins, len(kpts), bands[1] - bands[0])
        self.exxvv_sin = np.zeros(shape)   # valence-valence exchange energies
        self.exxvc_sin = np.zeros(shape)   # valence-core exchange energies
        self.f_sin = np.empty(shape)       # occupation numbers

        # The total EXX energy will not be calculated if we are only
        # interested in a few eigenvalues for a few k-points
        self.exx = np.nan    # total EXX energy
        self.exxvv = np.nan  # valence-valence
        self.exxvc = np.nan  # valence-core
        self.exxcc = 0.0     # core-core

        self.mysKn1n2 = None  # my (s, K, n1, n2) indices
        self.distribute_k_points_and_bands(self.nocc2)
        
        # All occupied states:
        self.mykpts = [self.get_k_point(s, K, n1, n2)
                       for s, K, n1, n2 in self.mysKn1n2]

        # Compensation charge used for molecular calculations only:
        self.beta = None      # e^(-beta*r^2)
        self.ngauss_G = None  # density
        self.vgauss_G = None  # potential

        self.G0 = None  # effective value for |G+q| when |G+q|=0
        
        self.skip_gamma = skip_gamma
        
        if not self.calc.atoms.pbc.any():
            # Set exponent of exp-function to -19 on the boundary:
            self.beta = 4 * 19 * (self.calc.wfs.gd.icell_cv**2).sum(1).max()
            prnt('Gaussian for electrostatic decoupling: e^(-beta*r^2),',
                 'beta=%.3f 1/Ang^2' % (self.beta / Bohr**2), file=self.fd)
        elif skip_gamma:
            prnt('Skip |G+q|=0 term', file=self.fd)
        else:
            # Volume per q-point:
            dvq = (2 * pi)**3 / self.vol / self.calc.wfs.kd.nbzkpts
            qcut = (dvq / (4 * pi / 3))**(1 / 3)
            if alpha == 0.0:
                self.G0 = (4 * pi * qcut / dvq)**-0.5
            else:
                self.G0 = (2 * pi**1.5 * erf(alpha**0.5 * qcut) / alpha**0.5 /
                           dvq)**-0.5
            prnt('G+q=0 term: Integrate e^(-alpha*q^2)/q^2 for',
                 'q<%.3f 1/Ang and alpha=%.3f Ang^2' %
                 (qcut / Bohr, alpha * Bohr**2), file=self.fd)

        # PAW matrices:
        self.V_asii = []  # valence-valence correction
        self.C_aii = []   # valence-core correction
        self.initialize_paw_exx_corrections()
    def to_file(self, calculator,
                filename='multipole.dat',
                mode='a'):
        """Expand the charge distribution in multipoles and write
        the result to a file"""

        if self.gd is None:
            self.initialize(calculator.density.finegd)
        q_L = self.expand(-calculator.density.rhot_g)

        f = paropen(filename, mode)

        prnt('# Multipole expansion of the charge density', file=f)
        prnt('# center =', self.center * Bohr, 'Angstrom', file=f)
        prnt('# lmax =', self.lmax, file=f)
        prnt(('# see https://trac.fysik.dtu.dk/projects/gpaw/browser/' +
              'trunk/c/bmgs/sharmonic.py'), file=f)
        prnt('# for the definition of spherical harmonics', file=f)
        prnt('# l  m    q_lm[|e| Angstrom**l]', file=f)

        L = 0
        for l in range(self.lmax + 1):
            for m in range(-l, l + 1):
                prnt('{0:2d} {1:3d} {2:g}'.format(l, m, q_L[L]), file=f)
                L += 1
        f.close()
Example #37
0
    def calculate(self, ecut, nbands=None):
        """Calculate RPA correlation energy for one or several cutoffs.

        ecut: float or list of floats
            Plane-wave cutoff(s).
        nbands: int
            Number of bands (defaults to number of plane-waves).
        """

        if isinstance(ecut, (float, int)):
            ecut_i = [ecut]
            for i in range(5):
                ecut_i.append(ecut_i[-1] * 0.8)
            ecut_i = np.sort(ecut_i)
        else:
            ecut_i = np.sort(ecut)
        self.ecut_i = np.asarray(ecut_i) / Hartree
        ecutmax = max(self.ecut_i)
        
        if nbands is None:
            prnt('Response function bands    : Equal to number of plane waves',
                 file=self.fd)
        else:
            prnt('Response function bands    : %s' % nbands, file=self.fd)
        prnt('Plane wave cutoff energies :', file=self.fd)
        for ecut in ecut_i:
            prnt('    %.0f eV' % ecut, file=self.fd)
        prnt(file=self.fd)

        if self.filename and os.path.isfile(self.filename):
            self.read()
            self.world.barrier()

        chi0 = Chi0(self.calc, 1j * Hartree * self.myomega_w, eta=0.0,
                    txt='response.txt', world=self.chicomm)

        nq = len(self.energy_qi)
        for q_c in self.ibzq_qc[nq:]:
            if (q_c == 0.0).all() and self.skip_gamma:
                self.energy_qi.append(len(self.ecut_i) * [0.0])
                self.write()
                prnt('Not calculating E_c(q) at Gamma', file=self.fd)
                prnt(file=self.fd)
                continue

            thisqd = KPointDescriptor([q_c])
            pd = PWDescriptor(ecutmax, self.calc.wfs.gd, complex, thisqd)
            nG = pd.ngmax

            chi0_wGG = np.zeros((self.mynw, nG, nG), complex)
            if not q_c.any():
                # Wings (x=0,1) and head (G=0) for optical limit and three
                # directions (v=0,1,2):
                chi0_wxvG = np.zeros((self.mynw, 2, 3, nG), complex)
            else:
                chi0_wxvG = None

            Q_aGii = chi0.initialize_paw_corrections(pd)

            # First not completely filled band:
            m1 = chi0.nocc1
            prnt('# %s  -  %s' % (len(self.energy_qi), ctime().split()[-2]),
                 file=self.fd)
            prnt('q = [%1.3f %1.3f %1.3f]' % tuple(q_c), file=self.fd)

            energy_i = []
            for ecut in self.ecut_i:
                if ecut == ecutmax:
                    # Nothing to cut away:
                    cut_G = None
                    m2 = nbands or nG
                else:
                    cut_G = np.arange(nG)[pd.G2_qG[0] <= 2 * ecut]
                    m2 = len(cut_G)

                prnt('E_cut = %d eV / Bands = %d:   ' % (ecut * Hartree, m2),
                     file=self.fd, end='', flush=True)

                energy = self.calculate_q(chi0, pd,
                                          chi0_wGG, chi0_wxvG, Q_aGii,
                                          m1, m2, cut_G)
                energy_i.append(energy)
                m1 = m2

                if ecut < ecutmax and self.chicomm.size > 1:
                    # Chi0 will be summed again over chicomm, so we divide
                    # by its size:
                    chi0_wGG *= 1.0 / self.chicomm.size
                    if chi0_wxvG is not None:
                        chi0_wxvG *= 1.0 / self.chicomm.size

            self.energy_qi.append(energy_i)
            self.write()
            prnt(file=self.fd)

        e_i = np.dot(self.weight_q, np.array(self.energy_qi))
        prnt('==========================================================',
             file=self.fd)
        prnt(file=self.fd)
        prnt('Total correlation energy:', file=self.fd)
        for e_cut, e in zip(self.ecut_i, e_i):
            prnt('%6.0f:   %6.4f eV' % (e_cut * Hartree, e * Hartree),
                 file=self.fd)
        prnt(file=self.fd)

        if len(e_i) > 1:
            self.extrapolate(e_i)

        prnt('Calculation completed at: ', ctime(), file=self.fd)
        prnt(file=self.fd)

        return e_i * Hartree
Example #38
0
    def calculate_rkernel(self):

        gd = self.gd
        ng_c = gd.N_c
        cell_cv = gd.cell_cv
        icell_cv = 2 * np.pi * np.linalg.inv(cell_cv)
        vol = np.linalg.det(cell_cv)

        ns = self.calc.wfs.nspins
        n_g = self.n_g   # density on rough grid

        fx_g = ns * self.get_fxc_g(n_g)   # local exchange kernel
        qc_g = (-4 * np.pi * ns / fx_g)**0.5   # cutoff functional
        flocal_g = qc_g**3 * fx_g / (6 * np.pi**2)   # ren. x-kernel for r=r'
        Vlocal_g = 2 * qc_g / np.pi   # ren. Hartree kernel for r=r'

        ng = np.prod(ng_c)   # number of grid points
        r_vg = gd.get_grid_point_coordinates()
        rx_g = r_vg[0].flatten()
        ry_g = r_vg[1].flatten()
        rz_g = r_vg[2].flatten()

        prnt('    %d grid points and %d plane waves at the Gamma point' %
             (ng, self.pd.ngmax), file=self.fd)

        # Unit cells
        R_Rv = []
        weight_R = []
        nR_v = self.unit_cells
        nR = np.prod(nR_v)
        for i in range(-nR_v[0] + 1, nR_v[0]):
            for j in range(-nR_v[1] + 1, nR_v[1]):
                for h in range(-nR_v[2] + 1, nR_v[2]):
                    R_Rv.append(i * cell_cv[0] +
                                j * cell_cv[1] +
                                h * cell_cv[2])
                    weight_R.append((nR_v[0] - abs(i)) *
                                    (nR_v[1] - abs(j)) *
                                    (nR_v[2] - abs(h)) / float(nR))
        if nR > 1:
            # with more than one unit cell only the exchange kernel is
            # calculated on the grid. The bare Coulomb kernel is added
            # in PW basis and Vlocal_g only the exchange part
            dv = self.calc.density.gd.dv
            gc = (3 * dv / 4 / np.pi)**(1 / 3.)
            Vlocal_g -= 2 * np.pi * gc**2 / dv
            prnt('    Lattice point sampling: ' +
                 '(%s x %s x %s)^2 ' % (nR_v[0], nR_v[1], nR_v[2]) +
                 ' Reduced to %s lattice points' % len(R_Rv), file=self.fd)

        l_g_size = -(-ng // mpi.world.size)
        l_g_range = range(mpi.world.rank * l_g_size,
                          min((mpi.world.rank+1) * l_g_size, ng))

        fhxc_qsGr = {}
        for iq in range(len(self.ibzq_qc)):
            fhxc_qsGr[iq] = np.zeros((ns, len(self.pd.G2_qG[iq]),
                                      len(l_g_range)), dtype=complex)

        inv_error = np.seterr()
        np.seterr(invalid='ignore')
        np.seterr(divide='ignore')

        t0 = time()
        # Loop over Lattice points
        for i, R_v in enumerate(R_Rv):
            # Loop over r'. f_rr and V_rr are functions of r (dim. as r_vg[0])
            if i == 1:
                prnt('      Finished 1 cell in %s seconds' % int(time() - t0) +
                     ' - estimated %s seconds left' %
                     int((len(R_Rv) - 1) * (time() - t0)), 
                     file=self.fd)
                self.fd.flush()
            if len(R_Rv) > 5:
                if (i+1) % (len(R_Rv) / 5 + 1) == 0:
                    prnt('      Finished %s cells in %s seconds'
                         % (i, int(time() - t0))
                         + ' - estimated %s seconds left'
                         % int((len(R_Rv) - i) * (time() - t0) / i), 
                         file=self.fd)
                    self.fd.flush()
            for g in l_g_range:
                rx = rx_g[g] + R_v[0]
                ry = ry_g[g] + R_v[1]
                rz = rz_g[g] + R_v[2]

                # |r-r'-R_i|
                rr = ((r_vg[0] - rx)**2 +
                      (r_vg[1] - ry)**2 +
                      (r_vg[2] - rz)**2)**0.5

                n_av = (n_g + n_g.flatten()[g]) / 2.
                fx_g = ns * self.get_fxc_g(n_av, index=g)
                qc_g = (-4 * np.pi * ns / fx_g)**0.5
                x = qc_g * rr
                osc_x = np.sin(x) - x*np.cos(x)
                f_rr = fx_g * osc_x / (2 * np.pi**2 * rr**3)
                if nR > 1:   # include only exchange part of the kernel here
                    V_rr = (sici(x)[0] * 2 / np.pi - 1) / rr
                else:        # include the full kernel (also hartree part)
                    V_rr = (sici(x)[0] * 2 / np.pi) / rr

                # Terms with r = r'
                if (np.abs(R_v) < 0.001).all():
                    tmp_flat = f_rr.flatten()
                    tmp_flat[g] = flocal_g.flatten()[g]
                    f_rr = tmp_flat.reshape(ng_c)
                    tmp_flat = V_rr.flatten()
                    tmp_flat[g] = Vlocal_g.flatten()[g]
                    V_rr = tmp_flat.reshape(ng_c)
                    del tmp_flat

                f_rr[np.where(n_av < self.density_cut)] = 0.0
                V_rr[np.where(n_av < self.density_cut)] = 0.0

                f_rr *= weight_R[i]
                V_rr *= weight_R[i]

                # r-r'-R_i
                r_r = np.array([r_vg[0] - rx, r_vg[1] - ry, r_vg[2] - rz])

                # Fourier transform of r
                for iq, q in enumerate(self.ibzq_qc):
                    q_v = np.dot(q, icell_cv)
                    e_q = np.exp(-1j * gemmdot(q_v, r_r, beta=0.0))
                    f_q = self.pd.fft((f_rr + V_rr) * e_q, iq) * vol / ng
                    fhxc_qsGr[iq][0, :, g - l_g_range[0]] += f_q
                    if ns == 2:
                        f_q = self.pd.fft(V_rr * e_q, iq) * vol / ng
                        fhxc_qsGr[iq][1, :, g - l_g_range[0]] += f_q

        mpi.world.barrier()

        np.seterr(**inv_error)

        for iq, q in enumerate(self.ibzq_qc):
            npw = len(self.pd.G2_qG[iq])
            fhxc_sGsG = np.zeros((ns * npw, ns * npw), complex)
            l_pw_size = -(-npw // mpi.world.size)  # parallelize over PW below
            l_pw_range = range(mpi.world.rank * l_pw_size,
                               min((mpi.world.rank + 1) * l_pw_size, npw))

            if mpi.world.size > 1:
                # redistribute grid and plane waves in fhxc_qsGr[iq]
                bg1 = BlacsGrid(mpi.world, 1, mpi.world.size)
                bg2 = BlacsGrid(mpi.world, mpi.world.size, 1)
                bd1 = bg1.new_descriptor(npw, ng, npw, - (-ng / mpi.world.size))
                bd2 = bg2.new_descriptor(npw, ng, -(-npw / mpi.world.size), ng)

                fhxc_Glr = np.zeros((len(l_pw_range), ng), dtype=complex)
                if ns == 2:
                    Koff_Glr = np.zeros((len(l_pw_range), ng), dtype=complex)

                r = Redistributor(bg1.comm, bd1, bd2)
                r.redistribute(fhxc_qsGr[iq][0], fhxc_Glr, npw, ng)
                if ns == 2:
                    r.redistribute(fhxc_qsGr[iq][1], Koff_Glr, npw, ng)
            else:
                fhxc_Glr = fhxc_qsGr[iq][0]
                if ns == 2:
                    Koff_Glr = fhxc_qsGr[iq][1]

            # Fourier transform of r'
            for iG in range(len(l_pw_range)):
                f_g = fhxc_Glr[iG].reshape(ng_c)
                f_G = self.pd.fft(f_g.conj(), iq) * vol / ng
                fhxc_sGsG[l_pw_range[0] + iG, :npw] = f_G.conj()
                if ns == 2:
                    v_g = Koff_Glr[iG].reshape(ng_c)
                    v_G = self.pd.fft(v_g.conj(), iq) * vol / ng
                    fhxc_sGsG[npw + l_pw_range[0] + iG, :npw] = v_G.conj()

            if ns == 2:  # f_00 = f_11 and f_01 = f_10
                fhxc_sGsG[:npw, npw:] = fhxc_sGsG[npw:, :npw]
                fhxc_sGsG[npw:, npw:] = fhxc_sGsG[:npw, :npw]

            mpi.world.sum(fhxc_sGsG)
            fhxc_sGsG /= vol

            if mpi.rank == 0:
                w = Writer('fhxc_%s_%s_%s_%s.gpw' %
                           (self.tag, self.xc, self.ecut, iq))
                w.dimension('sG', ns * npw)
                w.add('fhxc_sGsG', ('sG', 'sG'), dtype=complex)
                if nR > 1:  # add Hartree kernel evaluated in PW basis
                    Gq2_G = self.pd.G2_qG[iq]
                    if (q == 0).all():
                        Gq2_G[0] = 1.
                    vq_G = 4 * np.pi / Gq2_G
                    fhxc_sGsG += np.tile(np.eye(npw) * vq_G, (ns, ns))
                w.fill(fhxc_sGsG)
                w.close()
            mpi.world.barrier()
        prnt(file=self.fd)
Example #39
0
                ve.append((abs(np.linalg.det(d.cell)), d.energy))
            except AttributeError:
                ve.append((np.nan, np.nan))

        # sort according to volume
        ves = sorted(ve, key=lambda x: x[0])

        # EOS
        eos = EquationOfState([t[0] for t in ves], [t[1] for t in ves])
        try:
            v, e, B0, B1, R = eos.fit()
        except (ValueError, TypeError, LinAlgError):
            (v, e, B0, B1, R) = (np.nan, np.nan, np.nan, np.nan, np.nan)
        e = e / len(collection[name])
        v = v / len(collection[name])
        B0 = B0 / kJ * 1.0e24  # GPa
        A.append((e, v, B0, B1, R))
    return np.array(A).T


E, V, B0, B1, R = analyse(c, collection)

fd = open(db + '_raw.txt', 'w')
for name, e, v, b0, b1, r, in zip(collection.names, E, V, B0, B1, R):
    if not np.isnan(e):
        prnt('%2s %8.4f %8.4f %8.4f' % (name, v, b0, b1), file=fd)
fd = open(db + '_raw.csv', 'w')
for name, e, v, b0, b1, r, in zip(collection.names, E, V, B0, B1, R):
    if not np.isnan(e):
        prnt('%s, %8.4f, %8.4f, %8.4f' % (name, v, b0, b1), file=fd)
Example #40
0
    def to_file(self, calculator, filename='multipole.dat', mode='a'):
        """Expand the charge distribution in multipoles and write
        the result to a file"""

        if self.gd is None:
            self.initialize(calculator.density.finegd)
        q_L = self.expand(-calculator.density.rhot_g)

        f = paropen(filename, mode)

        prnt('# Multipole expansion of the charge density', file=f)
        prnt('# center =', self.center * Bohr, 'Angstrom', file=f)
        prnt('# lmax =', self.lmax, file=f)
        prnt(('# see https://trac.fysik.dtu.dk/projects/gpaw/browser/' +
              'trunk/c/bmgs/sharmonic.py'),
             file=f)
        prnt('# for the definition of spherical harmonics', file=f)
        prnt('# l  m    q_lm[|e| Angstrom**l]', file=f)

        L = 0
        for l in range(self.lmax + 1):
            for m in range(-l, l + 1):
                prnt('{0:2d} {1:3d} {2:g}'.format(l, m, q_L[L]), file=f)
                L += 1
        f.close()
if len(sys.argv) == 2 and 'run.py' not in sys.argv:
    db = sys.argv[1]
else:
    db = 'compression.db'  # default db file

c = ase.db.connect(db)

def analyse(c, names, linspace):

    A = []
    for name in names:
        e = []  # energies
        for x in linspace:
            try:
                d = c.get(name=name, x=x)
                assert name == d.name
                e.append(d.energy)
            except (KeyError, AttributeError):
                e.append(np.nan)
        while len(e) < len(linspace):  # missing data
            e.append(np.nan)
        A.append(e)
    return A

E = analyse(c, names, linspace)

fd = open(db + '_energies.csv', 'w')
prnt('c' + ',' + ','.join([str(round(e, 3)) for e in linspace]), file=fd)
for name, energies, in zip(names, E):
    prnt(name + ',' + ','.join([str(round(e, 4)) for e in energies]), file=fd)
                ve.append((np.nan, np.nan))

        # sort according to volume
        ves = sorted(ve, key=lambda x: x[0])

        # EOS
        eos = EquationOfState([t[0] for t in ves],
                              [t[1] for t in ves])
        try:
            v, e0, B0, B1, R = eos.fit()
        except (ValueError, TypeError, LinAlgError):
            (v, e0, B0, B1, R) = (np.nan, np.nan, np.nan, np.nan, [np.nan])
        if not R: R = [np.nan]  # sometimes R is an empty array
        if not isinstance(R, list): R = [R]  # sometimes R is not a list
        e0 = e0
        v = v
        B0 = B0 / kJ * 1.0e24  # GPa
        A.append((e0, v, B0, B1, R[0]))
    return np.array(A).T

E0, V, B0, B1, R = analyse(c, names)

fd = open(db + '_raw.txt', 'w')
for name, e0, v, b0, b1, r, in zip(names, E0, V, B0, B1, R):
    if not np.isnan(e0):
        prnt('%2s %8.4f %8.4f %8.4f %8.4f' % (name, e0, v, b0, b1), file=fd)
fd = open(db + '_raw.csv', 'w')
for name, e0, v, b0, b1, r, in zip(names, E0, V, B0, B1, R):
    if not np.isnan(e0):
        prnt('%s, %8.4f, %8.4f, %8.4f, %8.4f' % (name, e0, v, b0, b1), file=fd)
Example #43
0
 def print_initialization(self, xc, frequency_scale, nlambda):
     prnt('----------------------------------------------------------',
          file=self.fd)
     prnt('Non-self-consistent %s correlation energy' % xc, file=self.fd)
     prnt('----------------------------------------------------------',
          file=self.fd)
     prnt('Started at:  ', ctime(), file=self.fd)
     prnt(file=self.fd)
     prnt('Atoms                          :',
          self.calc.atoms.get_chemical_formula(mode='hill'), file=self.fd)
     prnt('Ground state XC functional     :',
          self.calc.hamiltonian.xc.name, file=self.fd)
     prnt('Valence electrons              :',
          self.calc.wfs.setups.nvalence, file=self.fd)
     prnt('Number of bands                :',
          self.calc.wfs.bd.nbands, file=self.fd)
     prnt('Number of spins                :',
          self.calc.wfs.nspins, file=self.fd)
     prnt('Number of k-points             :',
          len(self.calc.wfs.kd.bzk_kc), file=self.fd)
     prnt('Number of irreducible k-points :',
          len(self.calc.wfs.kd.ibzk_kc), file=self.fd)
     prnt('Number of q-points             :',
          len(self.bzq_qc), file=self.fd)
     prnt('Number of irreducible q-points :',
          len(self.ibzq_qc), file=self.fd)
     prnt(file=self.fd)
     for q, weight in zip(self.ibzq_qc, self.weight_q):
         prnt('    q: [%1.4f %1.4f %1.4f] - weight: %1.3f' %
              (q[0], q[1], q[2], weight), file=self.fd)
     prnt(file=self.fd)
     prnt('----------------------------------------------------------',
          file=self.fd)
     prnt('----------------------------------------------------------',
          file=self.fd)
     prnt(file=self.fd)
     if nlambda is None:
         prnt('Analytical coupling constant integration', file=self.fd)
     else:
         prnt('Numerical coupling constant integration using', nlambda,
              'Gauss-Legendre points', file=self.fd)
     prnt(file=self.fd)
     prnt('Frequencies', file=self.fd)
     prnt('    Gauss-Legendre integration with %s frequency points' %
          len(self.omega_w), file=self.fd)
     prnt('    Transformed from [0,\infty] to [0,1] using e^[-aw^(1/B)]',
          file=self.fd)
     prnt('    Highest frequency point at %5.1f eV and B=%1.1f' %
          (self.omega_w[-1] * Hartree, frequency_scale), file=self.fd)
     prnt(file=self.fd)
     prnt('Parallelization', file=self.fd)
     prnt('    Total number of CPUs          : % s' % self.world.size,
          file=self.fd)
     prnt('    Frequency decomposition       : % s' % self.wcomm.size,
          file=self.fd)
     prnt('    K-point/band decomposition    : % s' % self.chicomm.size,
          file=self.fd)
     prnt(file=self.fd)
 def log(self, *args, **kwargs):
     prnt(file=self.fd, *args, **kwargs)
     self.fd.flush()
            siter = siter + c.get(name=name, category='fcc111', adsorbate='').niter
            stime = stime + c.get(name=name, category='fcc111', adsorbate='').time
            N = N + 1
            siter = siter + c.get(name=name, category='fcc111', adsorbate='O').niter
            stime = stime + c.get(name=name, category='fcc111', adsorbate='O').time
            N = N + 1
            siter = siter + c.get(name=name, category='fcc111', adsorbate='C').niter
            stime = stime + c.get(name=name, category='fcc111', adsorbate='C').time
            N = N + 1
            siter = siter + c.get(name='O', category='fcc', adsorbate='').niter
            stime = stime + c.get(name='O', category='fcc', adsorbate='').time
            N = N + 1
            siter = siter + c.get(name='C', category='fcc', adsorbate='').niter
            stime = stime + c.get(name='C', category='fcc', adsorbate='').time
            N = N + 1
            results[7] = siter / N
            results[8] = stime / N
        except:
            pass
        A.append(results)
    return np.array(A)

results = analyse(c, names)

fd = open(db + '_raw.txt', 'w')
for name, r in zip(names, results):
    prnt('%2s %s' % (name, str(' '.join([str(round(r0, 4)) for r0 in r]))), file=fd)
fd = open(db + '_raw.csv', 'w')
for name, r in zip(names, results):
    prnt('%2s,%s' % (name, str(','.join([str(round(r0, 4)) for r0 in r]))), file=fd)