Example #1
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()
        print('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' %
              (tuple(nk_c) + (rc * Bohr, )),
              file=txt)

        self.a = 5 / rc
        print('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]
        print('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 #2
0
 def initialize_clgd(self):
     N_c = get_number_of_grid_points(self.cl.cell, self.cl.spacing)
     self.cl.spacing = np.diag(self.cl.cell) / N_c
     self.cl.gd = GridDescriptor(N_c, self.cl.cell, False, self.cl.dcomm,
                                 self.cl.dparsize)
     self.cl.gd_global = GridDescriptor(N_c, self.cl.cell, False,
                                        serial_comm, None)
     self.cl.extrapolated_qm_phi = self.cl.gd.empty()
Example #3
0
class WignerSeitzTruncatedCoulomb:
    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

    def get_potential(self, pd):
        q_c = pd.kd.bzk_kc[0]
        shift_c = (q_c * self.nk_c).round().astype(int)
        max_c = self.gd.N_c // 2
        K_G = pd.zeros()
        N_c = pd.gd.N_c
        for G, Q in enumerate(pd.Q_qG[0]):
            Q_c = (np.unravel_index(Q, N_c) + N_c // 2) % N_c - N_c // 2
            Q_c = Q_c * self.nk_c + shift_c
            if (abs(Q_c) < max_c).all():
                K_G[G] = self.K_Q[tuple(Q_c)]

        G2_G = pd.G2_qG[0]
        a = self.a
        if pd.kd.gamma:
            K_G[0] += pi / a**2
        else:
            K_G[0] += 4 * pi * (1 - np.exp(-G2_G[0] / (4 * a**2))) / G2_G[0]
        K_G[1:] += 4 * pi * (1 - np.exp(-G2_G[1:] / (4 * a**2))) / G2_G[1:]
        assert pd.dtype == complex
        return K_G
Example #4
0
class WignerSeitzTruncatedCoulomb:
    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
        
    def get_potential(self, pd):
        q_c = pd.kd.bzk_kc[0]
        shift_c = (q_c * self.nk_c).round().astype(int)
        max_c = self.gd.N_c // 2
        K_G = pd.zeros()
        N_c = pd.gd.N_c
        for G, Q in enumerate(pd.Q_qG[0]):
            Q_c = (np.unravel_index(Q, N_c) + N_c // 2) % N_c - N_c // 2
            Q_c = Q_c * self.nk_c + shift_c
            if (abs(Q_c) < max_c).all():
                K_G[G] = self.K_Q[tuple(Q_c)]

        G2_G = pd.G2_qG[0]
        a = self.a
        if pd.kd.gamma:
            K_G[0] += pi / a**2
        else:
            K_G[0] += 4 * pi * (1 - np.exp(-G2_G[0] / (4 * a**2))) / G2_G[0]
        K_G[1:] += 4 * pi * (1 - np.exp(-G2_G[1:] / (4 * a**2))) / G2_G[1:]
        assert pd.dtype == complex
        return K_G
Example #5
0
    def setUp(self):
        for virtvar in ['boundaries']:
            assert getattr(self,
                           virtvar) is not None, 'Virtual "%s"!' % virtvar

        # Basic unit cell information:
        res, N_c = shapeopt(100, self.G**3, 3, 0.2)
        #N_c = 4*np.round(np.array(N_c)/4) # makes domain decomposition easier
        cell_cv = self.h * np.diag(N_c)
        pbc_c = {'zero'    : (False,False,False), \
                 'periodic': (True,True,True), \
                 'mixed'   : (True, False, True)}[self.boundaries]

        # Create randomized gas-like atomic configuration on interim grid
        tmpgd = GridDescriptor(N_c, cell_cv, pbc_c)
        self.atoms = create_random_atoms(tmpgd)

        # Create setups
        Z_a = self.atoms.get_atomic_numbers()
        assert 1 == self.nspins
        self.setups = Setups(Z_a, p.setups, p.basis, p.lmax, xc)
        self.natoms = len(self.setups)

        # Decide how many kpoints to sample from the 1st Brillouin Zone
        kpts_c = np.ceil(
            (10 / Bohr) / np.sum(cell_cv**2, axis=1)**0.5).astype(int)
        kpts_c = tuple(kpts_c * pbc_c + 1 - pbc_c)
        self.bzk_kc = kpts2ndarray(kpts_c)

        # Set up k-point descriptor
        self.kd = KPointDescriptor(self.bzk_kc, self.nspins)
        self.kd.set_symmetry(self.atoms, self.setups, p.usesymm)

        # Set the dtype
        if self.kd.gamma:
            self.dtype = float
        else:
            self.dtype = complex

        # Create communicators
        parsize, parsize_bands = self.get_parsizes()
        assert self.nbands % np.prod(parsize_bands) == 0
        domain_comm, kpt_comm, band_comm = distribute_cpus(
            parsize, parsize_bands, self.nspins, self.kd.nibzkpts)

        self.kd.set_communicator(kpt_comm)

        # Set up band descriptor:
        self.bd = BandDescriptor(self.nbands, band_comm)

        # Set up grid descriptor:
        self.gd = GridDescriptor(N_c, cell_cv, pbc_c, domain_comm, parsize)

        # Set up kpoint/spin descriptor (to be removed):
        self.kd_old = KPointDescriptorOld(self.nspins, self.kd.nibzkpts,
                                          kpt_comm, self.kd.gamma, self.dtype)
Example #6
0
    def setUp(self):
        for virtvar in ['boundaries', 'celltype']:
            assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar

        # Basic unit cell information:
        pbc_c = {'zero'    : (False,False,False), \
                 'periodic': (True,True,True), \
                 'mixed'   : (True, False, True)}[self.boundaries]
        a, b = self.a, 2**0.5*self.a
        cell_cv = {'general'   : np.array([[0,a,a],[a/2,0,a/2],[a/2,a/2,0]]),
                   'rotated'   : np.array([[0,0,b],[b/2,0,0],[0,b/2,0]]),
                   'inverted'   : np.array([[0,0,b],[0,b/2,0],[b/2,0,0]]),
                   'orthogonal': np.diag([b, b/2, b/2])}[self.celltype]
        cell_cv = np.array([(4-3*pbc)*c_v for pbc,c_v in zip(pbc_c, cell_cv)])

        # Decide how many kpoints to sample from the 1st Brillouin Zone
        kpts_c = np.ceil((10/Bohr)/np.sum(cell_cv**2,axis=1)**0.5).astype(int)
        kpts_c = tuple(kpts_c*pbc_c + 1-pbc_c)
        bzk_kc = kpts2ndarray(kpts_c)
        self.gamma = len(bzk_kc) == 1 and not bzk_kc[0].any()

        #p = InputParameters()
        #Z_a = self.atoms.get_atomic_numbers()
        #xcfunc = XC(p.xc)
        #setups = Setups(Z_a, p.setups, p.basis, p.lmax, xcfunc)
        #symmetry, weight_k, self.ibzk_kc = reduce_kpoints(self.atoms, bzk_kc,
        #                                                  setups, p.usesymm)

        self.ibzk_kc = bzk_kc.copy() # don't use symmetry reduction of kpoints
        self.nibzkpts = len(self.ibzk_kc)
        self.ibzk_kv = kpoint_convert(cell_cv, skpts_kc=self.ibzk_kc)

        # Parse parallelization parameters and create suitable communicators.
        #parsize, parsize_bands = create_parsize_minbands(self.nbands, world.size)
        parsize, parsize_bands = world.size//gcd(world.size, self.nibzkpts), 1
        assert self.nbands % np.prod(parsize_bands) == 0
        domain_comm, kpt_comm, band_comm = distribute_cpus(parsize,
            parsize_bands, self.nspins, self.nibzkpts)

        # Set up band descriptor:
        self.bd = BandDescriptor(self.nbands, band_comm)

        # Set up grid descriptor:
        N_c = np.round(np.sum(cell_cv**2, axis=1)**0.5 / self.h)
        N_c += 4-N_c % 4 # makes domain decomposition easier
        self.gd = GridDescriptor(N_c, cell_cv, pbc_c, domain_comm, parsize)
        self.assertEqual(self.gamma, np.all(~self.gd.pbc_c))

        # What to do about kpoints?
        self.kpt_comm = kpt_comm

        if debug and world.rank == 0:
            comm_sizes = tuple([comm.size for comm in [world, self.bd.comm, \
                                                   self.gd.comm, self.kpt_comm]])
            print '%d world, %d band, %d domain, %d kpt' % comm_sizes
Example #7
0
 def __init__(self, gd, spline_j, spos_c, index=None):
     rcut = max([spline.get_cutoff() for spline in spline_j])
     corner_c = np.ceil(spos_c * gd.N_c - rcut / gd.h_c).astype(int)
     size_c = np.ceil(spos_c * gd.N_c + rcut / gd.h_c).astype(int) - corner_c
     smallgd = GridDescriptor(N_c=size_c + 1, cell_cv=gd.h_c * (size_c + 1), pbc_c=False, comm=mpi.serial_comm)
     lfc = LFC(smallgd, [spline_j])
     lfc.set_positions((spos_c[np.newaxis, :] * gd.N_c - corner_c + 1) / smallgd.N_c)
     ni = lfc.Mmax
     f_iG = smallgd.zeros(ni)
     lfc.add(f_iG, {0: np.eye(ni)})
     LocalizedFunctions.__init__(self, gd, f_iG, corner_c, index=index)
def extend_grid(gd, N_cd):
    N_cd = np.array(N_cd)
    
    N_c = gd.N_c + N_cd.sum(axis=1)
    cell_cv = gd.h_cv * N_c
    
    move_c = gd.get_grid_spacings() * N_cd[:,0]
    
    egd = GridDescriptor(N_c, cell_cv, gd.pbc_c, gd.comm)
    egd.extend_N_cd = N_cd
    
    return egd, cell_cv*Bohr, move_c*Bohr
def extend_grid(gd, N_cd):
    N_cd = np.array(N_cd)

    N_c = gd.N_c + N_cd.sum(axis=1)
    cell_cv = gd.h_cv * N_c

    move_c = gd.get_grid_spacings() * N_cd[:, 0]

    egd = GridDescriptor(N_c, cell_cv, gd.pbc_c, gd.comm)
    egd.extend_N_cd = N_cd

    return egd, cell_cv * Bohr, move_c * Bohr
Example #10
0
def main():
    from gpaw.grid_descriptor import GridDescriptor
    from gpaw.mpi import world

    serial = world.new_communicator([world.rank])

    # Generator which must run on all ranks
    gen = np.random.RandomState(0)

    # This one is just used by master
    gen_serial = np.random.RandomState(17)

    maxsize = 5
    for i in range(1):
        N1_c = gen.randint(1, maxsize, 3)
        N2_c = gen.randint(1, maxsize, 3)

        gd1 = GridDescriptor(N1_c, N1_c)
        gd2 = GridDescriptor(N2_c, N2_c)
        serial_gd1 = gd1.new_descriptor(comm=serial)
        # serial_gd2 = gd2.new_descriptor(comm=serial)

        a1_serial = serial_gd1.empty()
        a1_serial.flat[:] = gen_serial.rand(a1_serial.size)

        if world.rank == 0:
            print('r0: a1 serial', a1_serial.ravel())

        a1 = gd1.empty()
        a1[:] = -1

        grid2grid(world, serial_gd1, gd1, a1_serial, a1)

        print(world.rank, 'a1 distributed', a1.ravel())
        world.barrier()

        a2 = gd2.zeros()
        a2[:] = -2
        grid2grid(world, gd1, gd2, a1, a2)
        print(world.rank, 'a2 distributed', a2.ravel())
        world.barrier()

        #grid2grid(world, gd2, gd2_serial

        gd1 = GridDescriptor(N1_c, N1_c * 0.2)
        #serialgd = gd2.new_descriptor(

        a1 = gd1.empty()
        a1.flat[:] = gen.rand(a1.size)

        #print a1
        grid2grid(world, gd1, gd2, a1, a2)
Example #11
0
def interpolate_2d(mat):
    from gpaw.grid_descriptor import GridDescriptor
    from gpaw.transformers import Transformer
    nn = 10
    N_c = np.zeros([3], dtype=int)
    N_c[1:] = mat.shape[:2]
    N_c[0] = nn
    bmat = np.resize(mat, N_c)
    gd = GridDescriptor(N_c, N_c)
    finegd = GridDescriptor(N_c * 2, N_c)
    interpolator = Transformer(gd, finegd, 3)
    fine_bmat = finegd.zeros()
    interpolator.apply(bmat, fine_bmat)
    return fine_bmat[0]
Example #12
0
    def initialize_more_things(self):
        if self.alphas:
            from gpaw.mpi import SerialCommunicator
            scale_c1 = (self.shape / (1.0 * self.gd.N_c))[:, np.newaxis]
            gdfft = GridDescriptor(self.shape,
                                   self.gd.cell_cv * scale_c1,
                                   True,
                                   comm=SerialCommunicator())
            k_k = construct_reciprocal(gdfft)[0][:, :, :self.shape[2] // 2 +
                                                 1]**0.5
            k_k[0, 0, 0] = 0.0

            self.dj_k = k_k / (2 * pi / self.rcut)
            self.j_k = self.dj_k.astype(int)
            self.dj_k -= self.j_k
            self.dj_k *= 2 * pi / self.rcut

            if self.verbose:
                print('VDW: density array size:',
                      self.gd.get_size_of_global_array())
                print('VDW: zero-padded array size:', self.shape)
                print(('VDW: maximum kinetic energy: %.3f Hartree' %
                       (0.5 * k_k.max()**2)))

            assert self.j_k.max() < self.Nr // 2, ('Use larger Nr than %i.' %
                                                   self.Nr)

        else:
            self.dj_k = None
            self.j_k = None
Example #13
0
    def read_3D(self, file, filetype=None):
        """Read the density from a 3D file"""

        if filetype is None:
            # estimate file type from name ending
            filetype = file.split('.')[-1]
        filetype.lower()

        if filetype == 'plt':
            data, cell = read_plt(file)

            pbc_c = [True, True, True]
            N_c = np.array(data.shape)
            for c in range(3):
                if N_c[c] % 2 == 1:
                    pbc_c[c] = False
                    N_c[c] += 1
            self.gd = GridDescriptor(N_c, cell.diagonal() / Bohr, pbc_c)
            self.offset_c = [int(not a) for a in self.gd.pbc_c]

        else:
            raise NotImplementedError('unknown file type "' + filetype + '"')

        self.file = file
        self.ldos = np.array(data * Bohr**3, np.float)
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 setUp(self):
        for virtvar in ['boundaries']:
            assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar

        parsize_domain, parsize_bands = create_parsize_minbands(self.nbands, world.size)
        assert self.nbands % np.prod(parsize_bands) == 0
        comms = distribute_cpus(parsize_domain,
                                parsize_bands, self.nspins, self.nibzkpts)
        domain_comm, kpt_comm, band_comm, block_comm = \
            [comms[name] for name in 'dkbK']

        self.block_comm = block_comm

        # Set up band descriptor:
        self.bd = BandDescriptor(self.nbands, band_comm)

        # Set up grid descriptor:
        res, ngpts = shapeopt(300, self.G**3, 3, 0.2)
        cell_c = self.h * np.array(ngpts)
        pbc_c = {'zero'    : False, \
                 'periodic': True, \
                 'mixed'   : (True, False, True)}[self.boundaries]
        self.gd = GridDescriptor(ngpts, cell_c, pbc_c, domain_comm, parsize_domain)

        # What to do about kpoints?
        self.kpt_comm = kpt_comm
Example #16
0
def test_coulomb(N=2**6, a=20):
    Nc = (N, N, N)  # Number of grid point
    gd = GridDescriptor(Nc, (a, a, a), True)  # grid-descriptor object
    xyz, r2 = coordinates(
        gd)  # matrix with the square of the radial coordinate
    r = np.sqrt(r2)  # matrix with the values of the radial coordinate
    nH = np.exp(-2 * r) / pi  # density of the hydrogen atom
    C = Coulomb(gd)  # coulomb calculator

    if world.size > 1:
        C.load('real')
        t0 = time.time()
        print('Processor %s of %s: %s Ha in %s sec' %
              (gd.comm.rank + 1, gd.comm.size,
               -0.5 * C.coulomb(nH, method='real'), time.time() - t0))
        return
    else:
        C.load('recip_ewald')
        C.load('recip_gauss')
        C.load('real')
        test = {}
        t0 = time.time()
        test['dual density'] = (-0.5 * C.coulomb(nH, nH.copy()),
                                time.time() - t0)
        for method in ('real', 'recip_gauss', 'recip_ewald'):
            t0 = time.time()
            test[method] = (-0.5 * C.coulomb(nH, method=method),
                            time.time() - t0)
        return test
Example #17
0
    def setUp(self):
        for virtvar in ['dtype', 'parstride_bands']:
            assert getattr(self,
                           virtvar) is not None, 'Virtual "%s"!' % virtvar

        parsize, parsize_bands = create_parsize_maxbands(
            self.nbands, world.size)
        assert self.nbands % np.prod(parsize_bands) == 0
        domain_comm, kpt_comm, band_comm = distribute_cpus(
            parsize, parsize_bands, self.nspins, self.nibzkpts)

        # Set up band descriptor:
        self.bd = BandDescriptor(self.nbands, band_comm, self.parstride_bands)

        # Set up grid descriptor:
        res, ngpts = shapeopt(100, self.G**3, 3, 0.2)
        cell_c = self.h * np.array(ngpts)
        pbc_c = (True, False, True)
        self.gd = GridDescriptor(ngpts, cell_c, pbc_c, domain_comm, parsize)

        # Create Kohn-Sham layouts for these band and grid descriptors:
        self.ksl = self.create_kohn_sham_layouts()

        # What to do about kpoints?
        self.kpt_comm = kpt_comm
Example #18
0
 def __init__(self, gd, spline_j, spos_c, index=None):
     rcut = max([spline.get_cutoff() for spline in spline_j])
     corner_c = np.ceil(spos_c * gd.N_c - rcut / gd.h_c).astype(int)
     size_c = np.ceil(spos_c * gd.N_c + rcut / gd.h_c).astype(int) - corner_c
     smallgd = GridDescriptor(N_c=size_c + 1,
                              cell_cv=gd.h_c * (size_c + 1),
                              pbc_c=False,
                              comm=mpi.serial_comm)
     lfc = LFC(smallgd, [spline_j])
     lfc.set_positions((spos_c[np.newaxis, :] * gd.N_c - corner_c + 1) /
                       smallgd.N_c)
     ni = lfc.Mmax
     f_iG = smallgd.zeros(ni)
     lfc.add(f_iG, {0: np.eye(ni)})
     LocalizedFunctions.__init__(self, gd, f_iG, corner_c, 
                                  index=index)
Example #19
0
    def set_grid_descriptor(self, gd):
        if (self.gd is not None and (self.gd.N_c == gd.N_c).all()
                and (self.gd.pbc_c == gd.pbc_c).all()
                and (self.gd.cell_cv == gd.cell_cv).all()):
            return

        VDWFunctional.set_grid_descriptor(self, gd)
        if self.size is None:
            self.shape = gd.N_c.copy()
            for c, n in enumerate(self.shape):
                if not gd.pbc_c[c]:
                    self.shape[c] = int(2**ceil(log(n) / log(2)))
        else:
            self.shape = np.array(self.size)

        scale_c1 = (self.shape / (1.0 * gd.N_c))[:, np.newaxis]
        gdfft = GridDescriptor(self.shape, gd.cell_cv * scale_c1, True)
        k_k = construct_reciprocal(gdfft)[0][:, :, :self.shape[2] // 2 +
                                             1]**0.5
        k_k[0, 0, 0] = 0.0

        self.dj_k = k_k / (2 * pi / self.rcut)
        self.j_k = self.dj_k.astype(int)
        self.dj_k -= self.j_k
        self.dj_k *= 2 * pi / self.rcut

        assert self.j_k.max() < self.Nr // 2, 'Use larger Nr.'

        if self.verbose:
            print 'VDW: density array size:', gd.get_size_of_global_array()
            print 'VDW: zero-padded array size:', self.shape
            print('VDW: maximum kinetic energy: %.3f Hartree' %
                  (0.5 * k_k.max()**2))
Example #20
0
    def get_combined_data(self, qmdata=None, cldata=None, spacing=None):

        if qmdata is None:
            qmdata = self.density.rhot_g

        if cldata is None:
            cldata = self.classical_material.charge_density

        if spacing is None:
            spacing = self.cl.gd.h_cv[0, 0]

        spacing_au = spacing / Bohr  # from Angstroms to a.u.

        # Collect data from different processes
        cln = self.cl.gd.collect(cldata)
        qmn = self.qm.gd.collect(qmdata)

        clgd = GridDescriptor(self.cl.gd.N_c, self.cl.cell, False, serial_comm,
                              None)

        if world.rank == 0:
            cln *= self.classical_material.sign
            # refine classical part
            while clgd.h_cv[0, 0] > spacing_au * 1.50:  # 45:
                cln = Transformer(clgd, clgd.refine()).apply(cln)
                clgd = clgd.refine()

            # refine quantum part
            qmgd = GridDescriptor(self.qm.gd.N_c, self.qm.cell, False,
                                  serial_comm, None)
            while qmgd.h_cv[0, 0] < clgd.h_cv[0, 0] * 0.95:
                qmn = Transformer(qmgd, qmgd.coarsen()).apply(qmn)
                qmgd = qmgd.coarsen()

            assert np.all(qmgd.h_cv == clgd.h_cv
                          ), " Spacings %.8f (qm) and %.8f (cl) Angstroms" % (
                              qmgd.h_cv[0][0] * Bohr, clgd.h_cv[0][0] * Bohr)

            # now find the corners
            r_gv_cl = clgd.get_grid_point_coordinates().transpose((1, 2, 3, 0))
            cind = self.qm.corner1 / np.diag(clgd.h_cv) - 1

            n = qmn.shape

            # print 'Corner points:     ', self.qm.corner1*Bohr,      ' - ', self.qm.corner2*Bohr
            # print 'Calculated points: ', r_gv_cl[tuple(cind)]*Bohr, ' - ', r_gv_cl[tuple(cind+n+1)]*Bohr

            cln[cind[0] + 1:cind[0] + n[0] + 1, cind[1] + 1:cind[1] + n[1] + 1,
                cind[2] + 1:cind[2] + n[2] + 1] += qmn

        world.barrier()
        return cln, clgd
Example #21
0
def test(xc, tol=5e-10):
    N_c = np.array([10, 6, 4])
    # This test is totally serial.
    gd = GridDescriptor(N_c,
                        N_c * 0.2,
                        pbc_c=(1, 0, 1),
                        comm=world.new_communicator([world.rank]))
    actual_n = N_c - (1 - gd.pbc_c)

    gen = np.random.RandomState(17)
    n_sg = gd.zeros(2)
    n_sg[:] = gen.rand(*n_sg.shape)
    #sigma_xg = gd.zeros(3)
    #sigma_xg[:] = gen.random.rand(*sigma_xg.shape)

    if hasattr(xc, 'libvdwxc'):
        xc._nspins = 2
        xc.initialize_backend(gd)

    v_sg = gd.zeros(2)
    E = xc.calculate(gd, n_sg, v_sg)
    print('E', E)

    dn = 1e-6

    all_indices = itertools.product(range(2), range(1, actual_n[0], 2),
                                    range(0, actual_n[1], 2),
                                    range(0, actual_n[2], 2))

    for testindex in all_indices:
        n1_sg = n_sg.copy()
        n2_sg = n_sg.copy()
        v = v_sg[testindex] * gd.dv
        n1_sg[testindex] -= dn
        n2_sg[testindex] += dn

        E1 = xc.calculate(gd, n1_sg, v_sg.copy())
        E2 = xc.calculate(gd, n2_sg, v_sg.copy())

        dedn = 0.5 * (E2 - E1) / dn
        err = abs(dedn - v)
        print('{}{} v={} fd={} err={}'.format(xc.name, list(testindex), v,
                                              dedn, err))
        assert err < tol, err
Example #22
0
def make_dummy_kpt_reference(l, function, k_c,
                             rcut=6., a=10., n=60, dtype=complex):
    r = np.linspace(0., rcut, 300)
    mcount = 2*l + 1
    fcount = 1
    kcount = 1
    gd = GridDescriptor((n, n, n), (a, a, a), (True, True, True))
    kpt = KPoint([], gd, 1., 0, 0, 0, k_c, dtype)
    spline = Spline(l, r[-1], function(r))
    center = (.5, .5, .5)
    lf = create_localized_functions([spline], gd, center, dtype=dtype)
    lf.set_phase_factors([kpt.k_c])
    psit_nG = gd.zeros(mcount, dtype=dtype)
    coef_xi = np.identity(mcount * fcount, dtype=dtype)
    lf.add(psit_nG, coef_xi, k=0)
    kpt.psit_nG = psit_nG
    print 'Number of boxes', len(lf.box_b)
    print 'Phase kb factors shape', lf.phase_kb.shape
    return gd, kpt, center
Example #23
0
    def setUp(self):
        for virtvar in ['boundaries', 'celltype']:
            assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar

        # Basic unit cell information:
        pbc_c = {'zero'    : (False,False,False), \
                 'periodic': (True,True,True), \
                 'mixed'   : (True, False, True)}[self.boundaries]
        a, b = self.a, 2**0.5*self.a
        cell_cv = {'general'   : np.array([[0,a,a],[a/2,0,a/2],[a/2,a/2,0]]),
                   'rotated'   : np.array([[0,0,b],[b/2,0,0],[0,b/2,0]]),
                   'inverted'   : np.array([[0,0,b],[0,b/2,0],[b/2,0,0]]),
                   'orthogonal': np.diag([b, b/2, b/2])}[self.celltype]
        cell_cv = np.array([(4-3*pbc)*c_v for pbc,c_v in zip(pbc_c, cell_cv)])

        # Decide how many kpoints to sample from the 1st Brillouin Zone
        kpts_c = np.ceil((10/Bohr)/np.sum(cell_cv**2,axis=1)**0.5).astype(int)
        kpts_c = tuple(kpts_c*pbc_c + 1-pbc_c)
        bzk_kc = kpts2ndarray(kpts_c)
        self.gamma = len(bzk_kc) == 1 and not bzk_kc[0].any()

        #p = InputParameters()
        #Z_a = self.atoms.get_atomic_numbers()
        #xcfunc = XC(p.xc)
        #setups = Setups(Z_a, p.setups, p.basis, p.lmax, xcfunc)
        #symmetry, weight_k, self.ibzk_kc = reduce_kpoints(self.atoms, bzk_kc,
        #                                                  setups, p.usesymm)

        self.ibzk_kc = bzk_kc.copy() # don't use symmetry reduction of kpoints
        self.nibzkpts = len(self.ibzk_kc)
        self.ibzk_kv = kpoint_convert(cell_cv, skpts_kc=self.ibzk_kc)

        # Parse parallelization parameters and create suitable communicators.
        #parsize_domain, parsize_bands = create_parsize_minbands(self.nbands, world.size)
        parsize_domain, parsize_bands = world.size//gcd(world.size, self.nibzkpts), 1
        assert self.nbands % np.prod(parsize_bands) == 0
        domain_comm, kpt_comm, band_comm = distribute_cpus(parsize_domain,
            parsize_bands, self.nspins, self.nibzkpts)

        # Set up band descriptor:
        self.bd = BandDescriptor(self.nbands, band_comm)

        # Set up grid descriptor:
        N_c = np.round(np.sum(cell_cv**2, axis=1)**0.5 / self.h)
        N_c += 4-N_c % 4 # makes domain decomposition easier
        self.gd = GridDescriptor(N_c, cell_cv, pbc_c, domain_comm, parsize_domain)
        self.assertEqual(self.gamma, np.all(~self.gd.pbc_c))

        # What to do about kpoints?
        self.kpt_comm = kpt_comm

        if debug and world.rank == 0:
            comm_sizes = tuple([comm.size for comm in [world, self.bd.comm, \
                                                   self.gd.comm, self.kpt_comm]])
            print '%d world, %d band, %d domain, %d kpt' % comm_sizes
    def get_combined_data(self, qmdata=None, cldata=None, spacing=None):
        
        if qmdata is None:
            qmdata = self.density.rhot_g
        
        if cldata is None:
            cldata = self.classical_material.charge_density
        
        if spacing is None:
            spacing = self.cl.gd.h_cv[0, 0]
        
        spacing_au = spacing / Bohr  # from Angstroms to a.u.
        
        # Collect data from different processes
        cln = self.cl.gd.collect(cldata)
        qmn = self.qm.gd.collect(qmdata)

        clgd = GridDescriptor(self.cl.gd.N_c,
                              self.cl.cell,
                              False,
                              serial_comm,
                              None)

        if world.rank == 0:
            cln *= self.classical_material.sign
            # refine classical part
            while clgd.h_cv[0, 0] > spacing_au * 1.50:  # 45:
                cln = Transformer(clgd, clgd.refine()).apply(cln)
                clgd = clgd.refine()
                
            # refine quantum part
            qmgd = GridDescriptor(self.qm.gd.N_c,
                                  self.qm.cell,
                                  False,
                                  serial_comm,
                                  None)                           
            while qmgd.h_cv[0, 0] < clgd.h_cv[0, 0] * 0.95:
                qmn = Transformer(qmgd, qmgd.coarsen()).apply(qmn)
                qmgd = qmgd.coarsen()
            
            assert np.all(qmgd.h_cv == clgd.h_cv), " Spacings %.8f (qm) and %.8f (cl) Angstroms" % (qmgd.h_cv[0][0] * Bohr, clgd.h_cv[0][0] * Bohr)
            
            # now find the corners
            r_gv_cl = clgd.get_grid_point_coordinates().transpose((1, 2, 3, 0))
            cind = self.qm.corner1 / np.diag(clgd.h_cv) - 1
            
            n = qmn.shape

            # print 'Corner points:     ', self.qm.corner1*Bohr,      ' - ', self.qm.corner2*Bohr
            # print 'Calculated points: ', r_gv_cl[tuple(cind)]*Bohr, ' - ', r_gv_cl[tuple(cind+n+1)]*Bohr
                        
            cln[cind[0] + 1:cind[0] + n[0] + 1,
                cind[1] + 1:cind[1] + n[1] + 1,
                cind[2] + 1:cind[2] + n[2] + 1] += qmn
        
        world.barrier()
        return cln, clgd
Example #25
0
def test():
    from gpaw.grid_descriptor import GridDescriptor

    ngpts = 40
    h = 1 / ngpts
    N_c = (ngpts, ngpts, ngpts)
    a = h * ngpts
    gd = GridDescriptor(N_c, (a, a, a))

    from gpaw.spline import Spline
    a = np.array([1, 0.9, 0.8, 0.0])
    s = Spline(0, 0.2, a)
    x = LocalizedFunctionsCollection(gd, [[s], [s]])
    x.set_positions([(0.5, 0.45, 0.5), (0.5, 0.55, 0.5)])
    n_G = gd.zeros()
    x.add(n_G)
    import pylab as plt
    plt.contourf(n_G[20, :, :])
    plt.axis('equal')
    plt.show()
Example #26
0
def test():
    from gpaw.grid_descriptor import GridDescriptor

    ngpts = 40
    h = 1.0 / ngpts
    N_c = (ngpts, ngpts, ngpts)
    a = h * ngpts
    gd = GridDescriptor(N_c, (a, a, a))
    
    from gpaw.spline import Spline
    a = np.array([1, 0.9, 0.8, 0.0])
    s = Spline(0, 0.2, a)
    x = LocalizedFunctionsCollection(gd, [[s], [s]])
    x.set_positions([(0.5, 0.45, 0.5), (0.5, 0.55, 0.5)])
    n_G = gd.zeros()
    x.add(n_G)
    import pylab as plt
    plt.contourf(n_G[20, :, :])
    plt.axis('equal')
    plt.show()
Example #27
0
    def solve_mesh(self, X, Y, Z, pot, dens0, permitivity):

        gd = GridDescriptor([X.shape[0] + 1, X.shape[1] + 1, X.shape[2] + 1],
                            cell_cv=[
                                X[0, -1, 0] - X[0, 0, 0],
                                Y[-1, 0, 0] - Y[0, 0, 0],
                                Z[0, 0, -1] - Z[0, 0, 0]
                            ],
                            pbc_c=False)
        self.set_grid_descriptor(gd)
        self.solve(pot, dens0, permitivity)
Example #28
0
def interpolate_weight(calc, weight, h=0.05, n=2):
    '''interpolates cdft weight function,
    gd is the fine grid '''
    gd = calc.density.finegd

    weight = gd.collect(weight, broadcast=True)
    weight = gd.zero_pad(weight)

    w = np.zeros_like(weight)
    gd1 = GridDescriptor(gd.N_c, gd.cell_cv, comm=serial_comm)
    gd1.distribute(weight, w)

    N_c = h2gpts(h / Bohr, gd.cell_cv)
    N_c = np.array([get_efficient_fft_size(N, n) for N in N_c])
    gd2 = GridDescriptor(N_c, gd.cell_cv, comm=serial_comm)

    interpolator = Interpolator(gd1, gd2)
    W = interpolator.interpolate(w)

    return W
Example #29
0
def go(comm, ngpts, repeat, narrays, out, prec):
    N_c = np.array((ngpts, ngpts, ngpts))
    a = 10.0
    gd = GridDescriptor(N_c, (a, a, a), comm=comm))
    gdcoarse = gd.coarsen()
    gdfine = gd.refine()
    kin1 = Laplace(gd, -0.5, 1).apply
    laplace = Laplace(gd, -0.5, 2)
    kin2 = laplace.apply
    restrict = Transformer(gd, gdcoarse, 1).apply
    interpolate = Transformer(gd, gdfine, 1).apply
    precondition = Preconditioner(gd, laplace, np_float)
    a1 = gd.empty(narrays)
    a1[:] = 1.0
    a2 = gd.empty(narrays)
    c = gdcoarse.empty(narrays)
    f = gdfine.empty(narrays)

    T = [0, 0, 0, 0, 0]
    for i in range(repeat):
        comm.barrier()
        kin1(a1, a2)
        comm.barrier()
        t0a = time()
        kin1(a1, a2)
        t0b = time()
        comm.barrier()
        t1a = time()
        kin2(a1, a2)
        t1b = time()
        comm.barrier()
        t2a = time()
        for A, C in zip(a1,c):
            restrict(A, C)
        t2b = time()
        comm.barrier()
        t3a = time()
        for A, F in zip(a1,f):
            interpolate(A, F)
        t3b = time()
        comm.barrier()
        if prec:
            t4a = time()
            for A in a1:
                precondition(A, None, None, None)
            t4b = time()
            comm.barrier()

        T[0] += t0b - t0a
        T[1] += t1b - t1a
        T[2] += t2b - t2a
        T[3] += t3b - t3a
        if prec:
            T[4] += t4b - t4a

    if mpi.rank == 0:
        out.write(' %2d %2d %2d' % tuple(gd.parsize_c))
        out.write(' %12.6f %12.6f %12.6f %12.6f %12.6f\n' %
                  tuple([t / repeat / narrays for t in T]))
        out.flush()
Example #30
0
    def __init__(self, calc, h=0.05, n=2):
        """Create transformation object.

        calc: GPAW calculator object
            The calcalator that has the wave functions.
        h: float
            Desired grid-spacing in Angstrom.
        n: int
            Force number of points to be a mulitiple of n.
        """
        self.calc = calc
        gd = calc.wfs.gd

        gd1 = GridDescriptor(gd.N_c, gd.cell_cv, comm=serial_comm)

        # Descriptor for the final grid:
        N_c = h2gpts(h / Bohr, gd.cell_cv)
        N_c = np.array([get_efficient_fft_size(N, n) for N in N_c])
        gd2 = self.gd = GridDescriptor(N_c, gd.cell_cv, comm=serial_comm)
        self.interpolator = Interpolator(gd1, gd2, self.calc.wfs.dtype)

        self.dphi = None  # PAW correction (will be initialized when needed)
Example #31
0
    def __init__(self, cell_cv, nk_c, txt=None):
        txt = txt or 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()
        print('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' %
              (tuple(nk_c) + (rc * Bohr,)), file=txt)

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

        nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0))
                for L in L_c]
        print('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_ijk = self.gd.empty()

        pos_ijkv = self.gd.get_grid_point_coordinates().transpose((1, 2, 3, 0))
        corner_xv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv)

        # Ignore division by zero (in 0,0,0 corner):
        with seterr(invalid='ignore'):
            # Loop over first dimension to avoid too large ndarrays.
            for pos_jkv, v_jk in zip(pos_ijkv, v_ijk):
                # Distances to the 8 corners:
                d_jkxv = pos_jkv[:, :, np.newaxis] - corner_xv
                r_jk = (d_jkxv**2).sum(axis=3).min(2)**0.5
                v_jk[:] = erf(self.a * r_jk) / r_jk

        # Fix 0/0 corner value:
        v_ijk[0, 0, 0] = 2 * self.a / pi**0.5

        self.K_Q = np.fft.fftn(v_ijk) * self.gd.dv
Example #32
0
def make_dummy_reference(l, function=None, rcut=6., a=12., n=60, dtype=float):
    """Make a mock reference wave function using a made-up radial function
    as reference"""
    #print 'Dummy reference: l=%d, rcut=%.02f, alpha=%.02f' % (l, rcut, alpha)
    r = np.arange(0., rcut, .01)

    if function is None:
        function = QuasiGaussian(4., rcut)

    norm = get_norm(r, function(r), l)
    function.renormalize(norm)
    #g = QuasiGaussian(alpha, rcut)

    mcount = 2 * l + 1
    fcount = 1
    gd = GridDescriptor((n, n, n), (a, a, a), (False, False, False))
    spline = Spline(l, r[-1], function(r), points=50)
    center = (.5, .5, .5)
    lf = create_localized_functions([spline], gd, center, dtype=dtype)
    psit_k = gd.zeros(mcount, dtype=dtype)
    coef_xi = np.identity(mcount * fcount, dtype=dtype)
    lf.add(psit_k, coef_xi)
    return gd, psit_k, center, function
Example #33
0
def extended_grid_descriptor(gd,
                             extend_N_cd=None,
                             N_c=None, extcomm=None):
    """Create grid descriptor for extended grid.

    Provide only either extend_N_cd or N_c.

    Parameters:

    extend_N_cd: ndarray, int
        Number of extra grid points per axis (c) and
        direction (d, left or right)
    N_c: ndarray, int
        Number of grid points in extended grid
    extcomm:
        Communicator for the extended grid, defaults to gd.comm
    """

    if extcomm is None:
        extcomm = gd.comm

    if extend_N_cd is None:
        assert N_c is not None, 'give only extend_N_cd or N_c'
        N_c = np.array(N_c, dtype=np.int)
        extend_N_cd = np.tile((N_c - gd.N_c) // 2, (2, 1)).T
    else:  # extend_N_cd is not None:
        assert N_c is None, 'give only extend_N_cd or N_c'
        extend_N_cd = np.array(extend_N_cd, dtype=np.int)
        N_c = gd.N_c + extend_N_cd.sum(axis=1)

    cell_cv = gd.h_cv * N_c
    move_c = gd.get_grid_spacings() * extend_N_cd[:, 0]

    egd = GridDescriptor(N_c, cell_cv, gd.pbc_c, extcomm)
    egd.extend_N_cd = extend_N_cd

    return egd, cell_cv * Bohr, move_c * Bohr
Example #34
0
def rigorous_testing():
    from itertools import product, permutations, cycle
    from gpaw.mpi import world
    gridpointcounts = [1, 2, 10, 21]
    cpucounts = np.arange(1, world.size + 1)
    pbc = cycle(product([0, 1], [0, 1], [0, 1]))

    # This yields all possible parallelizations!
    for parsize_c in product(cpucounts, cpucounts, cpucounts):
        if np.prod(parsize_c) != world.size:
            continue

        # All possible grid point counts
        for N_c in product(gridpointcounts, gridpointcounts, gridpointcounts):

            # We simply can't be bothered to also do all possible
            # combinations with PBCs.  Trying every possible set of
            # boundary conditions at least ones should be quite fine
            # enough.
            pbc_c = next(pbc)
            for dirs in permutations([0, 1, 2]):
                independent_dir, distribute_dir, reduce_dir = dirs

                parsize2_c = list(parsize_c)
                parsize2_c[reduce_dir] = 1
                parsize2_c[distribute_dir] *= parsize_c[reduce_dir]
                parsize2_c = tuple(parsize2_c)
                assert np.prod(parsize2_c) == np.prod(parsize_c)

                try:
                    gd = GridDescriptor(N_c=N_c,
                                        pbc_c=pbc_c,
                                        cell_cv=0.2 * np.array(N_c),
                                        parsize_c=parsize_c)
                    gd2 = get_compatible_grid_descriptor(
                        gd, distribute_dir, reduce_dir)

                    #gd2 = gd.new_descriptor(parsize_c=parsize2_c)
                except ValueError:  # Skip illegal distributions
                    continue

                if gd.comm.rank == 1:
                    #print(gd, gd2)
                    print(
                        'N_c=%s[%s] redist %s -> %s [ind=%d dist=%d red=%d]' %
                        (N_c, pbc_c, parsize_c, parsize2_c, independent_dir,
                         distribute_dir, reduce_dir))
                gd.comm.barrier()
                test(N_c, gd, gd2, reduce_dir, distribute_dir, verbose=False)
Example #35
0
def make_dummy_kpt_reference(l,
                             function,
                             k_c,
                             rcut=6.,
                             a=10.,
                             n=60,
                             dtype=complex):
    r = np.linspace(0., rcut, 300)
    mcount = 2 * l + 1
    fcount = 1
    kcount = 1
    gd = GridDescriptor((n, n, n), (a, a, a), (True, True, True))
    kpt = KPoint([], gd, 1., 0, 0, 0, k_c, dtype)
    spline = Spline(l, r[-1], function(r))
    center = (.5, .5, .5)
    lf = create_localized_functions([spline], gd, center, dtype=dtype)
    lf.set_phase_factors([kpt.k_c])
    psit_nG = gd.zeros(mcount, dtype=dtype)
    coef_xi = np.identity(mcount * fcount, dtype=dtype)
    lf.add(psit_nG, coef_xi, k=0)
    kpt.psit_nG = psit_nG
    print 'Number of boxes', len(lf.box_b)
    print 'Phase kb factors shape', lf.phase_kb.shape
    return gd, kpt, center
Example #36
0
 def apply_t(self):
     """Apply kinetic energy operator and return new object."""
     p = 2  # padding
     newsize_c = self.size_c + 2 * p
     gd = GridDescriptor(N_c=newsize_c + 1,
                         cell_cv=self.gd.h_c * (newsize_c + 1),
                         pbc_c=False,
                         comm=mpi.serial_comm)
     T = Laplace(gd, scale =1/2., n=p)
     f_ig = np.zeros((len(self.f_iG),) + tuple(newsize_c))
     f_ig[:, p:-p, p:-p, p:-p] = self.f_iG
     Tf_iG = np.empty_like(f_ig)
     T.apply(f_ig, Tf_iG)
     return LocalizedFunctions(self.gd, Tf_iG, self.corner_c - p,
                               self.index)
Example #37
0
def make_dummy_reference(l, function=None, rcut=6., a=12., n=60,
                         dtype=float):
    """Make a mock reference wave function using a made-up radial function
    as reference"""
    #print 'Dummy reference: l=%d, rcut=%.02f, alpha=%.02f' % (l, rcut, alpha)
    r = np.arange(0., rcut, .01)

    if function is None:
        function = QuasiGaussian(4., rcut)

    norm = get_norm(r, function(r), l)
    function.renormalize(norm)
    #g = QuasiGaussian(alpha, rcut)
    
    mcount = 2*l + 1
    fcount = 1
    gd = GridDescriptor((n, n, n), (a, a, a), (False, False, False))
    spline = Spline(l, r[-1], function(r), points=50)
    center = (.5, .5, .5)
    lf = create_localized_functions([spline], gd, center, dtype=dtype)
    psit_k = gd.zeros(mcount, dtype=dtype)
    coef_xi = np.identity(mcount * fcount, dtype=dtype)
    lf.add(psit_k, coef_xi)
    return gd, psit_k, center, function
Example #38
0
    def get_electrostatic_potential(self, ae=True, rcgauss=0.02):
        ham = self.calc.hamiltonian

        if ham.vHt_g is None:
            self.calc.restore_state()
            
        gd = ham.finegd
        v_r = gd.zero_pad(ham.vHt_g)
        gd1 = GridDescriptor(gd.N_c, gd.cell_cv, comm=serial_comm)
        interpolator = Interpolator(gd1, self.gd)
        v_R = interpolator.interpolate(v_r)

        if ae:
            alpha = 1 / (rcgauss / Bohr)**2
            self.add_potential_correction(v_R, alpha)
            
        return v_R * Hartree
Example #39
0
    def set_grid_descriptor(self, gd):
        if self.size is None:
            self.shape = gd.N_c.copy()
            for c, n in enumerate(self.shape):
                if not gd.pbc_c[c]:
                    # self.shape[c] = get_efficient_fft_size(n)
                    self.shape[c] = int(2**ceil(log(n) / log(2)))
        else:
            self.shape = np.array(self.size)
            for c, n in enumerate(self.shape):
                if gd.pbc_c[c]:
                    assert n == gd.N_c[c]
                else:
                    assert n >= gd.N_c[c]

        if self.alphas:
            scale_c1 = (self.shape / (1.0 * gd.N_c))[:, np.newaxis]
            gdfft = GridDescriptor(self.shape, gd.cell_cv * scale_c1, True)
            k_k = construct_reciprocal(gdfft)[0][:, :, :self.shape[2] // 2 +
                                                 1]**0.5
            k_k[0, 0, 0] = 0.0

            self.dj_k = k_k / (2 * pi / self.rcut)
            self.j_k = self.dj_k.astype(int)
            self.dj_k -= self.j_k
            self.dj_k *= 2 * pi / self.rcut

            if self.verbose:
                print('VDW: density array size:',
                      gd.get_size_of_global_array())
                print('VDW: zero-padded array size:', self.shape)
                print(('VDW: maximum kinetic energy: %.3f Hartree' %
                       (0.5 * k_k.max()**2)))

            assert self.j_k.max(
            ) < self.Nr // 2, 'Use larger Nr than %i.' % self.Nr

        else:
            self.dj_k = None
            self.j_k = None
def f(n, p):
    N = 2 * n
    gd = GridDescriptor((N, N, N), (L, L, L))
    a = gd.zeros()
    print(a.shape)
    #p = PoissonSolver(nn=1, relax=relax)
    p.set_grid_descriptor(gd)
    p.initialize()
    cut = N / 2.0 * 0.9
    s = Spline(l=0, rmax=cut, f_g=np.array([1, 0.5, 0.0]))
    c = LFC(gd, [[s], [s]])
    c.set_positions([(0, 0, 0), (0.5, 0.5, 0.5)])
    c.add(a)

    I0 = gd.integrate(a)
    a -= gd.integrate(a) / L**3

    I = gd.integrate(a)
    b = gd.zeros()
    p.solve(b, a, charge=0)#, eps=1e-20)
    return gd.collect(b, broadcast=1)
Example #41
0
from time import time
from gpaw.transformers import Transformer
from gpaw.grid_descriptor import GridDescriptor
from gpaw.mpi import world

ngpts = 80
N_c = (ngpts, ngpts, ngpts)
a = 10.0
gd = GridDescriptor(N_c, (a, a, a))
gdfine = gd.refine()
interpolate = Transformer(gd, gdfine, 3).apply
a1 = gd.empty()
a1[:] = 1.0
f = gdfine.empty()
ta = time()
r = 600
for i in range(r):
    interpolate(a1, f)
tb = time()
n = 8 * (1 + 2 + 4) * ngpts**3
print '%.3f GFlops' % (r * n / (tb - ta) * 1e-9)

"""
python: 0.330 GFlops
mpirun -np 2 gpaw-python: 0.500 GFlops
gpaw-python + OMP: 0.432 GFlops
"""
Example #42
0
        n[-1, i] -= 0.000002
        Em = xc.calculate_spherical(rgd, n, v)
        x2 = (Ep - Em) / 0.000002
        print(name, nspins, E, x, x2, x - x2)
        equal(x, x2, 1e-9)
        n[-1, i] += 0.000001
        if nspins == 1:
            ns = rgd.empty(2)
            ns[:] = n / 2
            Es = xc.calculate_spherical(rgd, ns, 0 * ns)
            equal(E, Es, 1e-13)
        

N = 20
a = 1.0
gd = GridDescriptor((N, N, N), (a, a, a))

for name in ['LDA', 'PBE']:
    xc = XC(name)
    for nspins in [1, 2]:
        n = gd.empty(nspins)
        n.fill(0.03)
        z = np.arange(gd.beg_c[2], gd.end_c[2]) * a / N
        n[:] += 0.01 * np.sin(2 * pi * z / a)
        if nspins == 2:
            n[1] += 0.01 * np.cos(2 * pi * z / a)
        n /= nspins

        v = 0.0 * n
        E = xc.calculate(gd, n, v)
Example #43
0
from gpaw.transformers import Transformer
import numpy.random as ra
from gpaw.grid_descriptor import GridDescriptor

p = 0
n = 20
gd1 = GridDescriptor((n, n, n), (8.0, 8.0, 8.0), pbc_c=p)
a1 = gd1.zeros()
ra.seed(8)
a1[:] = ra.random(a1.shape)
gd2 = gd1.refine()
a2 = gd2.zeros()
i = Transformer(gd1, gd2).apply
i(a1, a2)
assert abs(gd1.integrate(a1) - gd2.integrate(a2)) < 1e-10
r = Transformer(gd2, gd1).apply
a2[0] = 0.0
a2[:, 0] = 0.0
a2[:, :, 0] = 0.0
a2[-1] = 0.0
a2[:, -1] = 0.0
a2[:, :, -1] = 0.0
r(a2, a1)
assert abs(gd1.integrate(a1) - gd2.integrate(a2)) < 1e-10
Example #44
0
class DF(CHI):
    """This class defines dielectric function related physical quantities."""

    def __init__(self,
                 calc=None,
                 nbands=None,
                 w=None,
                 q=None,
                 eshift=None,
                 ecut=10.,
                 density_cut=None,
                 G_plus_q=False,
                 eta=0.2,
                 rpad=None,
                 vcut=None,
                 ftol=1e-7,
                 txt=None,
                 xc='ALDA',
                 print_xc_scf=False,
                 hilbert_trans=True,
                 time_ordered=False,
                 optical_limit=False,
                 comm=None,
                 kcommsize=None):

        CHI.__init__(self, calc=calc, nbands=nbands, w=w, q=q, eshift=eshift,
                     ecut=ecut, density_cut=density_cut,
                     G_plus_q=G_plus_q, eta=eta, rpad=rpad, vcut=vcut,
                     ftol=ftol, txt=txt, xc=xc, hilbert_trans=hilbert_trans,
                     time_ordered=time_ordered, optical_limit=optical_limit,
                     comm=comm, kcommsize=kcommsize)

        self.df_flag = False
        self.print_bootstrap = print_xc_scf
        self.df1_w = None  # NLF RPA
        self.df2_w = None  # LF RPA
        self.df3_w = None  # NLF ALDA
        self.df4_w = None  # LF ALDA

    def get_dielectric_matrix(self,
                              xc='RPA',
                              overwritechi0=False,
                              symmetric=True,
                              chi0_wGG=None,
                              calc=None,
                              vcut=None,
                              dir=None):
	if self.chi0_wGG is None and chi0_wGG is None:
            self.initialize()
            self.calculate()
        elif self.chi0_wGG is None and chi0_wGG is not None:
            #Read from file and reinitialize 
            self.xc = xc

            from gpaw.response.parallel import par_read 
            self.chi0_wGG = par_read(chi0_wGG, 'chi0_wGG')
            self.nvalbands = self.nbands
            #self.parallel_init() # parallelization not yet implemented
            self.Nw_local = self.Nw  # parallelization not yet implemented
            if self.calc is None:
                from gpaw import GPAW
                self.calc = GPAW(calc,txt=None)
            if self.xc == 'ALDA' or self.xc == 'ALDA_X':
                from gpaw.response.kernel import calculate_Kxc
                from gpaw.grid_descriptor import GridDescriptor
                from gpaw.mpi import world, rank, size, serial_comm
                    
                self.pbc = self.calc.atoms.pbc
                self.gd = GridDescriptor(self.calc.wfs.gd.N_c*self.rpad, self.acell_cv,
                                         pbc_c=True, comm=serial_comm)

                R_av = self.calc.atoms.positions / Bohr
                nt_sg = self.calc.density.nt_sG
                    
                if (self.rpad > 1).any() or (self.pbc - True).any():
                    nt_sG = self.gd.zeros(self.nspins)
                    #nt_sG = np.zeros([self.nspins, self.nG[0], self.nG[1], self.nG[2]])
                    for s in range(self.nspins):
                        nt_G = self.pad(nt_sg[s])
                        nt_sG[s] = nt_G
                else:
                    nt_sG = nt_sg
                        
                self.Kxc_sGG = calculate_Kxc(self.gd, 
                                             nt_sG,
                                             self.npw, self.Gvec_Gc,
                                             self.gd.N_c, self.vol,
                                             self.bcell_cv, R_av,
                                             self.calc.wfs.setups,
                                             self.calc.density.D_asp,
                                             functional=self.xc,
                                             density_cut=self.density_cut)

        if overwritechi0:
            dm_wGG = self.chi0_wGG
        else:
            dm_wGG = np.zeros_like(self.chi0_wGG)

        if dir is None:
            q_c = self.q_c
        else:
            q_c = np.diag((1,1,1))[dir] * self.qopt
            self.chi0_wGG[:,0,:] = self.chi00G_wGv[:,:,dir]
            self.chi0_wGG[:,:,0] = self.chi0G0_wGv[:,:,dir]
        
        from gpaw.response.kernel import calculate_Kc, CoulombKernel
        kernel = CoulombKernel(vcut=self.vcut,
                               pbc=self.calc.atoms.pbc,
                               cell=self.acell_cv)
        self.Kc_GG = kernel.calculate_Kc(q_c,
                                         self.Gvec_Gc,
                                         self.bcell_cv,
                                         symmetric=symmetric)
        #self.Kc_GG = calculate_Kc(q_c,
        #                          self.Gvec_Gc,
        #                          self.acell_cv,
        #                          self.bcell_cv,
        #                          self.pbc,
        #                          self.vcut,
        #                          symmetric=symmetric)

        tmp_GG = np.eye(self.npw, self.npw)

        if xc == 'RPA':
            self.printtxt('Use RPA.')
            for iw in range(self.Nw_local):
                dm_wGG[iw] = tmp_GG - self.Kc_GG * self.chi0_wGG[iw]
                
        elif xc == 'ALDA':
            self.printtxt('Use ALDA kernel.')
            # E_LDA = 1 - v_c chi0 (1-fxc chi0)^-1
            # http://prb.aps.org/pdf/PRB/v33/i10/p7017_1 eq. 4
            A_wGG = self.chi0_wGG.copy()
            for iw in range(self.Nw_local):
                A_wGG[iw] = np.dot(self.chi0_wGG[iw], np.linalg.inv(tmp_GG - np.dot(self.Kxc_sGG[0], self.chi0_wGG[iw])))
    
            for iw in range(self.Nw_local):
                dm_wGG[iw] = tmp_GG - self.Kc_GG * A_wGG[iw]                

        return dm_wGG


    def get_inverse_dielectric_matrix(self, xc='RPA'):

        dm_wGG = self.get_dielectric_matrix(xc=xc)
        dminv_wGG = np.zeros_like(dm_wGG)
        for iw in range(self.Nw_local):
            dminv_wGG[iw] = np.linalg.inv(dm_wGG[iw])
        return dminv_wGG


    def get_chi(self, xc='RPA'):
        """Solve Dyson's equation."""

	if self.chi0_wGG is None:
            self.initialize()
            self.calculate()
        else:
            pass # read from file and re-initializing .... need to be implemented

        kernel_GG = np.zeros((self.npw, self.npw), dtype=complex)
        chi_wGG = np.zeros_like(self.chi0_wGG)

        # Coulomb kernel
        for iG in range(self.npw):
            qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv)
            kernel_GG[iG,iG] = 4 * pi / np.dot(qG, qG)
            
        if xc == 'ALDA':
            kernel_GG += self.Kxc_sGG[0]

        for iw in range(self.Nw_local):
            tmp_GG = np.eye(self.npw, self.npw) - np.dot(self.chi0_wGG[iw], kernel_GG)
            chi_wGG[iw] = np.dot(np.linalg.inv(tmp_GG) , self.chi0_wGG[iw])

        return chi_wGG
    

    def get_dielectric_function(self, xc='RPA', dir=None):
        """Calculate the dielectric function. Returns df1_w and df2_w.

        Parameters:

        df1_w: ndarray
            Dielectric function without local field correction.
        df2_w: ndarray
            Dielectric function with local field correction.
        """

        if not self.optical_limit:
            assert dir is None
            
        if self.df_flag is False:
            dm_wGG = self.get_dielectric_matrix(xc=xc, dir=dir)

            Nw_local = dm_wGG.shape[0]
            dfNLF_w = np.zeros(Nw_local, dtype = complex)
            dfLFC_w = np.zeros(Nw_local, dtype = complex)
            df1_w = np.zeros(self.Nw, dtype = complex)
            df2_w = np.zeros(self.Nw, dtype = complex)

            for iw in range(Nw_local):
                tmp_GG = dm_wGG[iw]
                dfLFC_w[iw] = 1. / np.linalg.inv(tmp_GG)[0, 0]
                dfNLF_w[iw] = tmp_GG[0, 0]

            self.wcomm.all_gather(dfNLF_w, df1_w)
            self.wcomm.all_gather(dfLFC_w, df2_w)

            if xc == 'RPA':
                self.df1_w = df1_w
                self.df2_w = df2_w
            elif xc=='ALDA' or xc=='ALDA_X':
                self.df3_w = df1_w
                self.df4_w = df2_w                

        if xc == 'RPA':
            return self.df1_w, self.df2_w
        elif xc == 'ALDA' or xc=='ALDA_X':
            return self.df3_w, self.df4_w


    def get_surface_response_function(self, z0=0., filename='surf_EELS'):
        """Calculate surface response function."""

	if self.chi0_wGG is None:
            self.initialize()
            self.calculate()


        g_w2 = np.zeros((self.Nw,2), dtype=complex)
        assert self.acell_cv[0, 2] == 0. and self.acell_cv[1, 2] == 0.

        Nz = self.gd.N_c[2] # number of points in z direction
        tmp = np.zeros(Nz, dtype=int)
        nGz = 0         # number of G_z 
        for i in range(self.npw):
            if self.Gvec_Gc[i, 0] == 0 and self.Gvec_Gc[i, 1] == 0:
                tmp[nGz] = self.Gvec_Gc[i, 2]
                nGz += 1
        assert (np.abs(self.Gvec_Gc[:nGz, :2]) < 1e-10).all()

        for id, xc in enumerate(['RPA', 'ALDA']):
            chi_wGG = self.get_chi(xc=xc)
    
            # The first nGz are all Gx=0 and Gy=0 component
            chi_wgg_LFC = chi_wGG[:, :nGz, :nGz]
            del chi_wGG
            chi_wzz_LFC = np.zeros((self.Nw_local, Nz, Nz), dtype=complex)        
    
            # Fourier transform of chi_wgg to chi_wzz
            Gz_g = tmp[:nGz] * self.bcell_cv[2,2]
            z_z = np.linspace(0, self.acell_cv[2,2]-self.gd.h_cv[2,2], Nz)
            phase1_zg = np.exp(1j  * np.outer(z_z, Gz_g))
            phase2_gz = np.exp(-1j * np.outer(Gz_g, z_z))
    
            for iw in range(self.Nw_local):
                chi_wzz_LFC[iw] = np.dot(np.dot(phase1_zg, chi_wgg_LFC[iw]), phase2_gz)
            chi_wzz_LFC /= self.acell_cv[2,2]        
    
            # Get surface response function
    
            z_z -= z0 / Bohr
            q_v = np.dot(self.q_c, self.bcell_cv)
            qq = sqrt(np.inner(q_v, q_v))
            phase1_1z = np.array([np.exp(qq*z_z)])
            phase2_z1 = np.exp(qq*z_z)
    
            tmp_w = np.zeros(self.Nw_local, dtype=complex)        
            for iw in range(self.Nw_local):
                tmp_w[iw] = np.dot(np.dot(phase1_1z, chi_wzz_LFC[iw]), phase2_z1)[0]            
    
            tmp_w *= -2 * pi / qq * self.gd.h_cv[2,2]**2        
            g_w = np.zeros(self.Nw, dtype=complex)
            self.wcomm.all_gather(tmp_w, g_w)
            g_w2[:, id] = g_w
    
        if rank == 0:
            f = open(filename,'w')
            for iw in range(self.Nw):
                energy = iw * self.dw * Hartree
                print >> f, energy, np.imag(g_w2[iw, 0]), np.imag(g_w2[iw, 1])
            f.close()

        # Wait for I/O to finish
        self.comm.barrier()


    def check_sum_rule(self, df1_w=None, df2_w=None):
        """Check f-sum rule."""

	if df1_w is None:
            df1_w = self.df1_w
            df2_w = self.df2_w

        N1 = N2 = 0
        for iw in range(self.Nw):
            w = iw * self.dw
            N1 += np.imag(df1_w[iw]) * w
            N2 += np.imag(df2_w[iw]) * w
        N1 *= self.dw * self.vol / (2 * pi**2)
        N2 *= self.dw * self.vol / (2 * pi**2)

        self.printtxt('')
        self.printtxt('Sum rule for ABS:')
        nv = self.nvalence
        self.printtxt('Without local field: N1 = %f, %f  %% error' %(N1, (N1 - nv) / nv * 100) )
        self.printtxt('Include local field: N2 = %f, %f  %% error' %(N2, (N2 - nv) / nv * 100) )

        N1 = N2 = 0
        for iw in range(self.Nw):
            w = iw * self.dw
            N1 -= np.imag(1/df1_w[iw]) * w
            N2 -= np.imag(1/df2_w[iw]) * w
        N1 *= self.dw * self.vol / (2 * pi**2)
        N2 *= self.dw * self.vol / (2 * pi**2)
                
        self.printtxt('')
        self.printtxt('Sum rule for EELS:')
        nv = self.nvalence
        self.printtxt('Without local field: N1 = %f, %f  %% error' %(N1, (N1 - nv) / nv * 100) )
        self.printtxt('Include local field: N2 = %f, %f  %% error' %(N2, (N2 - nv) / nv * 100) )


    def get_macroscopic_dielectric_constant(self, xc='RPA'):
        """Calculate macroscopic dielectric constant. Returns eM1 and eM2

        Macroscopic dielectric constant is defined as the real part of dielectric function at w=0.
        
        Parameters:

        eM1: float
            Dielectric constant without local field correction. (RPA, ALDA)
        eM2: float
            Dielectric constant with local field correction.

        """

        assert self.optical_limit
        self.printtxt('')
        self.printtxt('%s Macroscopic Dielectric Constant:' % xc)
        dirstr = ['x', 'y', 'z']

        for dir in range(3):
        
            eM = np.zeros(2)
            df1, df2 = self.get_dielectric_function(xc=xc, dir=dir)
            eps0 = np.real(df1[0])
            eps = np.real(df2[0])
            self.printtxt('  %s direction' %(dirstr[dir]))
            self.printtxt('    Without local field: %f' % eps0 )
            self.printtxt('    Include local field: %f' % eps )        
            
        return eps0, eps


    def get_absorption_spectrum(self, filename='Absorption.dat'):
        """Calculate optical absorption spectrum. By default, generate a file 'Absorption.dat'.

        Optical absorption spectrum is obtained from the imaginary part of dielectric function.
        """

        assert self.optical_limit
        for dir in range(3):
            df1, df2 = self.get_dielectric_function(xc='RPA', dir=dir)
            if self.xc == 'ALDA':
                df3, df4 = self.get_dielectric_function(xc='ALDA', dir=dir)
            if self.xc is 'ALDA_X':
                df3, df4 = self.get_dielectric_function(xc='ALDA_X', dir=dir)
    
            Nw = df1.shape[0]
    
            if self.xc == 'Bootstrap':
                # bootstrap doesnt support all direction spectra yet
                from gpaw.response.fxc import Bootstrap
                Kc_GG = np.zeros((self.npw, self.npw))
                q_c = np.diag((1, 1, 1))[dir] * self.qopt

                for iG in range(self.npw):
                    qG = np.dot(q_c + self.Gvec_Gc[iG], self.bcell_cv)
                    Kc_GG[iG,iG] = 4 * pi / np.dot(qG, qG)
    
                from gpaw.mpi import world
                assert self.wcomm.size == world.size
                df3 = Bootstrap(self.chi0_wGG, Nw, Kc_GG, self.printtxt, self.print_bootstrap, self.wcomm)
    
            if rank == 0:
                f = open('%s.%s' % (filename, 'xyz'[dir]), 'w')
                #f = open(filename+'.%s'%(dirstr[dir]),'w') # ????
                for iw in range(Nw):
                    energy = iw * self.dw * Hartree
                    if self.xc == 'RPA':
                        print >> f, energy, np.real(df1[iw]), np.imag(df1[iw]), \
                              np.real(df2[iw]), np.imag(df2[iw])
                    elif self.xc == 'ALDA':
                        print >> f, energy, np.real(df1[iw]), np.imag(df1[iw]), \
                          np.real(df2[iw]), np.imag(df2[iw]), \
                          np.real(df3[iw]), np.imag(df3[iw]), \
                          np.real(df4[iw]), np.imag(df4[iw])
                    elif self.xc == 'Bootstrap':
                        print >> f, energy, np.real(df1[iw]), np.imag(df1[iw]), \
                          np.real(df2[iw]), np.imag(df2[iw]), \
                          np.real(df3[iw]), np.imag(df3[iw])
                f.close()
    
            # Wait for I/O to finish
            self.comm.barrier()


    def get_EELS_spectrum(self, filename='EELS.dat'):
        """Calculate EELS spectrum. By default, generate a file 'EELS.dat'.

        EELS spectrum is obtained from the imaginary part of the inverse of dielectric function.
        """

        # calculate RPA dielectric function
        df1, df2 = self.get_dielectric_function(xc='RPA')
        if self.xc == 'ALDA':
            df3, df4 = self.get_dielectric_function(xc='ALDA')
        Nw = df1.shape[0]

        if rank == 0:
            f = open(filename,'w')
            for iw in range(self.Nw):
                energy = iw * self.dw * Hartree
                if self.xc == 'RPA':
                    print >> f, energy, -np.imag(1./df1[iw]), -np.imag(1./df2[iw])
                elif self.xc == 'ALDA':
                    print >> f, energy, -np.imag(1./df1[iw]), -np.imag(1./df2[iw]), \
                       -np.imag(1./df3[iw]), -np.imag(1./df4[iw])
            f.close()

        # Wait for I/O to finish
        self.comm.barrier()


    def get_jdos(self, f_skn, e_skn, kd, kq, dw, Nw, sigma):
        """Calculate Joint density of states"""

        JDOS_w = np.zeros(Nw)
        nbands = f_skn[0].shape[1]

        for k in range(kd.nbzkpts):
            print k
            ibzkpt1 = kd.bz2ibz_k[k]
            ibzkpt2 = kd.bz2ibz_k[kq[k]]
            for n in range(nbands):
                for m in range(nbands):
                    focc = f_skn[0][ibzkpt1, n] - f_skn[0][ibzkpt2, m]
                    w0 = e_skn[0][ibzkpt2, m] - e_skn[0][ibzkpt1, n]
                    if focc > 0 and w0 >= 0:
                        w0_id = int(w0 / dw)
                        if w0_id + 1 < Nw:
                            alpha = (w0_id + 1 - w0/dw) / dw
                            JDOS_w[w0_id] += focc * alpha
                            alpha = (w0/dw-w0_id) / dw
                            JDOS_w[w0_id+1] += focc * alpha
                            
        w = np.arange(Nw) * dw * Hartree

        return w, JDOS_w


    def calculate_induced_density(self, q, w):
        """ Evaluate induced density for a certain q and w.

        Parameters:

        q: ndarray
            Momentum tranfer at reduced coordinate.
        w: scalar
            Energy (eV).
        """

        if type(w) is int:
            iw = w
            w = self.wlist[iw] / Hartree
        elif type(w) is float:
            w /= Hartree
            iw = int(np.round(w / self.dw))
        else:
            raise ValueError('Frequency not correct !')

        self.printtxt('Calculating Induced density at q, w (iw)')
        self.printtxt('(%f, %f, %f), %f(%d)' %(q[0], q[1], q[2], w*Hartree, iw))

        # delta_G0
        delta_G = np.zeros(self.npw)
        delta_G[0] = 1.

        # coef is (q+G)**2 / 4pi
        coef_G = np.zeros(self.npw)
        for iG in range(self.npw):
            qG = np.dot(q + self.Gvec_Gc[iG], self.bcell_cv)
            coef_G[iG] = np.dot(qG, qG)
        coef_G /= 4 * pi

        # obtain chi_G0(q,w)
        dm_wGG = self.get_RPA_dielectric_matrix()
        tmp_GG = dm_wGG[iw]
        del dm_wGG
        chi_G = (np.linalg.inv(tmp_GG)[:, 0] - delta_G) * coef_G

        gd = self.gd
        r = gd.get_grid_point_coordinates()

        # calculate dn(r,q,w)
        drho_R = gd.zeros(dtype=complex)
        for iG in range(self.npw):
            qG = np.dot(q + self.Gvec_Gc[iG], self.bcell_cv)
            qGr_R = np.inner(qG, r.T).T
            drho_R += chi_G[iG] * np.exp(1j * qGr_R)

        # phase = sum exp(iq.R_i)
        return drho_R


    def get_induced_density_z(self, q, w):
        """Get induced density on z axis (summation over xy-plane). """

        drho_R = self.calculate_induced_density(q, w)

        drho_z = np.zeros(self.gd.N_c[2],dtype=complex)
#        dxdy = np.cross(self.h_c[0], self.h_c[1])

        for iz in range(self.gd.N_c[2]):
            drho_z[iz] = drho_R[:,:,iz].sum()

        return drho_z

    def get_eigenmodes(self,filename = None, chi0 = None, calc = None, dm = None, 
                       xc = 'RPA', sum = None, vcut = None, checkphase = False, 
                       return_full = False):
        """
        Calculate the plasmonic eigenmodes as eigenvectors of the dielectric matrix.  

        Parameters:

        filename:  pckl file
                   output from response calculation.
         
        chi0:  gpw file
               chi0_wGG from response calculation.

        calc:  gpaw calculator instance
               ground state calculator used in response calculation.
               Wavefunctions only needed if chi0 is calculated from scratch

        dm:  gpw file
             dielectric matrix from response calculation

        xc:  str 'RPA'or 'ALDA' XC- Kernel
        
        sum:  str
              '2D': sum in the x and y directions
              '1D': To be implemented

        vcut:  str '0D','1D' or '2D'
               Cut the Coulomb potential 

        checkphase:   Bool
                      if True, the eigenfunctions id rotated in the complex
                      plane, to be made as real as posible

        return_full:  Bool
                      if True, the eigenvectors in reciprocal space is also
                      returned. 
           
        """
        self.read(filename)
        self.pbc = [1,1,1]
        #self.calc.atoms.pbc = [1,1,1]
        npw = self.npw
        self.w_w = np.linspace(0, self.dw * (self.Nw - 1)*Hartree, self.Nw)
        self.vcut = vcut
        dm_wGG = self.get_dielectric_matrix(xc=xc,
                                            symmetric=False,
                                            chi0_wGG=chi0,
                                            calc=calc,
                                            vcut=vcut)
    
        q = self.q_c
        

        # get grid on which the eigenmodes are calculated
        #gd = self.calc.wfs.gd
        #r = gd.get_grid_point_coordinates()
        #rrr = r*Bohr 
        from gpaw.utilities.gpts import get_number_of_grid_points
        from gpaw.grid_descriptor import GridDescriptor
        grid_size = [1,1,1]
        h=0.2
        cell_cv = self.acell_cv*np.diag(grid_size)
        mode = 'fd'
        realspace = True
        h /= Bohr
        N_c = get_number_of_grid_points(cell_cv, h, mode, realspace)
        gd = GridDescriptor(N_c, cell_cv, self.pbc) 
        #gd = self.calc.wfs.gd
        r = gd.get_grid_point_coordinates()
        rrr = r*Bohr
        
        eig_0 = np.array([], dtype = complex)
        eig_left = np.array([], dtype = complex)
        eig_right = np.array([], dtype = complex)
        vec_modes = np.zeros([1, self.npw], dtype = complex)
        vec_modes_dual = np.zeros([1, self.npw], dtype = complex)
        vec_modes_density = np.zeros([1, self.npw], dtype = complex)
        vec_modes_norm = np.zeros([1, self.npw], dtype = complex)
        eig_all = np.zeros([1, self.npw], dtype = complex)
        eig_dummy = np.zeros([1, self.npw], dtype = complex)
        v_dummy = np.zeros([1, self.npw], dtype = complex)
        vec_dummy = np.zeros([1, self.npw], dtype = complex)
        vec_dummy2 = np.zeros([1, self.npw], dtype = complex)
        w_0 = np.array([]) 
        w_left = np.array([])
        w_right = np.array([])
     
        if sum == '2D':
            v_ind = np.zeros([1, r.shape[-1]], dtype = complex)
            n_ind = np.zeros([1, r.shape[-1]], dtype = complex)
        elif sum == '1D':            
            self.printtxt('1D sum not implemented')
            return 
        else:
            v_ind = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype = complex)
            n_ind = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype = complex)

        eps_GG_plus = dm_wGG[0]
        eig_plus, vec_plus = np.linalg.eig(eps_GG_plus)  # find eigenvalues and eigenvectors
        vec_plus_dual = np.linalg.inv(vec_plus)
        
        # loop over frequencies, where the eigenvalues for the 2D matrix in G,G' are found.
        for i in np.array(range(self.Nw-1))+1:
            eps_GG = eps_GG_plus
            eig, vec = eig_plus,vec_plus
            vec_dual = vec_plus_dual
            eps_GG_plus = dm_wGG[i] # epsilon_GG'(omega + d-omega)
            eig_plus, vec_plus = np.linalg.eig(eps_GG_plus)
            vec_plus_dual = np.linalg.inv(vec_plus)
            eig_dummy[0,:] = eig
            eig_all = np.append(eig_all, eig_dummy, axis=0) # append all eigenvalues to array         
            # loop to check find the eigenvalues that crosses zero from negative to positive values:
            for k in range(self.npw):
                for m in range(self.npw):
                    if eig[k]< 0 and 0 < eig_plus[m]:
                        # check it's the same mode - Overlap between eigenvectors should be large:
                        if abs(np.inner(vec[:,k], vec_plus_dual[m,:])) > 0.95:                             
                            self.printtxt('crossing found at w = %1.1f eV'%self.w_w[i-1])
                            eig_left = np.append(eig_left, eig[k])   
                            eig_right = np.append(eig_right, eig_plus[m])

                            vec_dummy[0, :] = vec[:,k]
                            vec_modes = np.append(vec_modes, vec_dummy, axis = 0)
                            vec_dummy[0, :] = vec_dual[k, :].T
                            vec_modes_dual = np.append(vec_modes_dual, vec_dummy, axis = 0)
                                                   
                            w1 = self.w_w[i-1]
                            w2 = self.w_w[i]
                            a = np.real((eig_plus[m]-eig[k]) / (w2-w1))
                            w0 = np.real(-eig[k]) / a + w1
                            eig0 = a*(w0-w1)+eig[k]

                            w_0 = np.append(w_0,w0)
                            w_left = np.append(w_left, w1)
                            eig_0 = np.append(eig_0,eig0)                           

                            n_dummy = np.zeros([1, r.shape[1], r.shape[2],
                                                r.shape[3]], dtype = complex)
                            v_dummy = np.zeros([1, r.shape[1], r.shape[2],
                                                r.shape[3]], dtype = complex)    

                            vec_n = np.zeros([self.npw])
                            
                            for iG in range(self.npw):  # Fourier transform
                                qG = np.dot((q + self.Gvec_Gc[iG]), self.bcell_cv)
                                coef_G = np.dot(qG, qG) / (4 * pi)
                                qGr_R = np.inner(qG, r.T).T
                                v_dummy += vec[iG, k] * np.exp(1j * qGr_R) 
                                n_dummy += vec[iG, k] * np.exp(1j * qGr_R) * coef_G
                                                        
                            if checkphase: # rotate eigenvectors in complex plane 
                                integral = np.zeros([81])
                                phases = np.linspace(0,2,81)
                                for ip in range(81):
                                    v_int = v_dummy * np.exp(1j * pi * phases[ip])
                                    integral[ip] = abs(np.imag(v_int)).sum()                                     
                                phase = phases[np.argsort(integral)][0]
                                
                                v_dummy *= np.exp(1j * pi * phase)
                                n_dummy *= np.exp(1j * pi * phase)
                                

                            if sum == '2D':
                                i_xyz = 3 
                                v_dummy_z = np.zeros([1,v_dummy.shape[i_xyz]],
                                                     dtype = complex)
                                n_dummy_z = np.zeros([1,v_dummy.shape[i_xyz]],
                                                     dtype = complex)
                                v_dummy_z[0,:] = np.sum(np.sum(v_dummy, axis = 1),
                                                        axis = 1)[0,:]
                                n_dummy_z[0,:] = np.sum(np.sum(n_dummy, axis = 1),
                                                        axis = 1)[0,:]

                                v_ind = np.append(v_ind, v_dummy_z, axis=0)
                                n_ind = np.append(n_ind, n_dummy_z, axis=0)
                                                    
                            elif sum == '1D':
                                self.printtxt('1D sum not implemented')
                            else :
                                v_ind = np.append(v_ind, v_dummy, axis=0)
                                n_ind = np.append(n_ind, n_dummy, axis=0)
            
        """                        
        returns: grid points, frequency grid, all eigenvalues, mode energies, left point energies,
                 mode eigenvalues, eigenvalues of left and right-side points,
                 (mode eigenvectors, mode dual eigenvectors,)
                 induced potential in real space, induced density in real space
        """
        
        if return_full:
            return rrr, self.w_w, eig_all[1:], w_0, eig_0, w_left, eig_left, \
               eig_right, vec_modes[1:], vec_modes_dual[1:], v_ind[1:], n_ind[1:]
            
        else:
            return rrr, self.w_w, eig_all[1:], w_0, eig_0, w_left, eig_left, \
               eig_right, v_ind[1:], n_ind[1:]
                        
        
    def project_chi_to_LCAO_pair_orbital(self, orb_MG):

        nLCAO = orb_MG.shape[0]
        N = np.zeros((self.Nw, nLCAO, nLCAO), dtype=complex)

        kcoulinv_GG = np.zeros((self.npw, self.npw))
        for iG in range(self.npw):
            qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv)
            kcoulinv_GG[iG, iG] = np.dot(qG, qG)

        kcoulinv_GG /= 4.*pi

        dm_wGG = self.get_RPA_dielectric_matrix()

        for mu in range(nLCAO):
            for nu in range(nLCAO):
                pairorb_R = orb_MG[mu] * orb_MG[nu]
                if not (pairorb_R * pairorb_R.conj() < 1e-10).all():
                    tmp_G = np.fft.fftn(pairorb_R) * self.vol / self.nG0

                    pairorb_G = np.zeros(self.npw, dtype=complex)
                    for iG in range(self.npw):
                        index = self.Gindex[iG]
                        pairorb_G[iG] = tmp_G[index[0], index[1], index[2]]

                    for iw in range(self.Nw):
                        chi_GG = (dm_wGG[iw] - np.eye(self.npw)) * kcoulinv_GG
                        N[iw, mu, nu] = (np.outer(pairorb_G.conj(), pairorb_G) * chi_GG).sum()
#                        N[iw, mu, nu] = np.inner(pairorb_G.conj(),np.inner(pairorb_G, chi_GG))

        return N


    def write(self, filename, all=False):
        """Dump essential data"""

        data = {'nbands': self.nbands,
                'acell': self.acell_cv, #* Bohr,
                'bcell': self.bcell_cv, #/ Bohr,
                'h_cv' : self.gd.h_cv,   #* Bohr,
                'nG'   : self.gd.N_c,
                'nG0'  : self.nG0,
                'vol'  : self.vol,   #* Bohr**3,
                'BZvol': self.BZvol, #/ Bohr**3,
                'nkpt' : self.kd.nbzkpts,
                'ecut' : self.ecut,  #* Hartree,
                'npw'  : self.npw,
                'eta'  : self.eta,   #* Hartree,
                'ftol' : self.ftol,
                'Nw'   : self.Nw,
                'NwS'  : self.NwS,
                'dw'   : self.dw,    # * Hartree,
                'q_red': self.q_c,
                'q_car': self.qq_v,    # / Bohr,
                'qmod' : np.dot(self.qq_v, self.qq_v), # / Bohr
                'vcut' : self.vcut,
                'pbc'  : self.pbc,
                'nvalence'     : self.nvalence,                
                'hilbert_trans' : self.hilbert_trans,
                'optical_limit' : self.optical_limit,
                'e_skn'         : self.e_skn,          # * Hartree,
                'f_skn'         : self.f_skn,
                'bzk_kc'       : self.kd.bzk_kc,
                'ibzk_kc'      : self.kd.ibzk_kc,
                'kq_k'         : self.kq_k,
                'Gvec_Gc'      : self.Gvec_Gc,
                'dfNLFRPA_w'   : self.df1_w,
                'dfLFCRPA_w'   : self.df2_w,
                'dfNLFALDA_w'  : self.df3_w,
                'dfLFCALDA_w'  : self.df4_w,
                'df_flag'      : True}

        if all:
            from gpaw.response.parallel import par_write
            par_write('chi0' + filename,'chi0_wGG',self.wcomm,self.chi0_wGG)
        
        if rank == 0:
            pickle.dump(data, open(filename, 'w'), -1)

        self.comm.barrier()


    def read(self, filename):
        """Read data from pickle file"""

        data = pickle.load(open(filename))
        
        self.nbands = data['nbands']
        self.acell_cv = data['acell']
        self.bcell_cv = data['bcell']
        self.nG0   = data['nG0']
        self.vol   = data['vol']
        self.BZvol = data['BZvol']
        self.ecut  = data['ecut']
        self.npw   = data['npw']
        self.eta   = data['eta']
        self.ftol  = data['ftol']
        self.Nw    = data['Nw']
        self.NwS   = data['NwS']
        self.dw    = data['dw']
        self.q_c   = data['q_red']
        self.qq_v  = data['q_car']
        self.qmod  = data['qmod']
        #self.vcut  = data['vcut']
        #self.pbc = data['pbc']
        
        self.hilbert_trans = data['hilbert_trans']
        self.optical_limit = data['optical_limit']
      
        self.e_skn  = data['e_skn']
        self.f_skn  = data['f_skn']
                
        self.nvalence= data['nvalence']
        self.kq_k    = data['kq_k']
        self.Gvec_Gc  = data['Gvec_Gc']
        self.df1_w   = data['dfNLFRPA_w']
        self.df2_w   = data['dfLFCRPA_w']
        self.df3_w   = data['dfNLFALDA_w']
        self.df4_w   = data['dfLFCALDA_w']
        self.df_flag = data['df_flag']
        
        self.printtxt('Read succesfully !')
Example #45
0
from gpaw.fd_operators import Gradient
import numpy as np
from gpaw.grid_descriptor import GridDescriptor
from gpaw.mpi import world

if world.size > 4:
    # Grid is so small that domain decomposition cannot exceed 4 domains
    assert world.size % 4 == 0
    group, other = divmod(world.rank, 4)
    ranks = np.arange(4*group, 4*(group+1))
    domain_comm = world.new_communicator(ranks)
else:
    domain_comm = world

gd = GridDescriptor((8, 1, 1), (8.0, 1.0, 1.0), comm=domain_comm)
a = gd.zeros()
dadx = gd.zeros()
a[:, 0, 0] = np.arange(gd.beg_c[0], gd.end_c[0])
gradx = Gradient(gd, v=0)
print a.itemsize, a.dtype, a.shape
print dadx.itemsize, dadx.dtype, dadx.shape
gradx.apply(a, dadx)

#   a = [ 0.  1.  2.  3.  4.  5.  6.  7.]
#
#   da
#   -- = [-2.5  1.   1.   1.   1.   1.  1.  -2.5]
#   dx

dadx = gd.collect(dadx, broadcast=True)
assert dadx[3, 0, 0] == 1.0 and np.sum(dadx[:, 0, 0]) == 0.0
assert np.prod(D) * B == world.size, 'D=%s, B=%d, W=%d' % (D,B,world.size)

# Set up communicators:
comms = distribute_cpus(parsize_domain=D,
                        parsize_bands=B,
                        nspins=1, nibzkpts=1)
domain_comm, kpt_comm, band_comm, block_comm = \
    [comms[name] for name in ['d', 'k', 'b', 'K']]

assert kpt_comm.size == 1
if world.rank == 0:
    print('MPI: %d domains, %d band groups' % (domain_comm.size, band_comm.size))

# Set up band and grid descriptors:
bd = BandDescriptor(N, band_comm, False)
gd = GridDescriptor((G, G, G), (a, a, a), True, domain_comm, parsize=D)
ksl = BandLayouts(gd, bd, block_comm, float)

# Random wave functions:
psit_mG = gd.empty(M)
for m in range(M):
    np.random.seed(world.rank * M + m)
    psit_mG[m] = np.random.uniform(-0.5, 0.5, tuple(gd.n_c))
if world.rank == 0:
    print('Size of wave function array:', psit_mG.shape)
P_ani = {0: psit_mG[:, :2, 0, 0].copy(),
         1: psit_mG[:, -1, -1, -3:].copy()}

kin = Laplace(gd, -0.5, 2).apply
vt_G = gd.empty()
vt_G.fill(0.567)
from time import time
import numpy as np
from gpaw.mpi import world, size, rank
from gpaw.utilities.blas import gemm
from gpaw.mic.micblas import gemm as mic_gemm
import pymic
import sys

device = pymic.devices[0]
stream = device.get_default_stream()

gpts = int(sys.argv[1])
nbands = int(sys.argv[2])
repeats = 10

gd = GridDescriptor([gpts, gpts, gpts], comm=world, parsize=size)

a = gd.empty(nbands)
b = gd.empty(nbands)

np.random.seed(10)
a[:] = np.random.random(a.shape)
b[:] = np.random.random(b.shape)
c = np.zeros((nbands, nbands))

# warm-up
for i in range(3):
    gd.integrate(a, b, hermitian=False, _transposed_result=c)
    gemm(1.0, a, c, 0.0, b)
# equal(np.sum(c), 3600.89536641, 1e-6)
t0 = time()
Example #48
0
from gpaw.test import equal
from gpaw.grid_descriptor import GridDescriptor
from gpaw.spline import Spline
import gpaw.mpi as mpi
from gpaw.lfc import LocalizedFunctionsCollection as LFC

s = Spline(0, 1.0, [1.0, 0.5, 0.0])
n = 40
a = 8.0
gd = GridDescriptor((n, n, n), (a, a, a), comm=mpi.serial_comm)
c = LFC(gd, [[s], [s], [s]])
c.set_positions([(0.5, 0.5, 0.25 + 0.25 * i) for i in [0, 1, 2]])
b = gd.zeros()
c.add(b)
x = gd.integrate(b)

gd = GridDescriptor((n, n, n), (a, a, a), comm=mpi.serial_comm)
c = LFC(gd, [[s], [s], [s]])
c.set_positions([(0.5, 0.5, 0.25 + 0.25 * i) for i in [0, 1, 2]])
b = gd.zeros()
c.add(b)
y = gd.integrate(b)
equal(x, y, 1e-13)
Example #49
0
import numpy as np
from gpaw.lfc import LocalizedFunctionsCollection as LFC
from gpaw.grid_descriptor import GridDescriptor
from gpaw.spline import Spline
a = 4.0
gd = GridDescriptor(N_c=[16, 20, 20], cell_cv=[a, a + 1, a + 2],
                    pbc_c=(0, 1, 1))
spos_ac = np.array([[0.25, 0.15, 0.35], [0.5, 0.5, 0.5]])
kpts_kc = None
s = Spline(l=0, rmax=2.0, f_g=np.array([1, 0.9, 0.1, 0.0]))
p = Spline(l=1, rmax=2.0, f_g=np.array([1, 0.9, 0.1, 0.0]))
spline_aj = [[s], [s, p]]
c = LFC(gd, spline_aj, cut=True, forces=True)
c.set_positions(spos_ac)
C_ani = c.dict(3, zero=True)
if 1 in C_ani:
    C_ani[1][:, 1:] = np.eye(3)
psi = gd.zeros(3)
c.add(psi, C_ani)
c.integrate(psi, C_ani)
if 1 in C_ani:
    d = C_ani[1][:, 1:].diagonal()
    assert d.ptp() < 4e-6
    C_ani[1][:, 1:] -= np.diag(d)
    assert abs(C_ani[1]).max() < 5e-17
d_aniv = c.dict(3, derivative=True)
c.derivative(psi, d_aniv)
if 1 in d_aniv:
    for v in range(3):
        assert abs(d_aniv[1][v - 1, 0, v] + 0.2144) < 5e-5
        d_aniv[1][v - 1, 0, v] = 0
Example #50
0
from gpaw.grid_descriptor import GridDescriptor
from gpaw.fd_operators import Laplace
from gpaw.test import equal
import numpy as np
import time
import timeit
import os

import pyMIC as mic

offload_enabled = os.environ.get("GPAW_OFFLOAD");

device = mic.devices[0]

gpts = 64
gd = GridDescriptor([gpts, gpts, gpts])

a = gd.empty() # source
b = gd.empty() # result

np.random.seed(10)
a[:] = np.random.random(a.shape)
b[:] = np.zeros(b.shape)

op = Laplace(gd, 1.0, 3)

if offload_enabled:
    offl_a = device.bind(a)
    offl_b = device.bind(b)

print "--------------------------------------------------------------"
from gpaw.utilities.gauss import Gaussian
from gpaw.grid_descriptor import GridDescriptor
from gpaw.test import equal
from gpaw.mpi import world
from gpaw.poisson import PoissonSolver


def norm(a):
    return np.sqrt(np.sum(a.ravel() ** 2)) / len(a.ravel())


# Initialize classes
a = 20  # Size of cell
N = 48  # Number of grid points
Nc = (N, N, N)  # Number of grid points along each axis
gd = GridDescriptor(Nc, (a, a, a), 0)  # Grid-descriptor object
solver = PoissonSolver(nn=3)  # Numerical poisson solver
solver.set_grid_descriptor(gd)
solver.initialize()
solve = solver.solve
xyz, r2 = coordinates(gd)  # Matrix with the square of the radial coordinate
print(r2.shape)
r = np.sqrt(r2)  # Matrix with the values of the radial coordinate
nH = np.exp(-2 * r) / pi  # Density of the hydrogen atom
gauss = Gaussian(gd)  # An instance of Gaussian

# /------------------------------------------------\
# | Check if Gaussian densities are made correctly |
# \------------------------------------------------/
for gL in range(2, 9):
    g = gauss.get_gauss(gL)  # a gaussian of gL'th order
from math import pi
from gpaw.grid_descriptor import GridDescriptor
from gpaw.xc import XC
from gpaw.xc.noncollinear import NonCollinearLDAKernel, NonCollinearFunctional
import numpy as np
from gpaw.test import equal

N = 20
a = 1.0
gd = GridDescriptor((N, N, N), (a, a, a))

for xc in [XC('LDA'), XC('PBE')]:
    n = gd.empty(2)
    n.fill(0.03)
    z = np.arange(gd.beg_c[2], gd.end_c[2]) * a / N
    n[:] += 0.01 * np.sin(2 * pi * z / a)
    n[1] += 0.02 + 0.01 * np.cos(2 * pi * z / a)
    n /= 2

    v = 0.0 * n
    E = xc.calculate(gd, n, v)

    here = (gd.beg_c[0] <= 1 < gd.end_c[0] and
            gd.beg_c[1] <= 2 < gd.end_c[1] and
            gd.beg_c[2] <= 3 < gd.end_c[2])
    if here:
        x = v[-1, 1, 2, 3] * gd.dv
        n[-1, 1, 2, 3] += 0.000001
    Ep = xc.calculate(gd, n, v)
    if here:
        n[-1, 1, 2, 3] -= 0.000002
Example #53
0
    def abstract_boundary(self):
        # Abtract the effective potential, hartree potential, and average density
        #out from the electrode calculation.
        map = {'-': '0', '+': '1'}
	data = self.tio.read_data(filename='Lead_' + 
	                          map[self.direction], option='Lead')
        nn = data['fine_N_c'][2]
	ns = data['nspins']
        N_c = data['N_c']
	cell_cv = data['cell_cv']
	pbc_c = data['pbc_c']
	#parsize_c = data['parsize_c']
        if type(parsize_domain) is int:
            parsize_c = None
            assert parsize_domain == self.domain_comm.size
        else:
            parsize_c = parsize_domain
        if parsize_c is None:
            parsize_c = decompose_domain(N_c, self.domain_comm.size)
        parsize_c = np.array(parsize_c)
        d1 = N_c[0] // 2
        d2 = N_c[1] // 2
       
        vHt_g = data['vHt_g']
        vt_sg = data['vt_sg']
        nt_sg = data['nt_sg']
        rhot_g = data['rhot_g']
        vt_sG = data['vt_sG']
        nt_sG = data['nt_sG']
        self.D_asp = data['D_asp']
	self.dH_asp = data['dH_asp']
        gd = GridDescriptor(N_c, cell_cv, pbc_c, self.domain_comm, parsize_c)
	finegd = gd.refine()
	
        self.boundary_vHt_g = None
        self.boundary_vHt_g1 = None
        self.boundary_vt_sg_line = None
        self.boundary_nt_sg = None
        self.boundary_rhot_g_line = None
        self.boundary_vt_sG = None
        self.boundary_nt_sG = None

        if self.tio.domain_comm.rank == 0:
            self.boundary_vHt_g = self.slice(nn, vHt_g)
            self.boundary_nt_sg = self.slice(nn, nt_sg)
            if self.direction == '-':
                other_direction= '+'
            else:
                other_direction= '-'
            h = self.h_cz / 2.0
            b_vHt_g0 = self.boundary_vHt_g.copy()
            b_vHt_g1 = self.boundary_vHt_g.copy()

            self.boundary_vHt_g = interpolate_array(b_vHt_g0,
                                                    finegd, h, 
						    self.direction)
            self.boundary_vHt_g1 = interpolate_array(b_vHt_g1,
                                                     finegd, h, 
						     other_direction)
            vt_sg = interpolate_array(vt_sg, finegd, 
	                              h, self.direction)
            self.boundary_vt_sg_line =  aa1d(vt_sg)
            self.boundary_nt_sg = interpolate_array(self.boundary_nt_sg,
                                                    finegd, h, self.direction)
            rhot_g = interpolate_array(rhot_g, finegd, h, self.direction)
            self.boundary_rhot_g_line = aa1d(rhot_g)

            nn /= 2
            h *= 2
            self.boundary_vt_sG = self.slice(nn, vt_sG)
            self.boundary_nt_sG = self.slice(nn, nt_sG)
            self.boundary_vt_sG = interpolate_array(self.boundary_vt_sG,
                                                    gd, h, self.direction)
            self.boundary_nt_sG = interpolate_array(self.boundary_nt_sG,
                                                    gd, h, self.direction)

if size == 1:
    for name, D, cell in cells:
        if name == 'Jelver':
            # Strange one!
            continue
            
        print('------------------')
        print(name, D)
        print(cell[0])
        print(cell[1])
        print(cell[2])
        for n in range(1, 6):
            N = 2 * n + 2
            gd = GridDescriptor((N, N, N), cell)
            b_g = gd.zeros()
            r_gv = gd.get_grid_point_coordinates().transpose((1, 2, 3, 0))
            c_v = gd.cell_cv.sum(0) / 2
            r_gv -= c_v
            lap = Laplace(gd, n=n)
            grad_v = [Gradient(gd, v, n=n) for v in range(3)]
            assert lap.npoints == D * 2 * n + 1
            for m in range(0, 2 * n + 1):
                for ix in range(m + 1):
                    for iy in range(m - ix + 1):
                        iz = m - ix - iy
                        a_g = (r_gv**(ix, iy, iz)).prod(3)
                        if ix + iy + iz == 2 and max(ix, iy, iz) == 2:
                            r = 2.0
                        else:
Example #55
0
    def get_eigenmodes(self,filename = None, chi0 = None, calc = None, dm = None, 
                       xc = 'RPA', sum = None, vcut = None, checkphase = False, 
                       return_full = False):
        """
        Calculate the plasmonic eigenmodes as eigenvectors of the dielectric matrix.  

        Parameters:

        filename:  pckl file
                   output from response calculation.
         
        chi0:  gpw file
               chi0_wGG from response calculation.

        calc:  gpaw calculator instance
               ground state calculator used in response calculation.
               Wavefunctions only needed if chi0 is calculated from scratch

        dm:  gpw file
             dielectric matrix from response calculation

        xc:  str 'RPA'or 'ALDA' XC- Kernel
        
        sum:  str
              '2D': sum in the x and y directions
              '1D': To be implemented

        vcut:  str '0D','1D' or '2D'
               Cut the Coulomb potential 

        checkphase:   Bool
                      if True, the eigenfunctions id rotated in the complex
                      plane, to be made as real as posible

        return_full:  Bool
                      if True, the eigenvectors in reciprocal space is also
                      returned. 
           
        """
        self.read(filename)
        self.pbc = [1,1,1]
        #self.calc.atoms.pbc = [1,1,1]
        npw = self.npw
        self.w_w = np.linspace(0, self.dw * (self.Nw - 1)*Hartree, self.Nw)
        self.vcut = vcut
        dm_wGG = self.get_dielectric_matrix(xc=xc,
                                            symmetric=False,
                                            chi0_wGG=chi0,
                                            calc=calc,
                                            vcut=vcut)
    
        q = self.q_c
        

        # get grid on which the eigenmodes are calculated
        #gd = self.calc.wfs.gd
        #r = gd.get_grid_point_coordinates()
        #rrr = r*Bohr 
        from gpaw.utilities.gpts import get_number_of_grid_points
        from gpaw.grid_descriptor import GridDescriptor
        grid_size = [1,1,1]
        h=0.2
        cell_cv = self.acell_cv*np.diag(grid_size)
        mode = 'fd'
        realspace = True
        h /= Bohr
        N_c = get_number_of_grid_points(cell_cv, h, mode, realspace)
        gd = GridDescriptor(N_c, cell_cv, self.pbc) 
        #gd = self.calc.wfs.gd
        r = gd.get_grid_point_coordinates()
        rrr = r*Bohr
        
        eig_0 = np.array([], dtype = complex)
        eig_left = np.array([], dtype = complex)
        eig_right = np.array([], dtype = complex)
        vec_modes = np.zeros([1, self.npw], dtype = complex)
        vec_modes_dual = np.zeros([1, self.npw], dtype = complex)
        vec_modes_density = np.zeros([1, self.npw], dtype = complex)
        vec_modes_norm = np.zeros([1, self.npw], dtype = complex)
        eig_all = np.zeros([1, self.npw], dtype = complex)
        eig_dummy = np.zeros([1, self.npw], dtype = complex)
        v_dummy = np.zeros([1, self.npw], dtype = complex)
        vec_dummy = np.zeros([1, self.npw], dtype = complex)
        vec_dummy2 = np.zeros([1, self.npw], dtype = complex)
        w_0 = np.array([]) 
        w_left = np.array([])
        w_right = np.array([])
     
        if sum == '2D':
            v_ind = np.zeros([1, r.shape[-1]], dtype = complex)
            n_ind = np.zeros([1, r.shape[-1]], dtype = complex)
        elif sum == '1D':            
            self.printtxt('1D sum not implemented')
            return 
        else:
            v_ind = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype = complex)
            n_ind = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype = complex)

        eps_GG_plus = dm_wGG[0]
        eig_plus, vec_plus = np.linalg.eig(eps_GG_plus)  # find eigenvalues and eigenvectors
        vec_plus_dual = np.linalg.inv(vec_plus)
        
        # loop over frequencies, where the eigenvalues for the 2D matrix in G,G' are found.
        for i in np.array(range(self.Nw-1))+1:
            eps_GG = eps_GG_plus
            eig, vec = eig_plus,vec_plus
            vec_dual = vec_plus_dual
            eps_GG_plus = dm_wGG[i] # epsilon_GG'(omega + d-omega)
            eig_plus, vec_plus = np.linalg.eig(eps_GG_plus)
            vec_plus_dual = np.linalg.inv(vec_plus)
            eig_dummy[0,:] = eig
            eig_all = np.append(eig_all, eig_dummy, axis=0) # append all eigenvalues to array         
            # loop to check find the eigenvalues that crosses zero from negative to positive values:
            for k in range(self.npw):
                for m in range(self.npw):
                    if eig[k]< 0 and 0 < eig_plus[m]:
                        # check it's the same mode - Overlap between eigenvectors should be large:
                        if abs(np.inner(vec[:,k], vec_plus_dual[m,:])) > 0.95:                             
                            self.printtxt('crossing found at w = %1.1f eV'%self.w_w[i-1])
                            eig_left = np.append(eig_left, eig[k])   
                            eig_right = np.append(eig_right, eig_plus[m])

                            vec_dummy[0, :] = vec[:,k]
                            vec_modes = np.append(vec_modes, vec_dummy, axis = 0)
                            vec_dummy[0, :] = vec_dual[k, :].T
                            vec_modes_dual = np.append(vec_modes_dual, vec_dummy, axis = 0)
                                                   
                            w1 = self.w_w[i-1]
                            w2 = self.w_w[i]
                            a = np.real((eig_plus[m]-eig[k]) / (w2-w1))
                            w0 = np.real(-eig[k]) / a + w1
                            eig0 = a*(w0-w1)+eig[k]

                            w_0 = np.append(w_0,w0)
                            w_left = np.append(w_left, w1)
                            eig_0 = np.append(eig_0,eig0)                           

                            n_dummy = np.zeros([1, r.shape[1], r.shape[2],
                                                r.shape[3]], dtype = complex)
                            v_dummy = np.zeros([1, r.shape[1], r.shape[2],
                                                r.shape[3]], dtype = complex)    

                            vec_n = np.zeros([self.npw])
                            
                            for iG in range(self.npw):  # Fourier transform
                                qG = np.dot((q + self.Gvec_Gc[iG]), self.bcell_cv)
                                coef_G = np.dot(qG, qG) / (4 * pi)
                                qGr_R = np.inner(qG, r.T).T
                                v_dummy += vec[iG, k] * np.exp(1j * qGr_R) 
                                n_dummy += vec[iG, k] * np.exp(1j * qGr_R) * coef_G
                                                        
                            if checkphase: # rotate eigenvectors in complex plane 
                                integral = np.zeros([81])
                                phases = np.linspace(0,2,81)
                                for ip in range(81):
                                    v_int = v_dummy * np.exp(1j * pi * phases[ip])
                                    integral[ip] = abs(np.imag(v_int)).sum()                                     
                                phase = phases[np.argsort(integral)][0]
                                
                                v_dummy *= np.exp(1j * pi * phase)
                                n_dummy *= np.exp(1j * pi * phase)
                                

                            if sum == '2D':
                                i_xyz = 3 
                                v_dummy_z = np.zeros([1,v_dummy.shape[i_xyz]],
                                                     dtype = complex)
                                n_dummy_z = np.zeros([1,v_dummy.shape[i_xyz]],
                                                     dtype = complex)
                                v_dummy_z[0,:] = np.sum(np.sum(v_dummy, axis = 1),
                                                        axis = 1)[0,:]
                                n_dummy_z[0,:] = np.sum(np.sum(n_dummy, axis = 1),
                                                        axis = 1)[0,:]

                                v_ind = np.append(v_ind, v_dummy_z, axis=0)
                                n_ind = np.append(n_ind, n_dummy_z, axis=0)
                                                    
                            elif sum == '1D':
                                self.printtxt('1D sum not implemented')
                            else :
                                v_ind = np.append(v_ind, v_dummy, axis=0)
                                n_ind = np.append(n_ind, n_dummy, axis=0)
            
        """                        
        returns: grid points, frequency grid, all eigenvalues, mode energies, left point energies,
                 mode eigenvalues, eigenvalues of left and right-side points,
                 (mode eigenvectors, mode dual eigenvectors,)
                 induced potential in real space, induced density in real space
        """
        
        if return_full:
            return rrr, self.w_w, eig_all[1:], w_0, eig_0, w_left, eig_left, \
               eig_right, vec_modes[1:], vec_modes_dual[1:], v_ind[1:], n_ind[1:]
            
        else:
            return rrr, self.w_w, eig_all[1:], w_0, eig_0, w_left, eig_left, \
               eig_right, v_ind[1:], n_ind[1:]
Example #56
0
h = 0.2        # grid spacing
a = h * G      # side length of box
M = N // B     # number of bands per block
assert M * B == N

D = world.size // B  # number of domains
assert D * B == world.size

# Set up communicators:
r = world.rank // D * D
domain_comm = world.new_communicator(np.arange(r, r + D))
band_comm = world.new_communicator(np.arange(world.rank % D, world.size, D))

# Set up grid descriptor:
gd = GridDescriptor((G, G, G), (a, a, a), True, domain_comm, parsize)

# Random wave functions:
np.random.seed(world.rank)
psit_mG = np.random.uniform(-0.5, 0.5, size=(M,) + tuple(gd.n_c))
if world.rank == 0:
    print 'Size of wave function array:', psit_mG.shape

# Send and receive buffers:
send_mG = gd.empty(M)
recv_mG = gd.empty(M)

def run():
    S_nn = overlap(psit_mG, send_mG, recv_mG)

    t1 = time()
Example #57
0
    def get_dielectric_matrix(self,
                              xc='RPA',
                              overwritechi0=False,
                              symmetric=True,
                              chi0_wGG=None,
                              calc=None,
                              vcut=None,
                              dir=None):
	if self.chi0_wGG is None and chi0_wGG is None:
            self.initialize()
            self.calculate()
        elif self.chi0_wGG is None and chi0_wGG is not None:
            #Read from file and reinitialize 
            self.xc = xc

            from gpaw.response.parallel import par_read 
            self.chi0_wGG = par_read(chi0_wGG, 'chi0_wGG')
            self.nvalbands = self.nbands
            #self.parallel_init() # parallelization not yet implemented
            self.Nw_local = self.Nw  # parallelization not yet implemented
            if self.calc is None:
                from gpaw import GPAW
                self.calc = GPAW(calc,txt=None)
            if self.xc == 'ALDA' or self.xc == 'ALDA_X':
                from gpaw.response.kernel import calculate_Kxc
                from gpaw.grid_descriptor import GridDescriptor
                from gpaw.mpi import world, rank, size, serial_comm
                    
                self.pbc = self.calc.atoms.pbc
                self.gd = GridDescriptor(self.calc.wfs.gd.N_c*self.rpad, self.acell_cv,
                                         pbc_c=True, comm=serial_comm)

                R_av = self.calc.atoms.positions / Bohr
                nt_sg = self.calc.density.nt_sG
                    
                if (self.rpad > 1).any() or (self.pbc - True).any():
                    nt_sG = self.gd.zeros(self.nspins)
                    #nt_sG = np.zeros([self.nspins, self.nG[0], self.nG[1], self.nG[2]])
                    for s in range(self.nspins):
                        nt_G = self.pad(nt_sg[s])
                        nt_sG[s] = nt_G
                else:
                    nt_sG = nt_sg
                        
                self.Kxc_sGG = calculate_Kxc(self.gd, 
                                             nt_sG,
                                             self.npw, self.Gvec_Gc,
                                             self.gd.N_c, self.vol,
                                             self.bcell_cv, R_av,
                                             self.calc.wfs.setups,
                                             self.calc.density.D_asp,
                                             functional=self.xc,
                                             density_cut=self.density_cut)

        if overwritechi0:
            dm_wGG = self.chi0_wGG
        else:
            dm_wGG = np.zeros_like(self.chi0_wGG)

        if dir is None:
            q_c = self.q_c
        else:
            q_c = np.diag((1,1,1))[dir] * self.qopt
            self.chi0_wGG[:,0,:] = self.chi00G_wGv[:,:,dir]
            self.chi0_wGG[:,:,0] = self.chi0G0_wGv[:,:,dir]
        
        from gpaw.response.kernel import calculate_Kc, CoulombKernel
        kernel = CoulombKernel(vcut=self.vcut,
                               pbc=self.calc.atoms.pbc,
                               cell=self.acell_cv)
        self.Kc_GG = kernel.calculate_Kc(q_c,
                                         self.Gvec_Gc,
                                         self.bcell_cv,
                                         symmetric=symmetric)
        #self.Kc_GG = calculate_Kc(q_c,
        #                          self.Gvec_Gc,
        #                          self.acell_cv,
        #                          self.bcell_cv,
        #                          self.pbc,
        #                          self.vcut,
        #                          symmetric=symmetric)

        tmp_GG = np.eye(self.npw, self.npw)

        if xc == 'RPA':
            self.printtxt('Use RPA.')
            for iw in range(self.Nw_local):
                dm_wGG[iw] = tmp_GG - self.Kc_GG * self.chi0_wGG[iw]
                
        elif xc == 'ALDA':
            self.printtxt('Use ALDA kernel.')
            # E_LDA = 1 - v_c chi0 (1-fxc chi0)^-1
            # http://prb.aps.org/pdf/PRB/v33/i10/p7017_1 eq. 4
            A_wGG = self.chi0_wGG.copy()
            for iw in range(self.Nw_local):
                A_wGG[iw] = np.dot(self.chi0_wGG[iw], np.linalg.inv(tmp_GG - np.dot(self.Kxc_sGG[0], self.chi0_wGG[iw])))
    
            for iw in range(self.Nw_local):
                dm_wGG[iw] = tmp_GG - self.Kc_GG * A_wGG[iw]                

        return dm_wGG
Example #58
0
from time import time
from gpaw.grid_descriptor import GridDescriptor
from gpaw.fd_operators import Laplace
import gpaw.mpi as mpi

n = 96
h = 0.1
L = n * h
gd = GridDescriptor((n, n, n), [L, L, L])

# Allocate arrays:
a = gd.zeros(100) + 1.2
b = gd.empty(100)

o = Laplace(gd, 2).apply

t0 = time()
for r in range(10):
    o(a, b)

if mpi.rank == 0:
    print time() - t0, a.shape