コード例 #1
0
ファイル: ut_gucops.py プロジェクト: robwarm/gpaw-symm
class UTGaussianWavefunctionSetup(UTDomainParallelSetup):
    __doc__ = UTDomainParallelSetup.__doc__ + """
    The pseudo wavefunctions are moving gaussians centered around each atom."""

    allocated = False
    dtype = None

    def setUp(self):
        UTDomainParallelSetup.setUp(self)

        for virtvar in ['dtype']:
            assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar

        # Set up kpoint descriptor:
        self.kd = KPointDescriptor(self.nspins, self.nibzkpts, self.kpt_comm, \
            self.gamma, self.dtype)

        # Choose a sufficiently small width of gaussian test functions
        cell_c = np.sum(self.gd.cell_cv**2, axis=1)**0.5
        self.sigma = np.min((0.1+0.4*self.gd.pbc_c)*cell_c)

        if debug and world.rank == 0:
            print 'sigma=%8.5f Ang' % (self.sigma*Bohr), 'cell_c:', cell_c*Bohr, 'Ang', 'N_c:', self.gd.N_c
        self.atoms = create_random_atoms(self.gd, 4, 'H', 4*self.sigma)
        self.r_vG = None
        self.wf_uG = None
        self.laplace0_uG = None

        self.allocate()

    def tearDown(self):
        UTDomainParallelSetup.tearDown(self)
        del self.phase_ucd, self.atoms, self.r_vG, self.wf_uG, self.laplace0_uG
        self.allocated = False

    def allocate(self):
        if self.allocated:
            raise RuntimeError('Already allocated!')

        # Calculate complex phase factors:
        self.phase_ucd = np.ones((self.kd.mynks, 3, 2), complex)
        if not self.gamma:
            for myu, phase_cd in enumerate(self.phase_ucd):
                u = self.kd.global_index(myu)
                s, k = self.kd.what_is(u)
                phase_cd[:] = np.exp(2j * np.pi * self.gd.sdisp_cd * \
                                     self.ibzk_kc[k,:,np.newaxis])
            assert self.dtype == complex, 'Complex wavefunctions are required.'

        self.r_vG = self.gd.get_grid_point_coordinates()
        self.wf_uG = self.gd.zeros(self.kd.mynks, dtype=self.dtype)
        self.laplace0_uG = self.gd.zeros(self.kd.mynks, dtype=self.dtype)
        buf_G = self.gd.empty(dtype=self.dtype)

        sdisp_Ac = []
        for a,spos_c in enumerate(self.atoms.get_scaled_positions() % 1.0):
            for sdisp_x in range(-1*self.gd.pbc_c[0],self.gd.pbc_c[0]+1):
                for sdisp_y in range(-1*self.gd.pbc_c[1],self.gd.pbc_c[1]+1):
                    for sdisp_z in range(-1*self.gd.pbc_c[2],self.gd.pbc_c[2]+1):
                        sdisp_c = np.array([sdisp_x, sdisp_y, sdisp_z])
                        if debug and world.rank == 0:
                            print 'a=%d, spos=%s, sdisp_c=%s' % (a,spos_c,sdisp_c)
                        sdisp_Ac.append((a,spos_c,sdisp_c))

        for a,spos_c,sdisp_c in sdisp_Ac:
            if debug and world.rank == 0:
                print 'Adding gaussian at a=%d, spos=%s, sigma=%8.5f Ang' % (a,spos_c+sdisp_c,self.sigma*Bohr)

            r0_v = np.dot(spos_c+sdisp_c, self.gd.cell_cv)

            for myu in range(self.kd.mynks):
                u = self.kd.global_index(myu)
                s, k = self.kd.what_is(u)
                ibzk_v = self.ibzk_kv[k]

                # f(r) = sum_a A exp(-|r-R^a|^2 / 2sigma^2) exp(i k.r)
                gaussian_wave(self.r_vG, r0_v, self.sigma, ibzk_v, A=1.0,
                              dtype=self.dtype, out_G=buf_G)
                self.wf_uG[myu] += buf_G

                # d^2/dx^2 exp(ikx-(x-x0)^2/2sigma^2)
                # ((ik-(x-x0)/sigma^2)^2 - 1/sigma^2) exp(ikx-(x-x0)^2/2sigma^2)
                dr2_G = np.sum((1j*ibzk_v[:,np.newaxis,np.newaxis,np.newaxis] \
                    - (self.r_vG-r0_v[:,np.newaxis,np.newaxis,np.newaxis]) \
                    / self.sigma**2)**2, axis=0)
                self.laplace0_uG[myu] += (dr2_G - 3/self.sigma**2) * buf_G

        self.allocated = True

    # =================================

    def test_something(self):
        laplace_uG = np.empty_like(self.laplace0_uG)
        op = Laplace(self.gd, dtype=self.dtype)
        for myu, laplace_G in enumerate(laplace_uG):
            phase_cd = {float:None, complex:self.phase_ucd[myu]}[self.dtype]
            op.apply(self.wf_uG[myu], laplace_G, phase_cd)
            print 'myu:', myu, 'diff:', np.std(laplace_G-self.laplace0_uG[myu]), '/', np.abs(laplace_G-self.laplace0_uG[myu]).max()
コード例 #2
0
ファイル: ut_gucops.py プロジェクト: yihsuanliu/gpaw
class UTGaussianWavefunctionSetup(UTDomainParallelSetup):
    __doc__ = UTDomainParallelSetup.__doc__ + """
    The pseudo wavefunctions are moving gaussians centered around each atom."""

    allocated = False
    dtype = None

    def setUp(self):
        UTDomainParallelSetup.setUp(self)

        for virtvar in ['dtype']:
            assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar

        # Set up kpoint descriptor:
        self.kd = KPointDescriptor(self.nspins, self.nibzkpts, self.kpt_comm, \
            self.gamma, self.dtype)

        # Choose a sufficiently small width of gaussian test functions
        cell_c = np.sum(self.gd.cell_cv**2, axis=1)**0.5
        self.sigma = np.min((0.1+0.4*self.gd.pbc_c)*cell_c)

        if debug and world.rank == 0:
            print 'sigma=%8.5f Ang' % (self.sigma*Bohr), 'cell_c:', cell_c*Bohr, 'Ang', 'N_c:', self.gd.N_c
        self.atoms = create_random_atoms(self.gd, 4, 'H', 4*self.sigma)
        self.r_vG = None
        self.wf_uG = None
        self.laplace0_uG = None

        self.allocate()

    def tearDown(self):
        UTDomainParallelSetup.tearDown(self)
        del self.phase_ucd, self.atoms, self.r_vG, self.wf_uG, self.laplace0_uG
        self.allocated = False

    def allocate(self):
        if self.allocated:
            raise RuntimeError('Already allocated!')

        # Calculate complex phase factors:
        self.phase_ucd = np.ones((self.kd.mynks, 3, 2), complex)
        if not self.gamma:
            for myu, phase_cd in enumerate(self.phase_ucd):
                u = self.kd.global_index(myu)
                s, k = self.kd.what_is(u)
                phase_cd[:] = np.exp(2j * np.pi * self.gd.sdisp_cd * \
                                     self.ibzk_kc[k,:,np.newaxis])
            assert self.dtype == complex, 'Complex wavefunctions are required.'

        self.r_vG = self.gd.get_grid_point_coordinates()
        self.wf_uG = self.gd.zeros(self.kd.mynks, dtype=self.dtype)
        self.laplace0_uG = self.gd.zeros(self.kd.mynks, dtype=self.dtype)
        buf_G = self.gd.empty(dtype=self.dtype)

        sdisp_Ac = []
        for a,spos_c in enumerate(self.atoms.get_scaled_positions() % 1.0):
            for sdisp_x in range(-1*self.gd.pbc_c[0],self.gd.pbc_c[0]+1):
                for sdisp_y in range(-1*self.gd.pbc_c[1],self.gd.pbc_c[1]+1):
                    for sdisp_z in range(-1*self.gd.pbc_c[2],self.gd.pbc_c[2]+1):
                        sdisp_c = np.array([sdisp_x, sdisp_y, sdisp_z])
                        if debug and world.rank == 0:
                            print 'a=%d, spos=%s, sdisp_c=%s' % (a,spos_c,sdisp_c)
                        sdisp_Ac.append((a,spos_c,sdisp_c))

        for a,spos_c,sdisp_c in sdisp_Ac:
            if debug and world.rank == 0:
                print 'Adding gaussian at a=%d, spos=%s, sigma=%8.5f Ang' % (a,spos_c+sdisp_c,self.sigma*Bohr)

            r0_v = np.dot(spos_c+sdisp_c, self.gd.cell_cv)

            for myu in range(self.kd.mynks):
                u = self.kd.global_index(myu)
                s, k = self.kd.what_is(u)
                ibzk_v = self.ibzk_kv[k]

                # f(r) = sum_a A exp(-|r-R^a|^2 / 2sigma^2) exp(i k.r)
                gaussian_wave(self.r_vG, r0_v, self.sigma, ibzk_v, A=1.0,
                              dtype=self.dtype, out_G=buf_G)
                self.wf_uG[myu] += buf_G

                # d^2/dx^2 exp(ikx-(x-x0)^2/2sigma^2)
                # ((ik-(x-x0)/sigma^2)^2 - 1/sigma^2) exp(ikx-(x-x0)^2/2sigma^2)
                dr2_G = np.sum((1j*ibzk_v[:,np.newaxis,np.newaxis,np.newaxis] \
                    - (self.r_vG-r0_v[:,np.newaxis,np.newaxis,np.newaxis]) \
                    / self.sigma**2)**2, axis=0)
                self.laplace0_uG[myu] += (dr2_G - 3/self.sigma**2) * buf_G

        self.allocated = True

    # =================================

    def test_something(self):
        laplace_uG = np.empty_like(self.laplace0_uG)
        op = Laplace(self.gd, dtype=self.dtype)
        for myu, laplace_G in enumerate(laplace_uG):
            phase_cd = {float:None, complex:self.phase_ucd[myu]}[self.dtype]
            op.apply(self.wf_uG[myu], laplace_G, phase_cd)
            print 'myu:', myu, 'diff:', np.std(laplace_G-self.laplace0_uG[myu]), '/', np.abs(laplace_G-self.laplace0_uG[myu]).max()