def test_from_spacegroup(self): s1 = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Li", "O"], [[0.25, 0.25, 0.25], [0, 0, 0]]) self.assertEqual(s1.formula, "Li8 O4") s2 = Structure.from_spacegroup(225, Lattice.cubic(3), ["Li", "O"], [[0.25, 0.25, 0.25], [0, 0, 0]]) self.assertEqual(s1, s2) s2 = Structure.from_spacegroup(225, Lattice.cubic(3), ["Li", "O"], [[0.25, 0.25, 0.25], [0, 0, 0]], site_properties={"charge": [1, -2]}) self.assertEqual(sum(s2.site_properties["charge"]), 0) s = Structure.from_spacegroup("Pm-3m", Lattice.cubic(3), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.assertEqual(s.formula, "Cs1 Cl1") self.assertRaises(ValueError, Structure.from_spacegroup, "Pm-3m", Lattice.tetragonal(1, 3), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.assertRaises(ValueError, Structure.from_spacegroup, "Pm-3m", Lattice.cubic(3), ["Cs"], [[0, 0, 0], [0.5, 0.5, 0.5]])
def test_get_slab(self): s = self.get_structure("LiFePO4") gen = SlabGenerator(s, [0, 0, 1], 10, 10) s = gen.get_slab(0.25) self.assertAlmostEqual(s.lattice.abc[2], 20.820740000000001) fcc = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) gen = SlabGenerator(fcc, [1, 1, 1], 10, 10) slab = gen.get_slab() gen = SlabGenerator(fcc, [1, 1, 1], 10, 10, primitive=False) slab_non_prim = gen.get_slab() self.assertEqual(len(slab), 6) self.assertEqual(len(slab_non_prim), len(slab) * 4) #Some randomized testing of cell vectors for i in range(1, 231): i = random.randint(1, 230) sg = SpaceGroup.from_int_number(i) if sg.crystal_system == "hexagonal" or (sg.crystal_system == \ "trigonal" and sg.symbol.endswith("H")): latt = Lattice.hexagonal(5, 10) else: #Cubic lattice is compatible with all other space groups. latt = Lattice.cubic(5) s = Structure.from_spacegroup(i, latt, ["H"], [[0, 0, 0]]) miller = (0, 0, 0) while miller == (0, 0, 0): miller = (random.randint(0, 6), random.randint(0, 6), random.randint(0, 6)) gen = SlabGenerator(s, miller, 10, 10) a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0)
def test_get_slabs(self): gen = SlabGenerator(self.get_structure("CsCl"), [0, 0, 1], 10, 10) #Test orthogonality of some internal variables. a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) self.assertEqual(len(gen.get_slabs()), 1) s = self.get_structure("LiFePO4") gen = SlabGenerator(s, [0, 0, 1], 10, 10) self.assertEqual(len(gen.get_slabs()), 5) self.assertEqual(len(gen.get_slabs(bonds={("P", "O"): 3})), 2) # There are no slabs in LFP that does not break either P-O or Fe-O # bonds for a miller index of [0, 0, 1]. self.assertEqual(len(gen.get_slabs( bonds={("P", "O"): 3, ("Fe", "O"): 3})), 0) #If we allow some broken bonds, there are a few slabs. self.assertEqual(len(gen.get_slabs( bonds={("P", "O"): 3, ("Fe", "O"): 3}, max_broken_bonds=2)), 2) # At this threshold, only the origin and center Li results in # clustering. All other sites are non-clustered. So the of # slabs is of sites in LiFePO4 unit cell - 2 + 1. self.assertEqual(len(gen.get_slabs(tol=1e-4)), 15) LiCoO2=Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) gen = SlabGenerator(LiCoO2, [0, 0, 1], 10, 10) lco = gen.get_slabs(bonds={("Co", "O"): 3}) self.assertEqual(len(lco), 1) a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) scc = Structure.from_spacegroup("Pm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) gen = SlabGenerator(scc, [0, 0, 1], 10, 10) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1) gen = SlabGenerator(scc, [1, 1, 1], 10, 10, max_normal_search=1) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1) # Test whether using units of hkl planes instead of Angstroms for # min_slab_size and min_vac_size will give us the same number of atoms natoms = [] for a in [1, 1.4, 2.5, 3.6]: s = Structure.from_spacegroup("Im-3m", Lattice.cubic(a), ["Fe"], [[0,0,0]]) slabgen = SlabGenerator(s, (1,1,1), 10, 10, in_unit_planes=True, max_normal_search=2) natoms.append(len(slabgen.get_slab())) n = natoms[0] for i in natoms: self.assertEqual(n, i)
def test_merge_sites(self): species = [{'Ag': 0.5}, {'Cl': 0.25}, {'Cl': 0.1}, {'Ag': 0.5}, {'F': 0.15}, {'F': 0.1}] coords = [[0, 0, 0], [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [0, 0, 0], [0.5, 0.5, 1.501], [0.5, 0.5, 1.501]] s = Structure(Lattice.cubic(1), species, coords) s.merge_sites(mode="s") self.assertEqual(s[0].specie.symbol, 'Ag') self.assertEqual(s[1].species_and_occu, Composition({'Cl': 0.35, 'F': 0.25})) self.assertArrayAlmostEqual(s[1].frac_coords, [.5, .5, .5005]) # Test for TaS2 with spacegroup 166 in 160 setting. l = Lattice.from_lengths_and_angles([3.374351, 3.374351, 20.308941], [90.000000, 90.000000, 120.000000]) species = ["Ta", "S", "S"] coords = [[0.000000, 0.000000, 0.944333], [0.333333, 0.666667, 0.353424], [0.666667, 0.333333, 0.535243]] tas2 = Structure.from_spacegroup(160, l, species, coords) assert len(tas2) == 13 tas2.merge_sites(mode="d") assert len(tas2) == 9 l = Lattice.from_lengths_and_angles([3.587776, 3.587776, 19.622793], [90.000000, 90.000000, 120.000000]) species = ["Na", "V", "S", "S"] coords = [[0.333333, 0.666667, 0.165000], [0.000000, 0.000000, 0.998333], [0.333333, 0.666667, 0.399394], [0.666667, 0.333333, 0.597273]] navs2 = Structure.from_spacegroup(160, l, species, coords) assert len(navs2) == 18 navs2.merge_sites(mode="d") assert len(navs2) == 12
def test_structure(self): quartz = self.quartz.structure np.testing.assert_array_almost_equal( quartz.lattice.matrix, [[4.913400, 0, 0], [-2.456700, 4.255129, 0], [0, 0, 5.405200]], ) self.assertEqual(quartz.formula, "Si3 O6") self.assertNotIn("molecule-ID", self.quartz.atoms.columns) ethane = self.ethane.structure np.testing.assert_array_almost_equal(ethane.lattice.matrix, np.diag([10.0] * 3)) lbounds = np.array(self.ethane.box.bounds)[:, 0] coords = self.ethane.atoms[["x", "y", "z"]].values - lbounds np.testing.assert_array_almost_equal(ethane.cart_coords, coords) np.testing.assert_array_almost_equal(ethane.site_properties["charge"], self.ethane.atoms["q"]) tatb = self.tatb.structure frac_coords = tatb.frac_coords[381] real_frac_coords = frac_coords - np.floor(frac_coords) np.testing.assert_array_almost_equal(real_frac_coords, [0.01553397, 0.71487872, 0.14134139]) co = Structure.from_spacegroup(194, Lattice.hexagonal(2.50078, 4.03333), ["Co"], [[1 / 3, 2 / 3, 1 / 4]]) ld_co = LammpsData.from_structure(co) self.assertEqual(ld_co.structure.composition.reduced_formula, "Co") ni = Structure.from_spacegroup(225, Lattice.cubic(3.50804), ["Ni"], [[0, 0, 0]]) ld_ni = LammpsData.from_structure(ni) self.assertEqual(ld_ni.structure.composition.reduced_formula, "Ni")
def setUp(self): self.cscl = Structure.from_spacegroup("Pm-3m", Lattice.cubic(4.2), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.Fe = Structure.from_spacegroup("Im-3m", Lattice.cubic(2.82), ["Fe"], [[0, 0, 0]]) mglatt = Lattice.from_parameters(3.2, 3.2, 5.13, 90, 90, 120) self.Mg = Structure(mglatt, ["Mg", "Mg"], [[1 / 3, 2 / 3, 1 / 4], [2 / 3, 1 / 3, 3 / 4]]) self.lifepo4 = self.get_structure("LiFePO4") self.tei = Structure.from_file(get_path("icsd_TeI.cif"), primitive=False) self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) self.p1 = Structure( Lattice.from_parameters(3, 4, 5, 31, 43, 50), ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]], ) self.graphite = self.get_structure("Graphite") self.trigBi = Structure( Lattice.from_parameters(3, 3, 10, 90, 90, 120), ["Bi", "Bi", "Bi", "Bi", "Bi", "Bi"], [ [0.3333, 0.6666, 0.39945113], [0.0000, 0.0000, 0.26721554], [0.0000, 0.0000, 0.73278446], [0.6666, 0.3333, 0.60054887], [0.6666, 0.3333, 0.06611779], [0.3333, 0.6666, 0.93388221], ], )
def setUp(self): l = Lattice.cubic(3.51) species = ["Ni"] coords = [[0, 0, 0]] self.Ni = Structure.from_spacegroup("Fm-3m", l, species, coords) self.Si = Structure.from_spacegroup("Fd-3m", Lattice.cubic(5.430500), ["Si"], [(0, 0, 0.5)])
def setUp(self): l = Lattice.cubic(3.51) species = ["Ni"] coords = [[0,0,0]] self.Ni = Structure.from_spacegroup("Fm-3m", l, species, coords) self.Si = Structure.from_spacegroup("Fd-3m", Lattice.cubic(5.430500), ["Si"], [(0, 0, 0.5)])
def test_sulfide_type(self): # NaS2 -> polysulfide latt = Lattice.tetragonal(9.59650, 11.78850) species = ["Na"] * 2 + ["S"] * 2 coords = [ [0.00000, 0.00000, 0.17000], [0.27600, 0.25000, 0.12500], [0.03400, 0.25000, 0.29600], [0.14700, 0.11600, 0.40000], ] struct = Structure.from_spacegroup(122, latt, species, coords) self.assertEqual(sulfide_type(struct), "polysulfide") # NaCl type NaS -> sulfide latt = Lattice.cubic(5.75) species = ["Na", "S"] coords = [[0.00000, 0.00000, 0.00000], [0.50000, 0.50000, 0.50000]] struct = Structure.from_spacegroup(225, latt, species, coords) self.assertEqual(sulfide_type(struct), "sulfide") # Na2S2O3 -> None (sulfate) latt = Lattice.monoclinic(6.40100, 8.10000, 8.47400, 96.8800) species = ["Na"] * 2 + ["S"] * 2 + ["O"] * 3 coords = [ [0.29706, 0.62396, 0.08575], [0.37673, 0.30411, 0.45416], [0.52324, 0.10651, 0.21126], [0.29660, -0.04671, 0.26607], [0.17577, 0.03720, 0.38049], [0.38604, -0.20144, 0.33624], [0.16248, -0.08546, 0.11608], ] struct = Structure.from_spacegroup(14, latt, species, coords) self.assertEqual(sulfide_type(struct), None) # Na3PS3O -> sulfide latt = Lattice.orthorhombic(9.51050, 11.54630, 5.93230) species = ["Na"] * 2 + ["S"] * 2 + ["P", "O"] coords = [ [0.19920, 0.11580, 0.24950], [0.00000, 0.36840, 0.29380], [0.32210, 0.36730, 0.22530], [0.50000, 0.11910, 0.27210], [0.50000, 0.29400, 0.35500], [0.50000, 0.30300, 0.61140], ] struct = Structure.from_spacegroup(36, latt, species, coords) self.assertEqual(sulfide_type(struct), "sulfide") # test for unphysical cells struct.scale_lattice(struct.volume * 10) self.assertEqual(sulfide_type(struct), "sulfide")
def test_interpolate(self): coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) struct = IStructure(self.lattice, ["Si"] * 2, coords) coords2 = list() coords2.append([0, 0, 0]) coords2.append([0.5, 0.5, 0.5]) struct2 = IStructure(self.struct.lattice, ["Si"] * 2, coords2) int_s = struct.interpolate(struct2, 10) for s in int_s: self.assertIsNotNone(s, "Interpolation Failed!") self.assertEqual(int_s[0].lattice, s.lattice) self.assertArrayEqual(int_s[1][1].frac_coords, [0.725, 0.5, 0.725]) badlattice = [[1, 0.00, 0.00], [0, 1, 0.00], [0.00, 0, 1]] struct2 = IStructure(badlattice, ["Si"] * 2, coords2) self.assertRaises(ValueError, struct.interpolate, struct2) coords2 = list() coords2.append([0, 0, 0]) coords2.append([0.5, 0.5, 0.5]) struct2 = IStructure(self.struct.lattice, ["Si", "Fe"], coords2) self.assertRaises(ValueError, struct.interpolate, struct2) # Test autosort feature. s1 = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) s1.pop(0) s2 = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) s2.pop(2) random.shuffle(s2) for s in s1.interpolate(s2, autosort_tol=0.5): self.assertArrayAlmostEqual(s1[0].frac_coords, s[0].frac_coords) self.assertArrayAlmostEqual(s1[2].frac_coords, s[2].frac_coords) # Make sure autosort has no effect on simpler interpolations, # and with shuffled sites. s1 = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) s2 = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) s2[0] = "Fe", [0.01, 0.01, 0.01] random.shuffle(s2) for s in s1.interpolate(s2, autosort_tol=0.5): self.assertArrayAlmostEqual(s1[1].frac_coords, s[1].frac_coords) self.assertArrayAlmostEqual(s1[2].frac_coords, s[2].frac_coords) self.assertArrayAlmostEqual(s1[3].frac_coords, s[3].frac_coords)
def test_merge_sites(self): species = [{ 'Ag': 0.5 }, { 'Cl': 0.25 }, { 'Cl': 0.1 }, { 'Ag': 0.5 }, { 'F': 0.15 }, { 'F': 0.1 }] coords = [[0, 0, 0], [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [0, 0, 0], [0.5, 0.5, 1.501], [0.5, 0.5, 1.501]] s = Structure(Lattice.cubic(1), species, coords) s.merge_sites(mode="s") self.assertEqual(s[0].specie.symbol, 'Ag') self.assertEqual(s[1].species_and_occu, Composition({ 'Cl': 0.35, 'F': 0.25 })) self.assertArrayAlmostEqual(s[1].frac_coords, [.5, .5, .5005]) # Test for TaS2 with spacegroup 166 in 160 setting. l = Lattice.from_lengths_and_angles([3.374351, 3.374351, 20.308941], [90.000000, 90.000000, 120.000000]) species = ["Ta", "S", "S"] coords = [[0.000000, 0.000000, 0.944333], [0.333333, 0.666667, 0.353424], [0.666667, 0.333333, 0.535243]] tas2 = Structure.from_spacegroup(160, l, species, coords) assert len(tas2) == 13 tas2.merge_sites(mode="d") assert len(tas2) == 9 l = Lattice.from_lengths_and_angles([3.587776, 3.587776, 19.622793], [90.000000, 90.000000, 120.000000]) species = ["Na", "V", "S", "S"] coords = [[0.333333, 0.666667, 0.165000], [0.000000, 0.000000, 0.998333], [0.333333, 0.666667, 0.399394], [0.666667, 0.333333, 0.597273]] navs2 = Structure.from_spacegroup(160, l, species, coords) assert len(navs2) == 18 navs2.merge_sites(mode="d") assert len(navs2) == 12
def setUp(self): self.cscl = Structure.from_spacegroup( "Pm-3m", Lattice.cubic(4.2), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.Fe = Structure.from_spacegroup(\ "Im-3m", Lattice.cubic(2.82), ["Fe"], [[0, 0, 0]]) self.lifepo4 = self.get_structure("LiFePO4") self.tei = Structure.from_file(get_path("icsd_TeI.cif"), primitive=False) self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50), ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]]) self.graphite = self.get_structure("Graphite")
def test_kpath_generation(self): triclinic = [1, 2] monoclinic = range(3, 16) orthorhombic = range(16, 75) tetragonal = range(75, 143) rhombohedral = range(143, 168) hexagonal = range(168, 195) cubic = range(195, 231) species = ['K', 'La', 'Ti'] coords = [[.345, 5, .77298], [.1345, 5.1, .77298], [.7, .8, .9]] for i in range(230): sg_num = i + 1 if sg_num in triclinic: lattice = Lattice([[3.0233057319441246,0,0], [0,7.9850357844548681,0], [0,0,8.1136762279561818]]) elif sg_num in monoclinic: lattice = Lattice.monoclinic(2, 9, 1, 99) elif sg_num in orthorhombic: lattice = Lattice.orthorhombic(2, 9, 1) elif sg_num in tetragonal: lattice = Lattice.tetragonal(2, 9) elif sg_num in rhombohedral: lattice = Lattice.hexagonal(2, 95) elif sg_num in hexagonal: lattice = Lattice.hexagonal(2, 9) elif sg_num in cubic: lattice = Lattice.cubic(2) struct = Structure.from_spacegroup(sg_num, lattice, species, coords) kpath = HighSymmKpath(struct) #Throws error if something doesn't work, causing test to fail.
def setUp(self): with open( os.path.join(PymatgenTest.TEST_FILES_DIR, "test_toec_data.json")) as f: self.data_dict = json.load(f) self.strains = [Strain(sm) for sm in self.data_dict["strains"]] self.pk_stresses = [Stress(d) for d in self.data_dict["pk_stresses"]] self.c2 = self.data_dict["C2_raw"] self.c3 = self.data_dict["C3_raw"] self.exp = ElasticTensorExpansion.from_voigt([self.c2, self.c3]) self.cu = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3.623), ["Cu"], [[0] * 3]) indices = [(0, 0), (0, 1), (3, 3)] values = [167.8, 113.5, 74.5] cu_c2 = ElasticTensor.from_values_indices(values, indices, structure=self.cu, populate=True) indices = [(0, 0, 0), (0, 0, 1), (0, 1, 2), (0, 3, 3), (0, 5, 5), (3, 4, 5)] values = [-1507.0, -965.0, -71.0, -7.0, -901.0, 45.0] cu_c3 = Tensor.from_values_indices(values, indices, structure=self.cu, populate=True) self.exp_cu = ElasticTensorExpansion([cu_c2, cu_c3]) cu_c4 = Tensor.from_voigt(self.data_dict["Cu_fourth_order"]) self.exp_cu_4 = ElasticTensorExpansion([cu_c2, cu_c3, cu_c4]) warnings.simplefilter("ignore")
def compile_crystal(datarow, flavor='pmg'): """ Helper method for representing the MPDS crystal structures in two flavors: either as a Pymatgen Structure object, or as an ASE Atoms object. Attention! These two flavors are not compatible, e.g. primitive vs. crystallographic cell is defaulted, atoms wrapped or non-wrapped into the unit cell etc. Note, that the crystal structures are not retrieved by default, so one needs to specify the fields while retrieval: - cell_abc - sg_n - setting - basis_noneq - els_noneq e.g. like this: {'S':['cell_abc', 'sg_n', 'setting', 'basis_noneq', 'els_noneq']} NB. occupancies are not considered. Args: datarow: (list) Required data to construct crystal structure: [cell_abc, sg_n, setting, basis_noneq, els_noneq] flavor: (str) Either "pmg", or "ase" Returns: - if flavor is pmg, returns Pymatgen Structure object - if flavor is ase, returns ASE Atoms object """ if not datarow or not datarow[-1]: return None cell_abc, sg_n, setting, basis_noneq, els_noneq = \ datarow[-5], int(datarow[-4]), datarow[-3], datarow[-2], datarow[-1] if flavor == 'pmg': return Structure.from_spacegroup( sg_n, Lattice.from_parameters(*cell_abc), els_noneq, basis_noneq ) elif flavor == 'ase' and use_ase: atom_data = [] setting = 2 if setting == '2' else 1 for num, i in enumerate(basis_noneq): atom_data.append(Atom(els_noneq[num], tuple(i))) return crystal( atom_data, spacegroup=sg_n, cellpar=cell_abc, primitive_cell=True, setting=setting, onduplicates='replace' ) else: raise APIError("Crystal structure treatment unavailable")
def setUp(self): self.structure = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3.5), ["Ni"], [[0, 0, 0]]) lattice = Lattice.cubic(3.010) frac_coords = [ [0.00000, 0.00000, 0.00000], [0.00000, 0.50000, 0.50000], [0.50000, 0.00000, 0.50000], [0.50000, 0.50000, 0.00000], [0.50000, 0.00000, 0.00000], [0.50000, 0.50000, 0.50000], [0.00000, 0.00000, 0.50000], [0.00000, 0.50000, 0.00000], ] species = ["Mg", "Mg", "Mg", "Mg", "O", "O", "O", "O"] self.MgO = Structure(lattice, species, frac_coords) slabs = generate_all_slabs( self.structure, max_index=2, min_slab_size=6.0, min_vacuum_size=15.0, max_normal_search=1, center_slab=True, ) self.slab_dict = {"".join([str(i) for i in slab.miller_index]): slab for slab in slabs} self.asf_211 = AdsorbateSiteFinder(self.slab_dict["211"]) self.asf_100 = AdsorbateSiteFinder(self.slab_dict["100"]) self.asf_111 = AdsorbateSiteFinder(self.slab_dict["111"]) self.asf_110 = AdsorbateSiteFinder(self.slab_dict["110"]) self.asf_struct = AdsorbateSiteFinder(Structure.from_sites(self.slab_dict["111"].sites))
def setUp(self): l = Lattice.cubic(3.51) species = ["Ni"] coords = [[0, 0, 0]] self.Ni = Structure.from_spacegroup("Fm-3m", l, species, coords) l = Lattice.cubic(2.819000) species = ["Fe"] coords = [[0, 0, 0]] self.Fe = Structure.from_spacegroup("Im-3m", l, species, coords) self.Si = Structure.from_spacegroup("Fd-3m", Lattice.cubic(5.430500), ["Si"], [(0, 0, 0.5)]) with open(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "reconstructions_archive.json")) as data_file: self.rec_archive = json.load(data_file)
def setUp(self): latt = Lattice.cubic(4.17) species = ["Ni", "O"] coords = [[0, 0, 0], [0.5, 0.5, 0.5]] self.NiO = Structure.from_spacegroup(225, latt, species, coords) latt = Lattice([[2.085, 2.085, 0.0], [0.0, -2.085, -2.085], [-2.085, 2.085, -4.17]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0, 0.5], [0, 0, 0], [0.25, 0.5, 0.25], [0.75, 0.5, 0.75]] self.NiO_AFM_111 = Structure(latt, species, coords) self.NiO_AFM_111.add_spin_by_site([-5, 5, 0, 0]) latt = Lattice([[2.085, 2.085, 0], [0, 0, -4.17], [-2.085, 2.085, 0]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0.5, 0.5], [0, 0, 0], [0, 0.5, 0], [0.5, 0, 0.5]] self.NiO_AFM_001 = Structure(latt, species, coords) self.NiO_AFM_001.add_spin_by_site([-5, 5, 0, 0]) parser = CifParser(os.path.join(PymatgenTest.TEST_FILES_DIR, "Fe3O4.cif")) self.Fe3O4 = parser.get_structures()[0] trans = AutoOxiStateDecorationTransformation() self.Fe3O4_oxi = trans.apply_transformation(self.Fe3O4) parser = CifParser(os.path.join(PymatgenTest.TEST_FILES_DIR, "Li8Fe2NiCoO8.cif")) self.Li8Fe2NiCoO8 = parser.get_structures()[0] self.Li8Fe2NiCoO8.remove_oxidation_states() warnings.simplefilter("ignore")
def setUp(self): self.cscl = Structure.from_spacegroup("Pm-3m", Lattice.cubic(4.2), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.Fe = Structure.from_spacegroup(\ "Im-3m", Lattice.cubic(2.82), ["Fe"], [[0, 0, 0]]) self.lifepo4 = self.get_structure("LiFePO4") self.tei = Structure.from_file(get_path("icsd_TeI.cif"), primitive=False) self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50), ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]]) self.graphite = self.get_structure("Graphite")
def test_normal_search(self): fcc = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) for miller in [(1, 0, 0), (1, 1, 0), (1, 1, 1), (2, 1, 1)]: gen = SlabGenerator(fcc, miller, 10, 10) gen_normal = SlabGenerator(fcc, miller, 10, 10, max_normal_search=max(miller)) slab = gen_normal.get_slab() self.assertAlmostEqual(slab.lattice.alpha, 90) self.assertAlmostEqual(slab.lattice.beta, 90) self.assertGreaterEqual(len(gen_normal.oriented_unit_cell), len(gen.oriented_unit_cell)) graphite = self.get_structure("Graphite") for miller in [(1, 0, 0), (1, 1, 0), (0, 0, 1), (2, 1, 1)]: gen = SlabGenerator(graphite, miller, 10, 10) gen_normal = SlabGenerator(graphite, miller, 10, 10, max_normal_search=max(miller)) self.assertGreaterEqual(len(gen_normal.oriented_unit_cell), len(gen.oriented_unit_cell)) sc = Structure(Lattice.hexagonal(3.32, 5.15), ["Sc", "Sc"], [[1/3, 2/3, 0.25], [2/3, 1/3, 0.75]]) gen = SlabGenerator(sc, (1, 1, 1), 10, 10, max_normal_search=1) self.assertAlmostEqual(gen.oriented_unit_cell.lattice.angles[1], 90)
def test_kpath_generation(self): triclinic = [1, 2] monoclinic = range(3, 16) orthorhombic = range(16, 75) tetragonal = range(75, 143) rhombohedral = range(143, 168) hexagonal = range(168, 195) cubic = range(195, 231) species = ["K", "La", "Ti"] coords = [[0.345, 5, 0.77298], [0.1345, 5.1, 0.77298], [0.7, 0.8, 0.9]] for i in range(230): sg_num = i + 1 if sg_num in triclinic: lattice = Lattice( [[3.0233057319441246, 1, 0], [0, 7.9850357844548681, 1], [0, 1.2, 8.1136762279561818]] ) elif sg_num in monoclinic: lattice = Lattice.monoclinic(2, 9, 1, 99) elif sg_num in orthorhombic: lattice = Lattice.orthorhombic(2, 9, 1) elif sg_num in tetragonal: lattice = Lattice.tetragonal(2, 9) elif sg_num in rhombohedral: lattice = Lattice.hexagonal(2, 95) elif sg_num in hexagonal: lattice = Lattice.hexagonal(2, 9) elif sg_num in cubic: lattice = Lattice.cubic(2) struct = Structure.from_spacegroup(sg_num, lattice, species, coords) kpath = KPathSeek(struct) # Throws error if something doesn't work, causing test to fail.
def test_normal_search(self): fcc = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) for miller in [(1, 0, 0), (1, 1, 0), (1, 1, 1), (2, 1, 1)]: gen = SlabGenerator(fcc, miller, 10, 10) gen_normal = SlabGenerator(fcc, miller, 10, 10, max_normal_search=max(miller)) slab = gen_normal.get_slab() self.assertAlmostEqual(slab.lattice.alpha, 90) self.assertAlmostEqual(slab.lattice.beta, 90) self.assertGreaterEqual(len(gen_normal.oriented_unit_cell), len(gen.oriented_unit_cell)) graphite = self.get_structure("Graphite") for miller in [(1, 0, 0), (1, 1, 0), (0, 0, 1), (2, 1, 1)]: gen = SlabGenerator(graphite, miller, 10, 10) gen_normal = SlabGenerator(graphite, miller, 10, 10, max_normal_search=max(miller)) self.assertGreaterEqual(len(gen_normal.oriented_unit_cell), len(gen.oriented_unit_cell)) sc = Structure(Lattice.hexagonal(3.32, 5.15), ["Sc", "Sc"], [[1 / 3, 2 / 3, 0.25], [2 / 3, 1 / 3, 0.75]]) gen = SlabGenerator(sc, (1, 1, 1), 10, 10, max_normal_search=1) self.assertAlmostEqual(gen.oriented_unit_cell.lattice.angles[1], 90)
def test_kpath_generation(self): triclinic = [1, 2] monoclinic = range(3, 16) orthorhombic = range(16, 75) tetragonal = range(75, 143) rhombohedral = range(143, 168) hexagonal = range(168, 195) cubic = range(195, 231) species = ['K', 'La', 'Ti'] coords = [[.345, 5, .77298], [.1345, 5.1, .77298], [.7, .8, .9]] for i in range(230): sg_num = i + 1 if sg_num in triclinic: lattice = Lattice([[3.0233057319441246, 0, 0], [0, 7.9850357844548681, 0], [0, 0, 8.1136762279561818]]) elif sg_num in monoclinic: lattice = Lattice.monoclinic(2, 9, 1, 99) elif sg_num in orthorhombic: lattice = Lattice.orthorhombic(2, 9, 1) elif sg_num in tetragonal: lattice = Lattice.tetragonal(2, 9) elif sg_num in rhombohedral: lattice = Lattice.hexagonal(2, 95) elif sg_num in hexagonal: lattice = Lattice.hexagonal(2, 9) elif sg_num in cubic: lattice = Lattice.cubic(2) struct = Structure.from_spacegroup(sg_num, lattice, species, coords) kpath = HighSymmKpath(struct) # Throws error if something doesn't work, causing test to fail. struct_file_path = os.path.join(test_dir_structs, 'ICSD_170.cif') struct = Structure.from_file(struct_file_path) hkp = HighSymmKpath(struct) self.assertEqual(hkp.name, 'MCLC5')
def topology_from_string(cgd: str, spacegroups: Dict[str, int]) -> Tuple[str, Structure]: lines = cgd.splitlines() lines = [l[2:].split() for l in lines if len(l) > 2] elements = [] xyz = [] is_2D = False # might benefit from new case syntax in 3.10 for l in lines: if l[0].startswith("NAME"): name = l[1].strip() elif l[0].startswith("GROUP"): groupname = l[1].strip() if groupname not in spacegroups.keys(): return groupname, None sg = spacegroups[groupname] elif l[0].startswith("CELL"): parameters = [float(p) for p in l[1:]] if len(parameters) == 3: # 2D net, only one angle and two vectors. # need to be completed up to 6 parameters parameters = parameters[0:2] + [10.0, 90.0, 90.0 ] + parameters[2:] is_2D = True lattice = Lattice.from_parameters(*parameters) elif l[0].startswith("NODE"): elements.append(get_el_sp(int(l[2]))) xyz.append(numpy.array(l[3:], dtype=float)) elif l[0].startswith("EDGE_CENTER"): # add a linear connector, represented by He elements.append(get_el_sp(int(2))) xyz.append(numpy.array(l[1:], dtype=float)) elif l[0].startswith("EDGE"): # now we append some dummies s = int((len(l) - 1) / 2) midl = int((len(l) + 1) / 2) x0 = numpy.array(l[1:midl], dtype=float).reshape(-1, 1) x1 = numpy.array(l[midl:], dtype=float).reshape(-1, 1) xx = numpy.concatenate([x0, x1], axis=1).T com = xx.mean(axis=0) xx -= com xx = xx.dot(numpy.eye(s) * 0.5) xx += com dummy_element = get_el_sp("X") xyz += [xx[0], xx[1]] elements += [dummy_element, dummy_element] # concatenate the coordinates xyz = numpy.stack(xyz, axis=0) if is_2D: # node coordinates need to be padded xyz = numpy.pad(xyz, ((0, 0), (0, 1)), 'constant', constant_values=0.0) # generate the crystal topology = Structure.from_spacegroup(sg=sg, lattice=lattice, species=elements, coords=xyz) # remove any duplicate sites topology.merge_sites(tol=1e-3, mode="delete") return name, topology
def from_dict(cls, d): """ Creates a CTRL file object from a dictionary. The dictionary must contain the items "ALAT", PLAT" and "SITE". Valid dictionary items are: ALAT: the a-lattice parameter PLAT: (3x3) array for the lattice vectors SITE: list of dictionaries: {'ATOM': class label, 'POS': (3x1) array of fractional coordinates} CLASS (optional): list of unique atom labels as str SPCGRP (optional): space group symbol (str) or number (int) HEADER (optional): HEADER text as a str VERS (optional): LMTO version as a str Args: d: The CTRL file as a dictionary. Returns: An LMTOCtrl object. """ for cat in ["HEADER", "VERS"]: if cat not in d: d[cat] = None alat = d["ALAT"] * bohr_to_angstrom plat = d["PLAT"] * alat species = [] positions = [] for site in d["SITE"]: species.append(re.split("[0-9*]", site["ATOM"])[0]) positions.append(site["POS"] * alat) # Only check if the structure is to be generated from the space # group if the number of sites is the same as the number of classes. # If lattice and the spacegroup don't match, assume it's primitive. if "CLASS" in d and "SPCGRP" in d \ and len(d["SITE"]) == len(d["CLASS"]): try: structure = Structure.from_spacegroup( d["SPCGRP"], plat, species, positions, coords_are_cartesian=True) except ValueError: structure = Structure(plat, species, positions, coords_are_cartesian=True, to_unit_cell=True) else: structure = Structure(plat, species, positions, coords_are_cartesian=True, to_unit_cell=True) return cls(structure, header=d["HEADER"], version=d["VERS"])
def _get_structure_from_spcgrp(self): if 'A' not in self.lattice: raise AssertionError() if 'B' not in self.lattice: logging.info('Lattice vector B not given, assume equal to A') self.lattice['B'] = self.lattice['A'] if 'C' not in self.lattice: logging.info('Lattice vector C not given, assume equal to A') self.lattice['C'] = self.lattice['C'] if 'ALPHA' not in self.lattice: logging.info('Lattice angle ALPHA not given, assume right-angle') self.lattice['ALPHA'] = 90 if 'BETA' not in self.lattice: logging.info('Lattice angle BETA not given, assume right-angle') self.lattice['BETA'] = 90 if 'GAMMA' not in self.lattice: try: spcgrp_number = int(self.lattice['SPCGRP']) except ValueError: spcgrp_number = 0 if (167 < spcgrp_number < 195): logging.info('Lattice angle GAMMA not given, ' 'hexagonal space group, assume 120') self.lattice['GAMMA'] = 120 else: logging.info('Lattice angle GAMMA not given, ' 'assume right-angle') self.lattice['GAMMA'] = 90 if self.cartesian: logging.info("Warning: Cartesian positions used without " "explicit lattice vectors") if 'UNITS' not in self.lattice or self.lattice['UNITS'] is None: if self.ignore_units: pass else: for length in ('A', 'B', 'C'): self.lattice[length] *= _bohr_to_angstrom if 'ALAT' not in self.lattice: raise AssertionError() for length in ('A', 'B', 'C'): self.lattice[length] *= self.lattice['ALAT'] lattice = Lattice.from_parameters(self.lattice['A'], self.lattice['B'], self.lattice['C'], self.lattice['ALPHA'], self.lattice['BETA'], self.lattice['GAMMA']) species, coords = self._get_species_coords() return Structure.from_spacegroup(self.lattice['SPCGRP'], lattice, species, coords, coords_are_cartesian=self.cartesian, tol=self.tol)
def test_kpath_acentered(self): species = ["K", "La", "Ti"] coords = [[0.345, 5, 0.77298], [0.1345, 5.1, 0.77298], [0.7, 0.8, 0.9]] lattice = Lattice.orthorhombic(2, 9, 1) struct = Structure.from_spacegroup(38, lattice, species, coords) sga = SpacegroupAnalyzer(struct) struct_prim = sga.get_primitive_standard_structure(international_monoclinic=False) kpath = KPathLatimerMunro(struct_prim) kpoints = kpath._kpath["kpoints"] labels = list(kpoints.keys()) self.assertEqual( sorted(labels), sorted(["a", "b", "c", "d", "d_{1}", "e", "f", "q", "q_{1}", "Γ"]), ) self.assertAlmostEqual(kpoints["a"][0], 0.0) self.assertAlmostEqual(kpoints["a"][1], 0.4999999999999997) self.assertAlmostEqual(kpoints["a"][2], 0.0) self.assertAlmostEqual(kpoints["f"][0], -0.49999999999999933) self.assertAlmostEqual(kpoints["f"][1], 0.4999999999999992) self.assertAlmostEqual(kpoints["f"][2], 0.4999999999999999) self.assertAlmostEqual(kpoints["c"][0], 0.0) self.assertAlmostEqual(kpoints["c"][1], 0.0) self.assertAlmostEqual(kpoints["c"][2], 0.5) self.assertAlmostEqual(kpoints["b"][0], -0.5000000000000002) self.assertAlmostEqual(kpoints["b"][1], 0.500000000000000) self.assertAlmostEqual(kpoints["b"][2], 0.0) self.assertAlmostEqual(kpoints["Γ"][0], 0) self.assertAlmostEqual(kpoints["Γ"][1], 0) self.assertAlmostEqual(kpoints["Γ"][2], 0) self.assertAlmostEqual(kpoints["e"][0], 0.0) self.assertAlmostEqual(kpoints["e"][1], 0.49999999999999956) self.assertAlmostEqual(kpoints["e"][2], 0.5000000000000002) d = False if np.allclose(kpoints["d_{1}"], [0.2530864197530836, 0.25308641975308915, 0.0], atol=1e-5) or np.allclose( kpoints["d"], [0.2530864197530836, 0.25308641975308915, 0.0], atol=1e-5 ): d = True self.assertTrue(d) q = False if np.allclose(kpoints["q_{1}"], [0.2530864197530836, 0.25308641975308915, 0.5], atol=1e-5) or np.allclose( kpoints["q"], [0.2530864197530836, 0.25308641975308915, 0.5], atol=1e-5 ): q = True self.assertTrue(q)
def test_get_slabs(self): gen = SlabGenerator(self.get_structure("CsCl"), [0, 0, 1], 10, 10) #Test orthogonality of some internal variables. a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) self.assertEqual(len(gen.get_slabs()), 1) s = self.get_structure("LiFePO4") gen = SlabGenerator(s, [0, 0, 1], 10, 10) self.assertEqual(len(gen.get_slabs()), 5) self.assertEqual(len(gen.get_slabs(bonds={("P", "O"): 3})), 2) # There are no slabs in LFP that does not break either P-O or Fe-O # bonds for a miller index of [0, 0, 1]. self.assertEqual( len(gen.get_slabs(bonds={ ("P", "O"): 3, ("Fe", "O"): 3 })), 0) #If we allow some broken bonds, there are a few slabs. self.assertEqual( len( gen.get_slabs(bonds={ ("P", "O"): 3, ("Fe", "O"): 3 }, max_broken_bonds=2)), 2) # At this threshold, only the origin and center Li results in # clustering. All other sites are non-clustered. So the of # slabs is of sites in LiFePO4 unit cell - 2 + 1. self.assertEqual(len(gen.get_slabs(tol=1e-4)), 15) LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) gen = SlabGenerator(LiCoO2, [0, 0, 1], 10, 10) lco = gen.get_slabs(bonds={("Co", "O"): 3}) self.assertEqual(len(lco), 1) a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) scc = Structure.from_spacegroup("Pm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) gen = SlabGenerator(scc, [0, 0, 1], 10, 10) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1) gen = SlabGenerator(scc, [1, 1, 1], 10, 10, max_normal_search=1) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1)
def test_kpath_acentered(self): species = ["K", "La", "Ti"] coords = [[0.345, 5, 0.77298], [0.1345, 5.1, 0.77298], [0.7, 0.8, 0.9]] lattice = Lattice.orthorhombic(2, 9, 1) struct = Structure.from_spacegroup(38, lattice, species, coords) kpath = KPathSetyawanCurtarolo(struct) kpoints = kpath._kpath["kpoints"] labels = list(kpoints.keys()) self.assertEqual( sorted(labels), sorted( ["\\Gamma", "A", "A_1", "R", "S", "T", "X", "X_1", "Y", "Z"]), ) self.assertEqual(kpoints["\\Gamma"][0], 0.00000000) self.assertAlmostEqual(kpoints["\\Gamma"][1], 0.00000000) self.assertAlmostEqual(kpoints["\\Gamma"][2], 0.00000000) self.assertAlmostEqual(kpoints["A"][0], 0.25308642) self.assertAlmostEqual(kpoints["A"][1], 0.25308642) self.assertAlmostEqual(kpoints["A"][2], 0.50000000) self.assertAlmostEqual(kpoints["A_1"][0], -0.25308642) self.assertAlmostEqual(kpoints["A_1"][1], 0.74691358) self.assertAlmostEqual(kpoints["A_1"][2], 0.50000000) self.assertAlmostEqual(kpoints["R"][0], 0.00000000) self.assertAlmostEqual(kpoints["R"][1], 0.50000000) self.assertAlmostEqual(kpoints["R"][2], 0.50000000) self.assertAlmostEqual(kpoints["S"][0], 0.00000000) self.assertAlmostEqual(kpoints["S"][1], 0.50000000) self.assertAlmostEqual(kpoints["S"][2], 0.00000000) self.assertAlmostEqual(kpoints["T"][0], -0.50000000) self.assertAlmostEqual(kpoints["T"][1], 0.50000000) self.assertAlmostEqual(kpoints["T"][2], 0.50000000) self.assertAlmostEqual(kpoints["X"][0], 0.25308642) self.assertAlmostEqual(kpoints["X"][1], 0.25308642) self.assertAlmostEqual(kpoints["X"][2], 0.00000000) self.assertAlmostEqual(kpoints["X_1"][0], -0.25308642) self.assertAlmostEqual(kpoints["X_1"][1], 0.74691358) self.assertAlmostEqual(kpoints["X_1"][2], 0.00000000) self.assertAlmostEqual(kpoints["Y"][0], -0.50000000) self.assertAlmostEqual(kpoints["Y"][1], 0.50000000) self.assertAlmostEqual(kpoints["Y"][2], 0.00000000) self.assertAlmostEqual(kpoints["Z"][0], 0.00000000) self.assertAlmostEqual(kpoints["Z"][1], 0.00000000) self.assertAlmostEqual(kpoints["Z"][2], 0.50000000)
def test_kpath_acentered(self): species = ['K', 'La', 'Ti'] coords = [[.345, 5, .77298], [.1345, 5.1, .77298], [.7, .8, .9]] lattice = Lattice.orthorhombic(2, 9, 1) struct = Structure.from_spacegroup(38, lattice, species, coords) kpath = HighSymmKpath(struct) kpoints = kpath._kpath['kpoints'] labels = list(kpoints.keys()) self.assertEqual( sorted(labels), sorted( ['\\Gamma', 'A', 'A_1', 'R', 'S', 'T', 'X', 'X_1', 'Y', 'Z'])) self.assertEqual(kpoints['\\Gamma'][0], 0.00000000) self.assertAlmostEqual(kpoints['\\Gamma'][1], 0.00000000) self.assertAlmostEqual(kpoints['\\Gamma'][2], 0.00000000) self.assertAlmostEqual(kpoints['A'][0], 0.25308642) self.assertAlmostEqual(kpoints['A'][1], 0.25308642) self.assertAlmostEqual(kpoints['A'][2], 0.50000000) self.assertAlmostEqual(kpoints['A_1'][0], -0.25308642) self.assertAlmostEqual(kpoints['A_1'][1], 0.74691358) self.assertAlmostEqual(kpoints['A_1'][2], 0.50000000) self.assertAlmostEqual(kpoints['R'][0], 0.00000000) self.assertAlmostEqual(kpoints['R'][1], 0.50000000) self.assertAlmostEqual(kpoints['R'][2], 0.50000000) self.assertAlmostEqual(kpoints['S'][0], 0.00000000) self.assertAlmostEqual(kpoints['S'][1], 0.50000000) self.assertAlmostEqual(kpoints['S'][2], 0.00000000) self.assertAlmostEqual(kpoints['T'][0], -0.50000000) self.assertAlmostEqual(kpoints['T'][1], 0.50000000) self.assertAlmostEqual(kpoints['T'][2], 0.50000000) self.assertAlmostEqual(kpoints['X'][0], 0.25308642) self.assertAlmostEqual(kpoints['X'][1], 0.25308642) self.assertAlmostEqual(kpoints['X'][2], 0.00000000) self.assertAlmostEqual(kpoints['X_1'][0], -0.25308642) self.assertAlmostEqual(kpoints['X_1'][1], 0.74691358) self.assertAlmostEqual(kpoints['X_1'][2], 0.00000000) self.assertAlmostEqual(kpoints['Y'][0], -0.50000000) self.assertAlmostEqual(kpoints['Y'][1], 0.50000000) self.assertAlmostEqual(kpoints['Y'][2], 0.00000000) self.assertAlmostEqual(kpoints['Z'][0], 0.00000000) self.assertAlmostEqual(kpoints['Z'][1], 0.00000000) self.assertAlmostEqual(kpoints['Z'][2], 0.50000000)
def test_cell_scattering_factors(self): # Test that fcc structure gives 0 intensity for mixed even, odd hkl. c = TEMCalculator() nacl = Structure.from_spacegroup("Fm-3m", Lattice.cubic(5.692), ["Na", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) point = [(2, 1, 0)] spacings = c.get_interplanar_spacings(nacl, point) angles = c.bragg_angles(spacings) cellscatt = c.cell_scattering_factors(nacl, angles) self.assertAlmostEqual(cellscatt[(2, 1, 0)], 0)
def test_from_spacegroup(self): s1 = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Li", "O"], [[0.25, 0.25, 0.25], [0, 0, 0]]) self.assertEqual(s1.formula, "Li8 O4") s2 = Structure.from_spacegroup(225, Lattice.cubic(3), ["Li", "O"], [[0.25, 0.25, 0.25], [0, 0, 0]]) self.assertEqual(s1, s2) s2 = Structure.from_spacegroup(225, Lattice.cubic(3), ["Li", "O"], [[0.25, 0.25, 0.25], [0, 0, 0]], site_properties={"charge": [1, -2]}) self.assertEqual(sum(s2.site_properties["charge"]), 0) s = Structure.from_spacegroup("Pm-3m", Lattice.cubic(3), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.assertEqual(s.formula, "Cs1 Cl1") self.assertRaises(ValueError, Structure.from_spacegroup, "Pm-3m", Lattice.tetragonal(1, 3), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]])
def test_normal_search(self): fcc = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) for miller in [(1, 0, 0), (1, 1, 0), (1, 1, 1), (2, 1, 1)]: gen = SlabGenerator(fcc, miller, 10, 10) gen_normal = SlabGenerator(fcc, miller, 10, 10, max_normal_search=max(miller)) slab = gen_normal.get_slab() self.assertAlmostEqual(slab.lattice.alpha, 90) self.assertAlmostEqual(slab.lattice.beta, 90) self.assertGreaterEqual(len(gen_normal.oriented_unit_cell), len(gen.oriented_unit_cell))
def test_get_chemsys(self): # Test with structure struct = Structure.from_spacegroup('Fm-3m', Lattice.cubic(5.0), ['Ni', 'O'], [[0, 0, 0], [0.75, 0.25, 0.75]]) self.assertEqual(get_chemsys(struct), 'Ni-O') # Test sorting test_val = get_chemsys("TiO2") self.assertEqual(test_val, "O-Ti") test_val = get_chemsys("BaNiO3") self.assertEqual(test_val, "Ba-Ni-O")
def setUp(self): # set up a test structure, the coordinations are not correct and are only # for test purposes. structure = Structure.from_spacegroup( 225, [[5.7, 0, 0], [0, 5.7, 0], [0, 0, 5.7]], ["Na1+", "Cl1-"], [[0, 0, 0], [0.5, 0, 0]], ) all_sites_coordination = [{"Cl": 6}] * 4 + [{"Na": 8, "Cl": [6, 8]}] * 4 structure.add_site_property("coordination", all_sites_coordination) self.structures = {"test_structure": structure} self.nn_methods = [MinimumVIRENN(), EconNN()]
def test_kpath_acentered(self): species = ['K', 'La', 'Ti'] coords = [[.345, 5, .77298], [.1345, 5.1, .77298], [.7, .8, .9]] lattice = Lattice.orthorhombic(2, 9, 1) struct = Structure.from_spacegroup(38, lattice, species, coords) kpath = HighSymmKpath(struct) kpoints = kpath._kpath['kpoints'] labels = list(kpoints.keys()) self.assertEqual(sorted(labels), sorted(['\\Gamma', 'A', 'A_1', 'R', 'S', 'T', 'X', 'X_1', 'Y', 'Z'])) self.assertEqual(kpoints['\\Gamma'][0], 0.00000000) self.assertAlmostEqual(kpoints['\\Gamma'][1], 0.00000000) self.assertAlmostEqual(kpoints['\\Gamma'][2], 0.00000000) self.assertAlmostEqual(kpoints['A'][0], 0.25308642) self.assertAlmostEqual(kpoints['A'][1], 0.25308642) self.assertAlmostEqual(kpoints['A'][2], 0.50000000) self.assertAlmostEqual(kpoints['A_1'][0], -0.25308642) self.assertAlmostEqual(kpoints['A_1'][1], 0.74691358) self.assertAlmostEqual(kpoints['A_1'][2], 0.50000000) self.assertAlmostEqual(kpoints['R'][0], 0.00000000) self.assertAlmostEqual(kpoints['R'][1], 0.50000000) self.assertAlmostEqual(kpoints['R'][2], 0.50000000) self.assertAlmostEqual(kpoints['S'][0], 0.00000000) self.assertAlmostEqual(kpoints['S'][1], 0.50000000) self.assertAlmostEqual(kpoints['S'][2], 0.00000000) self.assertAlmostEqual(kpoints['T'][0], -0.50000000) self.assertAlmostEqual(kpoints['T'][1], 0.50000000) self.assertAlmostEqual(kpoints['T'][2], 0.50000000) self.assertAlmostEqual(kpoints['X'][0], 0.25308642) self.assertAlmostEqual(kpoints['X'][1], 0.25308642) self.assertAlmostEqual(kpoints['X'][2], 0.00000000) self.assertAlmostEqual(kpoints['X_1'][0], -0.25308642) self.assertAlmostEqual(kpoints['X_1'][1], 0.74691358) self.assertAlmostEqual(kpoints['X_1'][2], 0.00000000) self.assertAlmostEqual(kpoints['Y'][0], -0.50000000) self.assertAlmostEqual(kpoints['Y'][1], 0.50000000) self.assertAlmostEqual(kpoints['Y'][2], 0.00000000) self.assertAlmostEqual(kpoints['Z'][0], 0.00000000) self.assertAlmostEqual(kpoints['Z'][1], 0.00000000) self.assertAlmostEqual(kpoints['Z'][2], 0.50000000)
def test_md(self): s = Structure.from_spacegroup(225, Lattice.cubic(3.62126), ["Cu"], [[0, 0, 0]]) ld = LammpsData.from_structure(s, atom_style="atomic") ff = "\n".join(["pair_style eam", "pair_coeff * * Cu_u3.eam"]) md = LammpsRun.md(data=ld, force_field=ff, temperature=1600.0, nsteps=10000) md.write_inputs(output_dir="md") with open(os.path.join("md", "in.md")) as f: md_script = f.read() script_string = """# Sample input script template for MD # Initialization units metal atom_style atomic # Atom definition read_data md.data #read_restart md.restart # Force field settings (consult official document for detailed formats) pair_style eam pair_coeff * * Cu_u3.eam # Create velocities velocity all create 1600.0 142857 mom yes rot yes dist gaussian # Ensemble constraints #fix 1 all nve fix 1 all nvt temp 1600.0 1600.0 0.1 #fix 1 all npt temp 1600.0 1600.0 0.1 iso $pressure $pressure 1.0 # Various operations within timestepping #fix ... #compute ... # Output settings #thermo_style custom ... # control the thermo data type to output thermo 100 # output thermo data every N steps #dump 1 all atom 100 traj.*.gz # dump a snapshot every 100 steps # Actions run 10000 """ self.assertEqual(md_script, script_string) self.assertTrue(os.path.exists(os.path.join("md", "md.data")))
def setUp(self): self.cscl = Structure.from_spacegroup( "Pm-3m", Lattice.cubic(4.2), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.Fe = Structure.from_spacegroup( \ "Im-3m", Lattice.cubic(2.82), ["Fe"], [[0, 0, 0]]) self.lifepo4 = self.get_structure("LiFePO4") self.tei = Structure.from_file(get_path("icsd_TeI.cif"), primitive=False) self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50), ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]]) self.graphite = self.get_structure("Graphite") self.trigBi = Structure(Lattice.from_parameters(3, 3, 10, 90, 90, 120), ["Bi", "Bi", "Bi", "Bi", "Bi", "Bi"], [[0.3333, 0.6666, 0.39945113], [0.0000, 0.0000, 0.26721554], [0.0000, 0.0000, 0.73278446], [0.6666, 0.3333, 0.60054887], [0.6666, 0.3333, 0.06611779], [0.3333, 0.6666, 0.93388221]])
def test_get_slabs(self): gen = SlabGenerator(self.get_structure("CsCl"), [0, 0, 1], 10, 10) #Test orthogonality of some internal variables. a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) self.assertEqual(len(gen.get_slabs()), 1) s = self.get_structure("LiFePO4") gen = SlabGenerator(s, [0, 0, 1], 10, 10) self.assertEqual(len(gen.get_slabs()), 5) self.assertEqual(len(gen.get_slabs(bonds={("P", "O"): 3})), 2) # There are no slabs in LFP that does not break either P-O or Fe-O # bonds for a miller index of [0, 0, 1]. self.assertEqual(len(gen.get_slabs( bonds={("P", "O"): 3, ("Fe", "O"): 3})), 0) #If we allow some broken bonds, there are a few slabs. self.assertEqual(len(gen.get_slabs( bonds={("P", "O"): 3, ("Fe", "O"): 3}, max_broken_bonds=2)), 2) # At this threshold, only the origin and center Li results in # clustering. All other sites are non-clustered. So the of # slabs is of sites in LiFePO4 unit cell - 2 + 1. self.assertEqual(len(gen.get_slabs(tol=1e-4)), 15) LiCoO2=Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) gen = SlabGenerator(LiCoO2, [0, 0, 1], 10, 10) lco = gen.get_slabs(bonds={("Co", "O"): 3}) self.assertEqual(len(lco), 1) a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) scc = Structure.from_spacegroup("Pm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) gen = SlabGenerator(scc, [0, 0, 1], 10, 10) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1) gen = SlabGenerator(scc, [1, 1, 1], 10, 10, max_normal_search=1) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1)
def test_apply_transformation(self): s = self.get_structure("LiFePO4") trans = SlabTransformation([0, 0, 1], 10, 10, shift=0.25) gen = SlabGenerator(s, [0, 0, 1], 10, 10) slab_from_gen = gen.get_slab(0.25) slab_from_trans = trans.apply_transformation(s) self.assertArrayAlmostEqual(slab_from_gen.lattice.matrix, slab_from_trans.lattice.matrix) self.assertArrayAlmostEqual(slab_from_gen.cart_coords, slab_from_trans.cart_coords) fcc = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) trans = SlabTransformation([1, 1, 1], 10, 10) slab_from_trans = trans.apply_transformation(fcc) gen = SlabGenerator(fcc, [1, 1, 1], 10, 10) slab_from_gen = gen.get_slab() self.assertArrayAlmostEqual(slab_from_gen.lattice.matrix, slab_from_trans.lattice.matrix) self.assertArrayAlmostEqual(slab_from_gen.cart_coords, slab_from_trans.cart_coords)
def test_is_laue(self): s = Structure.from_spacegroup("Fm-3m", np.eye(3) * 3, ["Cu"], [[0, 0, 0]]) a = SpacegroupAnalyzer(s) self.assertTrue(a.is_laue())
def test_primitive(self): s = Structure.from_spacegroup("Fm-3m", np.eye(3) * 3, ["Cu"], [[0, 0, 0]]) a = SpacegroupAnalyzer(s) self.assertEqual(len(s), 4) self.assertEqual(len(a.find_primitive()), 1)
def setUp(self): self.maxDiff = None # trivial example, simple square lattice for testing structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H'], [[0, 0, 0]]) self.square_sg = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) #TODO: decorating still fails because the structure graph gives a CN of 8 for this square lattice # self.square_sg.decorate_structure_with_ce_info() # body-centered square lattice for testing structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H', 'He'], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.bc_square_sg = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(-1, -1, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) # body-centered square lattice for testing # directions reversed, should be equivalent to as bc_square structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H', 'He'], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.bc_square_sg_r = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) self.bc_square_sg_r.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(-1, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(-1, -1, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(0, -1, 0), to_jimage=(0, 0, 0)) # MoS2 example, structure graph obtained from critic2 # (not ground state, from mp-1023924, single layer) stdout_file = os.path.join(os.path.dirname(__file__), "..", "..", "..", 'test_files/critic2/MoS2_critic2_stdout.txt') with open(stdout_file, 'r') as f: reference_stdout = f.read() self.structure = Structure.from_file(os.path.join(os.path.dirname(__file__), "..", "..", "..", 'test_files/critic2/MoS2.cif')) c2o = Critic2Output(self.structure, reference_stdout) self.mos2_sg = c2o.structure_graph(edge_weight="bond_length", edge_weight_units="Å") latt = Lattice.cubic(4.17) species = ["Ni", "O"] coords = [[0, 0, 0], [0.5, 0.5, 0.5]] self.NiO = Structure.from_spacegroup(225, latt, species, coords).get_primitive_structure() # BCC example. self.bcc = Structure(Lattice.cubic(5.0), ['He', 'He'], [[0, 0, 0], [0.5, 0.5, 0.5]]) warnings.simplefilter("ignore")