예제 #1
0
 def testGroupOps(self):
     """Do we correctly generate group operations inside the supercell?"""
     for nmat in self.groupsupers:
         sup = supercell.Supercell(self.crys, nmat)
         # print(super)
         # for g in super.G: if np.all(g.rot==self.one): print(g)
         self.assertEqual(len(sup.G), len(self.crys.G) * sup.size)
         invlatt = np.linalg.inv(sup.lattice)
         superposcart = [np.dot(sup.lattice, u) for u in sup.pos]
         for g in sup.G:
             for i, x, u in zip(itertools.count(), superposcart, sup.pos):
                 gx = np.dot(g.cartrot, x) + np.dot(sup.lattice, g.trans)
                 gu = crystal.incell(np.dot(invlatt, gx))
                 gu0 = crystal.incell(np.dot(g.rot, u) + g.trans)
                 gi = g.indexmap[0][i]
                 if not np.allclose(gu, gu0):
                     self.assertTrue(np.allclose(gu, gu0),
                                     msg="{}\nProblem with GroupOp:\n{}\n{} != {}".format(sup, g, gu, gu0))
                 if not np.allclose(gu, sup.pos[gi]):
                     self.assertTrue(np.allclose(gu, sup.pos[gi]),
                                     msg="{}\nProblem with GroupOp:\n{}\nIndexing: {} != {}".format(sup, g, gu,
                                                                                                    sup.pos[gi]))
     # do we successfully raise a Warning about broken symmetry?
     with self.assertWarns(RuntimeWarning):
         brokensymmsuper = np.array([[3, -5, 2], [-1, 2, 3], [4, -2, 1]])
         supercell.Supercell(self.crys, brokensymmsuper)
예제 #2
0
 def testSuper(self):
     """Can we make a supercell object?"""
     sup = supercell.Supercell(self.crys, self.one)
     self.assertNotEqual(sup, None)
     self.assertEqual(sup.Nchem, self.crys.Nchem)
     sup = supercell.Supercell(self.crys, self.one, interstitial=(1,))
     self.assertNotEqual(sup, None)
     sup = supercell.Supercell(self.crys, self.one, Nsolute=5)
     self.assertNotEqual(sup, None)
     self.assertEqual(sup.Nchem, self.crys.Nchem + 5)
     with self.assertRaises(ZeroDivisionError):
         supercell.Supercell(self.crys, np.zeros((3, 3), dtype=int))
예제 #3
0
 def testMultiply(self):
     """Can we multiply a supercell by our group operations successfully?"""
     sup = supercell.Supercell(self.crys, 3 * self.one, Nsolute=1)
     # set up some random occupancy
     Ntests = 100
     for c, ind in zip(np.random.randint(-1, sup.Nchem, size=Ntests),
                       np.random.randint(sup.size * sup.N, size=Ntests)):
         sup.setocc(ind, c)
     g_occ = sup.occ.copy()
     for g in sup.G:
         gsuper = g * sup
         if not gsuper.__sane__():
             self.assertTrue(False, msg='GroupOp:\n{}\nbreaks sanity?'.format(g))
         # because it's sane, we *only* need to test that occupation is correct
         # indexmap[0]: each entry is the index where it "lands"
         for n in range(sup.size * sup.N):
             g_occ[g.indexmap[0][n]] = sup.occ[n]
         self.assertTrue(np.all(g_occ == gsuper.occ))
         # rotate a few sites, see if they match up:
         for ind in np.random.randint(sup.size * sup.N, size=Ntests // 10):
             gu = crystal.incell(np.dot(g.rot, sup.pos[ind]) + g.trans)
             self.assertIsInstance(gu, np.ndarray)
             self.assertOrderingSuperEqual(gsuper[gu], sup[ind], msg='Group operation fail?')
     # quick test of multiplying the other direction, and in-place (which should all call the same code)
     self.assertOrderingSuperEqual(gsuper, sup * g, msg='Other rotation fail?')
     sup *= g
     self.assertOrderingSuperEqual(gsuper, sup, msg='In place rotation fail?')
예제 #4
0
 def testIndexExceptions(self):
     """Do we get raise indexing errors as appropriate?"""
     sup = supercell.Supercell(self.crys, 3 * self.one, interstitial=[1])
     with self.assertRaises(IndexError):
         sup.definesolute(0, 'Mg')
     with self.assertRaises(IndexError):
         sup.definesolute(-1, 'Mg')
     with self.assertRaises(IndexError):
         sup.definesolute(2, 'Mg')
     with self.assertRaises(IndexError):
         sup.setocc(0, 2)
     with self.assertRaises(IndexError):
         sup.setocc(sup.size * sup.N, 0)
     # and... all of the following should be *safe* operations:
     sup.setocc(0, 0)
     sup.setocc(-1, 0)
     sup = supercell.Supercell(self.crys, self.one, interstitial=[1], Nsolute=1)
     sup.definesolute(2, 'Mg')
예제 #5
0
    def testEquivalenceMap(self):
        """Can we construct an equivalence map between two supercells?"""
        sup = supercell.Supercell(self.crys, 3 * self.one, Nsolute=1)
        sup.definesolute(sup.Nchem - 1, 's')
        # set up some random occupancy
        Ntests = 100
        for c, ind in zip(np.random.randint(-1, sup.Nchem, size=Ntests),
                          np.random.randint(sup.size * sup.N, size=Ntests)):
            sup.setocc(ind, c)
        supercopy = sup.copy()
        # first equivalence test: introduce some random permutations of ordering of supercell
        for ind in np.random.randint(sup.size * sup.N, size=Ntests):
            c, sup[ind] = sup[ind], -1
            sup[ind] = c
        g, mapping = supercopy.equivalencemap(sup)
        self.assertNotEqual(g, None, msg='Cannot map between permutation?')
        supercopy.reorder(mapping)
        self.assertOrderingSuperEqual(sup, supercopy, msg='Improper map from random permutation')
        # apply all of the group operations, and see how they perform:
        for g in sup.G:
            gsuper = g * sup
            for ind in np.random.randint(sup.size * sup.N, size=Ntests):
                c, gsuper[ind] = gsuper[ind], -1
                gsuper[ind] = c
            g0, mapping = supercopy.equivalencemap(gsuper)
            if g != g0:
                msg = 'Group operations not equal?\n'
                for line0, line1 in itertools.zip_longest(g.__str__().splitlines(),
                                                          g0.__str__().splitlines(),
                                                          fillvalue=' - '):
                    msg += line0 + '\t' + line1 + '\n'
                self.fail(msg=msg)
            self.assertOrderingSuperEqual((g0 * supercopy).reorder(mapping), gsuper,
                                          msg='Group operation + mapping failure?')
            # do the testing with occposlist, since that's what this is really for...
            rotoccposlist = [[crystal.incell(np.dot(g0.rot, pos) + g0.trans) for pos in poslist]
                             for poslist in supercopy.occposlist()]
            # now, reorder:
            reorderoccposlist = copy.deepcopy(rotoccposlist)
            for reposlist, poslist, remap in zip(reorderoccposlist, rotoccposlist, mapping):
                for i, m in enumerate(remap):
                    reposlist[i] = poslist[m]
            for reposlist, gposlist in zip(reorderoccposlist, gsuper.occposlist()):
                for repos, gpos in zip(reposlist, gposlist):
                    self.assertTrue(np.allclose(repos, gpos),
                                    msg='Reordering the unit cell position failed?')

        # now try something that *shouldn't* be equivalent:
        for ind in np.random.randint(sup.size * sup.N, size=Ntests):
            # a chemical "permutation":
            sup[ind] = (sup[ind] + 2) % (sup.Nchem + 1) - 1
        g, mapping = supercopy.equivalencemap(sup)
        self.assertEqual(g, None, msg='Found a mapping where one should not exist?')
예제 #6
0
 def testFillPeriodic(self):
     """Can we fill up our periodic cell?"""
     sup = supercell.Supercell(self.crys, 3 * self.one, interstitial=[1])
     sup.fillperiodic((0, 0))
     self.assertEqual(len(sup.chemorder[0]), sup.size * len(self.crys.basis[0]))
     for n in range(1, sup.Nchem):
         self.assertEqual(len(sup.chemorder[n]), 0)
     for ind in range(sup.size * sup.N):
         if ind in sup.chemorder[0]:
             self.assertEqual(sup.occ[ind], 0)  # occupied with correct chemistry
         else:
             self.assertEqual(sup.occ[ind], -1)  # vacancy
     for ci in next((wset for wset in self.crys.Wyckoff if (0, 0) in wset), None):
         i = self.crys.atomindices.index(ci)
         for n in range(sup.size):
             self.assertIn(n * sup.N + i, sup.chemorder[0])
예제 #7
0
 def testSites(self):
     """Do we have the correct sites in our supercell?"""
     for n in range(100):
         randsuper = np.random.randint(-5, 6, size=(3, 3))
         if np.allclose(np.linalg.det(randsuper), 0): continue
         # for efficiency we don't bother generating group ops,
         # and also to avoid warnings about broken symmetry
         sup = supercell.Supercell(self.crys, randsuper, NOSYM=True)
         Rdictset = {ci: set() for ci in self.crys.atomindices}
         for u in sup.pos:
             x = np.dot(self.crys.lattice, np.dot(randsuper, u))
             R, ci = self.crys.cart2pos(x)
             self.assertNotEqual(ci, None)
             Rtup = tuple(R)
             self.assertNotIn(Rtup, Rdictset[ci])
             Rdictset[ci].add(Rtup)
         for v in Rdictset.values():
             self.assertEqual(len(v), sup.size)
예제 #8
0
 def testReorder(self):
     """Can we reorder a supercell?"""
     sup = supercell.Supercell(self.crys, 3 * self.one, Nsolute=1)
     sup.definesolute(sup.Nchem - 1, 's')
     # set up some random occupancy
     Ntests = 100
     for c, ind in zip(np.random.randint(-1, sup.Nchem, size=Ntests),
                       np.random.randint(sup.size * sup.N, size=Ntests)):
         sup.setocc(ind, c)
     # Try some simple reorderings: 1. unity permutation; 2. pop+push; 3. reversal
     supercopy = sup.copy()
     unitymap = [[i for i in range(len(clist))] for clist in sup.chemorder]
     supercopy.reorder(unitymap)
     self.assertOrderingSuperEqual(sup, supercopy, msg='Reordering fail with unity?')
     popmap = []
     for c, clist in enumerate(sup.chemorder):
         n = len(clist)
         popmap.append([(i + 1) % n for i in range(n)])
         indpoppush = clist[0]
         sup.setocc(indpoppush, -1)
         sup.setocc(indpoppush, c)  # *now* should be at the *end* of the chemorder list
     supercopy.reorder(popmap)
     self.assertOrderingSuperEqual(sup, supercopy, msg='Reordering fail with "pop/push"?')
     revmap = []
     for c, clist in enumerate(sup.chemorder):
         n = len(clist)
         revmap.append([(n - 1 - i) for i in range(n)])
         cl = clist.copy()  # need to be careful, since clist gets modified by our popping...
         for indpoppush in cl:
             sup.setocc(indpoppush, -1)
         cl.reverse()
         for indpoppush in cl:
             sup.setocc(indpoppush, c)
     supercopy.reorder(revmap)
     self.assertOrderingSuperEqual(sup, supercopy, msg='Reordering fail with reverse?')
     # test out a bad mapping:
     badmap = [[i % 2 for i in range(len(clist))] for clist in sup.chemorder]
     with self.assertRaises(ValueError):
         supercopy.reorder(badmap)
     self.assertOrderingSuperEqual(sup, supercopy, msg='Reordering is not safe after fail?')
예제 #9
0
 def testIndex(self):
     """Test that we can use index into our supercell appropriately"""
     for n in range(10):
         randsuper = np.random.randint(-5, 6, size=(3, 3))
         if np.allclose(np.linalg.det(randsuper), 0): continue
         # for efficiency we don't bother generating group ops,
         # and also to avoid warnings about broken symmetry
         sup = supercell.Supercell(self.crys, randsuper, NOSYM=True)
         for ind, u in enumerate(sup.pos):
             self.assertEqual(ind, sup.index(u))
             delta = np.random.uniform(-0.01, 0.01, size=3)
             self.assertEqual(ind, sup.index(crystal.incell(u + delta)))
         # test out setting by making a copy "by hand"
         randcopy = sup.copy()  # starts out empty, too.
         Ntests = 30
         for c, ind in zip(np.random.randint(-1, sup.Nchem, size=Ntests),
                           np.random.randint(sup.size * sup.N, size=Ntests)):
             sup.setocc(ind, c)
         for c, poslist in enumerate(sup.occposlist()):
             for pos in poslist:
                 randcopy[pos] = c
         self.assertOrderingSuperEqual(sup, randcopy, msg='Indexing fail?')
예제 #10
0
 def testSanity(self):
     """Does __sane__ operate as it should?"""
     # we use NOSYM for speed only
     sup = supercell.Supercell(self.crys, 3 * self.one, Nsolute=1, NOSYM=True)
     self.assertTrue(sup.__sane__(), msg='Empty supercell not sane?')
     # do a bunch of random operations, make sure we remain sane:
     Ntests = 100
     for c, ind in zip(np.random.randint(-1, sup.Nchem, size=Ntests),
                       np.random.randint(sup.size * sup.N, size=Ntests)):
         sup.setocc(ind, c)
         if not sup.__sane__():
             self.assertTrue(False, msg='Supercell:\n{}\nnot sane?'.format(sup))
     # Now! Break sanity (and then repair it)
     for c, ind in zip(np.random.randint(-1, sup.Nchem, size=Ntests),
                       np.random.randint(sup.size * sup.N, size=Ntests)):
         c0 = sup.occ[ind]
         if c == c0: continue
         sup.occ[ind] = c
         self.assertFalse(sup.__sane__())
         sup.occ[ind] = c0
         if not sup.__sane__():
             self.assertTrue(False, msg='Supercell:\n{}\nnot sane?'.format(sup))
예제 #11
0
 def testEqualityCopy(self):
     """Can we copy a supercell, and is it equal to itself?"""
     super0 = supercell.Supercell(self.crys, self.one)
     super2 = super0.copy()
     self.assertOrderingSuperEqual(super0, super2, msg="copy not equal")
예제 #12
0
 def testYAML(self):
     """Can we read/write YAML representation of a supercell?"""
     sup = supercell.Supercell(self.crys, 3 * self.one, interstitial=[1])
     YAMLstring = crystal.yaml.dump(sup)
     superYAML = crystal.yaml.load(YAMLstring)
     self.assertOrderingSuperEqual(sup, superYAML, msg='YAML write/read fail?')