Esempio n. 1
0
class UTProjectorFunctionSetup(UTLocalizedFunctionSetup):
    __doc__ = UTDomainParallelSetup.__doc__ + """
    Projection expansion coefficients are distributed over domains."""

    def setUp(self):
        UTLocalizedFunctionSetup.setUp(self)

        fdksl = get_KohnSham_layouts(None, 'fd', self.gd, self.bd, self.dtype)
        lcaoksl = get_KohnSham_layouts(None,
                                       'lcao',
                                       self.gd,
                                       self.bd,
                                       self.dtype,
                                       nao=self.setups.nao)
        args = (self.gd, self.setups.nvalence, self.setups, self.bd,
                self.dtype, world, self.kd)
        self.wfs = FDWaveFunctions(p.stencils[0], fdksl, fdksl, lcaoksl, *args)
        self.wfs.rank_a = self.rank0_a
        self.allocate(self.wfs.kpt_u, self.wfs.rank_a)
        assert self.allocated

        for kpt in self.wfs.kpt_u:
            for a, P_ni in kpt.P_ani.items():
                for myn, P_i in enumerate(P_ni):
                    n = self.bd.global_index(myn)
                    P_i[:] = 1e12 * kpt.s + 1e9 * kpt.k + 1e6 * a + 1e3 * n \
                        + np.arange(self.setups[a].ni, dtype=self.dtype)

    def tearDown(self):
        del self.wfs
        UTLocalizedFunctionSetup.tearDown(self)

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

        my_atom_indices = np.argwhere(rank_a == self.gd.comm.rank).ravel()
        self.holm_nielsen_check(my_atom_indices)
        self.wfs.allocate_arrays_for_projections(my_atom_indices)  #XXX
        self.chk_una = np.zeros((self.kd_old.nks, self.bd.nbands, self.natoms),
                                dtype=np.int64)
        self.allocated = True

    def update_references(self, kpt_u, rank_a):
        requests = []
        kpt_comm, band_comm, domain_comm = self.kd_old.comm, self.bd.comm, self.gd.comm
        for u in range(self.kd_old.nks):
            kpt_rank, myu = self.kd_old.who_has(u)
            for n in range(self.bd.nbands):
                band_rank, myn = self.bd.who_has(n)
                for a in range(self.natoms):
                    domain_rank = rank_a[a]
                    if kpt_comm.rank == kpt_rank and \
                       band_comm.rank == band_rank and \
                       domain_comm.rank == domain_rank:
                        kpt = kpt_u[myu]
                        chk = md5_array(kpt.P_ani[a][myn], numeric=True)
                        if world.rank == 0:
                            self.chk_una[u, n, a] = chk
                        else:
                            requests.append(world.send(np.array([chk], \
                                dtype=np.int64), 0, 1303+a, block=False))
                    elif world.rank == 0:
                        world_rank = rank_a[a] + \
                            band_rank * domain_comm.size + \
                            kpt_rank * domain_comm.size * band_comm.size
                        chk = self.chk_una[u, n,
                                           a:a + 1]  #XXX hack to get pointer
                        requests.append(world.receive(chk, world_rank, \
                            1303+a, block=False))
        world.waitall(requests)
        world.broadcast(self.chk_una, 0)

    def check_values(self, kpt_u, rank_a):
        for kpt in kpt_u:
            self.holm_nielsen_check(kpt.P_ani.keys())

        # Compare to reference checksums
        ret = True
        kpt_comm, band_comm, domain_comm = self.kd_old.comm, self.bd.comm, self.gd.comm
        for u in range(self.kd_old.nks):
            kpt_rank, myu = self.kd_old.who_has(u)
            for n in range(self.bd.nbands):
                band_rank, myn = self.bd.who_has(n)
                for a in range(self.natoms):
                    domain_rank = rank_a[a]
                    if kpt_comm.rank == kpt_rank and \
                       band_comm.rank == band_rank and \
                       domain_comm.rank == domain_rank:
                        kpt = kpt_u[myu]
                        chk = md5_array(kpt.P_ani[a][myn], numeric=True)
                        ret &= (chk == self.chk_una[u, n, a])
        self.assertTrue(ret)

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

    def test_initial_consistency(self):
        self.update_references(self.wfs.kpt_u, self.wfs.rank_a)
        self.check_values(self.wfs.kpt_u, self.wfs.rank_a)

    def test_redistribution_to_domains(self):
        self.update_references(self.wfs.kpt_u, self.wfs.rank_a)
        spos_ac = self.atoms.get_scaled_positions() % 1.0
        self.wfs.set_positions(spos_ac)
        self.check_values(self.wfs.kpt_u, self.wfs.rank_a)

    def test_redistribution_to_same(self):
        self.update_references(self.wfs.kpt_u, self.wfs.rank_a)
        spos_ac = self.atoms.get_scaled_positions() % 1.0
        self.wfs.set_positions(spos_ac)
        self.wfs.set_positions(spos_ac)
        self.check_values(self.wfs.kpt_u, self.wfs.rank_a)
Esempio n. 2
0
class UTProjectorFunctionSetup(UTLocalizedFunctionSetup):
    __doc__ = UTDomainParallelSetup.__doc__ + """
    Projection expansion coefficients are distributed over domains."""

    def setUp(self):
        UTLocalizedFunctionSetup.setUp(self)

        fdksl = get_KohnSham_layouts(None, 'fd', self.gd, self.bd, 
                                     self.dtype)
        lcaoksl = get_KohnSham_layouts(None, 'lcao', self.gd, self.bd,
                                       self.dtype, nao=self.setups.nao)
        args = (self.gd, self.setups.nvalence, self.setups,
                self.bd, self.dtype, world, self.kd)
        self.wfs = FDWaveFunctions(p.stencils[0], fdksl, fdksl, lcaoksl, *args)
        self.wfs.rank_a = self.rank0_a
        self.allocate(self.wfs.kpt_u, self.wfs.rank_a)
        assert self.allocated

        for kpt in self.wfs.kpt_u:
            for a,P_ni in kpt.P_ani.items():
                for myn,P_i in enumerate(P_ni):
                    n = self.bd.global_index(myn)
                    P_i[:] = 1e12 * kpt.s + 1e9 * kpt.k + 1e6 * a + 1e3 * n \
                        + np.arange(self.setups[a].ni, dtype=self.dtype)

    def tearDown(self):
        del self.wfs
        UTLocalizedFunctionSetup.tearDown(self)

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

        my_atom_indices = np.argwhere(rank_a == self.gd.comm.rank).ravel()
        self.holm_nielsen_check(my_atom_indices)
        self.wfs.allocate_arrays_for_projections(my_atom_indices) #XXX
        self.chk_una = np.zeros((self.kd_old.nks, self.bd.nbands,
                                 self.natoms), dtype=np.int64)
        self.allocated = True

    def update_references(self, kpt_u, rank_a):
        requests = []
        kpt_comm, band_comm, domain_comm = self.kd_old.comm, self.bd.comm, self.gd.comm
        for u in range(self.kd_old.nks):
            kpt_rank, myu = self.kd_old.who_has(u)
            for n in range(self.bd.nbands):
                band_rank, myn = self.bd.who_has(n)
                for a in range(self.natoms):
                    domain_rank = rank_a[a]
                    if kpt_comm.rank == kpt_rank and \
                       band_comm.rank == band_rank and \
                       domain_comm.rank == domain_rank:
                        kpt = kpt_u[myu]
                        chk = md5_array(kpt.P_ani[a][myn], numeric=True)
                        if world.rank == 0:
                            self.chk_una[u,n,a] = chk
                        else:
                            requests.append(world.send(np.array([chk], \
                                dtype=np.int64), 0, 1303+a, block=False))
                    elif world.rank == 0:
                        world_rank = rank_a[a] + \
                            band_rank * domain_comm.size + \
                            kpt_rank * domain_comm.size * band_comm.size
                        chk = self.chk_una[u,n,a:a+1] #XXX hack to get pointer
                        requests.append(world.receive(chk, world_rank, \
                            1303+a, block=False))
        world.waitall(requests)
        world.broadcast(self.chk_una, 0)

    def check_values(self, kpt_u, rank_a):
        for kpt in kpt_u:
           self.holm_nielsen_check(kpt.P_ani.keys())

        # Compare to reference checksums
        ret = True
        kpt_comm, band_comm, domain_comm = self.kd_old.comm, self.bd.comm, self.gd.comm
        for u in range(self.kd_old.nks):
            kpt_rank, myu = self.kd_old.who_has(u)
            for n in range(self.bd.nbands):
                band_rank, myn = self.bd.who_has(n)
                for a in range(self.natoms):
                    domain_rank = rank_a[a]
                    if kpt_comm.rank == kpt_rank and \
                       band_comm.rank == band_rank and \
                       domain_comm.rank == domain_rank:
                        kpt = kpt_u[myu]
                        chk = md5_array(kpt.P_ani[a][myn], numeric=True)
                        ret &= (chk == self.chk_una[u,n,a])
        self.assertTrue(ret)

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

    def test_initial_consistency(self):
        self.update_references(self.wfs.kpt_u, self.wfs.rank_a)
        self.check_values(self.wfs.kpt_u, self.wfs.rank_a)

    def test_redistribution_to_domains(self):
        self.update_references(self.wfs.kpt_u, self.wfs.rank_a)
        spos_ac = self.atoms.get_scaled_positions() % 1.0
        self.wfs.set_positions(spos_ac)
        self.check_values(self.wfs.kpt_u, self.wfs.rank_a)

    def test_redistribution_to_same(self):
        self.update_references(self.wfs.kpt_u, self.wfs.rank_a)
        spos_ac = self.atoms.get_scaled_positions() % 1.0
        self.wfs.set_positions(spos_ac)
        self.wfs.set_positions(spos_ac)
        self.check_values(self.wfs.kpt_u, self.wfs.rank_a)