def test_propertied_structure_mod(self): prop_structure = Structure(self.structure.lattice, ["Si"] * 2, self.structure.frac_coords, site_properties={'magmom': [5, -5]}) prop_structure.append("C", [0.25, 0.25, 0.25]) d = prop_structure.as_dict() with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") s2 = Structure.from_dict(d) self.assertEqual(len(w), 1) self.assertEqual( str(w[0].message), 'Not all sites have property magmom. Missing values are set ' 'to None.')
def test_propertied_structure_mod(self): prop_structure = Structure( self.structure.lattice, ["Si"] * 2, self.structure.frac_coords, site_properties={'magmom': [5, -5]}) prop_structure.append("C", [0.25, 0.25, 0.25]) d = prop_structure.as_dict() with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") s2 = Structure.from_dict(d) self.assertEqual(len(w), 1) self.assertEqual( str(w[0].message), 'Not all sites have property magmom. Missing values are set ' 'to None.')
def test_process_item(self): dummy_task = { "task_id": 1, "state": "successful", "orig_inputs": { "incar": { "IBRION": 2, "ISIF": 3, "NSW": 99 } }, "calcs_reversed": [{ "output": { "ionic_steps": [] } }] } coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = Lattice([[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]]) structure1 = Structure(lattice, ["Si", "Si"], coords) coords[1][0] = 0.0 structure2 = Structure(lattice, ["Si", "Si"], coords) dummy_task["calcs_reversed"][0]["input"] = { "incar": { "IBRION": 2, "ISIF": 3, "NSW": 99 } } ionic_steps = dummy_task["calcs_reversed"][0]["output"]["ionic_steps"] ionic_steps.append({"structure": structure1.as_dict()}) ionic_steps.append({"structure": structure1.as_dict()}) ml_strucs = self.builder.process_item(dummy_task) self.assertEqual(len(ml_strucs), 2)
class StructureTest(PymatgenTest): def setUp(self): coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = Lattice([[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]]) self.structure = Structure(lattice, ["Si", "Si"], coords) def test_mutable_sequence_methods(self): s = self.structure s[0] = "Fe" self.assertEqual(s.formula, "Fe1 Si1") s[0] = "Fe", [0.5, 0.5, 0.5] self.assertEqual(s.formula, "Fe1 Si1") self.assertArrayAlmostEqual(s[0].frac_coords, [0.5, 0.5, 0.5]) s.reverse() self.assertEqual(s[0].specie, Element("Si")) self.assertArrayAlmostEqual(s[0].frac_coords, [0.75, 0.5, 0.75]) s[0] = {"Mn": 0.5} self.assertEqual(s.formula, "Mn0.5 Fe1") del s[1] self.assertEqual(s.formula, "Mn0.5") s[0] = "Fe", [0.9, 0.9, 0.9], {"magmom": 5} self.assertEqual(s.formula, "Fe1") self.assertEqual(s[0].magmom, 5) def test_non_hash(self): self.assertRaises(TypeError, dict, [(self.structure, 1)]) def test_sort(self): s = self.structure s[0] = "F" s.sort() self.assertEqual(s[0].species_string, "Si") self.assertEqual(s[1].species_string, "F") s.sort(key=lambda site: site.species_string) self.assertEqual(s[0].species_string, "F") self.assertEqual(s[1].species_string, "Si") s.sort(key=lambda site: site.species_string, reverse=True) self.assertEqual(s[0].species_string, "Si") self.assertEqual(s[1].species_string, "F") def test_append_insert_remove_replace(self): s = self.structure s.insert(1, "O", [0.5, 0.5, 0.5]) self.assertEqual(s.formula, "Si2 O1") self.assertTrue(s.ntypesp == 2) self.assertTrue(s.symbol_set == ("Si", "O")) self.assertTrue(s.indices_from_symbol("Si") == (0,2)) self.assertTrue(s.indices_from_symbol("O") == (1,)) del s[2] self.assertEqual(s.formula, "Si1 O1") self.assertTrue(s.indices_from_symbol("Si") == (0,)) self.assertTrue(s.indices_from_symbol("O") == (1,)) s.append("N", [0.25, 0.25, 0.25]) self.assertEqual(s.formula, "Si1 N1 O1") self.assertTrue(s.ntypesp == 3) self.assertTrue(s.symbol_set == ("Si", "O", "N")) self.assertTrue(s.indices_from_symbol("Si") == (0,)) self.assertTrue(s.indices_from_symbol("O") == (1,)) self.assertTrue(s.indices_from_symbol("N") == (2,)) s[0] = "Ge" self.assertEqual(s.formula, "Ge1 N1 O1") self.assertTrue(s.symbol_set == ("Ge", "O", "N")) s.replace_species({"Ge": "Si"}) self.assertEqual(s.formula, "Si1 N1 O1") self.assertTrue(s.ntypesp == 3) s.replace_species({"Si": {"Ge": 0.5, "Si": 0.5}}) self.assertEqual(s.formula, "Si0.5 Ge0.5 N1 O1") #this should change the .5Si .5Ge sites to .75Si .25Ge s.replace_species({"Ge": {"Ge": 0.5, "Si": 0.5}}) self.assertEqual(s.formula, "Si0.75 Ge0.25 N1 O1") # In this case, s.ntypesp is ambiguous. # for the time being, we raise AttributeError. with self.assertRaises(AttributeError): s.ntypesp s.remove_species(["Si"]) self.assertEqual(s.formula, "Ge0.25 N1 O1") s.remove_sites([1, 2]) self.assertEqual(s.formula, "Ge0.25") def test_add_site_property(self): s = self.structure s.add_site_property("charge", [4.1, -5]) self.assertEqual(s[0].charge, 4.1) self.assertEqual(s[1].charge, -5) s.add_site_property("magmom", [3, 2]) self.assertEqual(s[0].charge, 4.1) self.assertEqual(s[0].magmom, 3) def test_propertied_structure(self): #Make sure that site properties are set to None for missing values. s = self.structure s.add_site_property("charge", [4.1, -5]) s.append("Li", [0.3, 0.3 ,0.3]) self.assertEqual(len(s.site_properties["charge"]), 3) def test_perturb(self): d = 0.1 pre_perturbation_sites = self.structure.sites[:] self.structure.perturb(distance=d) post_perturbation_sites = self.structure.sites for i, x in enumerate(pre_perturbation_sites): self.assertAlmostEqual(x.distance(post_perturbation_sites[i]), d, 3, "Bad perturbation distance") def test_add_oxidation_states(self): oxidation_states = {"Si": -4} self.structure.add_oxidation_state_by_element(oxidation_states) for site in self.structure: for k in site.species_and_occu.keys(): self.assertEqual(k.oxi_state, oxidation_states[k.symbol], "Wrong oxidation state assigned!") oxidation_states = {"Fe": 2} self.assertRaises(ValueError, self.structure.add_oxidation_state_by_element, oxidation_states) self.structure.add_oxidation_state_by_site([2, -4]) self.assertEqual(self.structure[0].specie.oxi_state, 2) self.assertRaises(ValueError, self.structure.add_oxidation_state_by_site, [1]) def test_remove_oxidation_states(self): co_elem = Element("Co") o_elem = Element("O") co_specie = Specie("Co", 2) o_specie = Specie("O", -2) coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = Lattice.cubic(10) s_elem = Structure(lattice, [co_elem, o_elem], coords) s_specie = Structure(lattice, [co_specie, o_specie], coords) s_specie.remove_oxidation_states() self.assertEqual(s_elem, s_specie, "Oxidation state remover " "failed") def test_apply_operation(self): op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 90) s = self.structure.copy() s.apply_operation(op) self.assertArrayAlmostEqual( s.lattice.matrix, [[0.000000, 3.840198, 0.000000], [-3.325710, 1.920099, 0.000000], [2.217138, -0.000000, 3.135509]], 5) op = SymmOp([[1, 1, 0, 0.5], [1, 0, 0, 0.5], [0, 0, 1, 0.5], [0, 0, 0, 1]]) s = self.structure.copy() s.apply_operation(op, fractional=True) self.assertArrayAlmostEqual( s.lattice.matrix, [[5.760297, 3.325710, 0.000000], [3.840198, 0.000000, 0.000000], [0.000000, -2.217138, 3.135509]], 5) def test_apply_strain(self): s = self.structure initial_coord = s[1].coords s.apply_strain(0.01) self.assertAlmostEqual( s.lattice.abc, (3.8785999130369997, 3.878600984287687, 3.8785999130549516)) self.assertArrayAlmostEqual(s[1].coords, initial_coord * 1.01) a1, b1, c1 = s.lattice.abc s.apply_strain([0.1, 0.2, 0.3]) a2, b2, c2 = s.lattice.abc self.assertAlmostEqual(a2 / a1, 1.1) self.assertAlmostEqual(b2 / b1, 1.2) self.assertAlmostEqual(c2 / c1, 1.3) def test_scale_lattice(self): initial_coord = self.structure[1].coords self.structure.scale_lattice(self.structure.volume * 1.01 ** 3) self.assertArrayAlmostEqual( self.structure.lattice.abc, (3.8785999130369997, 3.878600984287687, 3.8785999130549516)) self.assertArrayAlmostEqual(self.structure[1].coords, initial_coord * 1.01) def test_translate_sites(self): self.structure.translate_sites([0, 1], [0.5, 0.5, 0.5], frac_coords=True) self.assertArrayEqual(self.structure.frac_coords[0], [0.5, 0.5, 0.5]) self.structure.translate_sites([0], [0.5, 0.5, 0.5], frac_coords=False) self.assertArrayAlmostEqual(self.structure.cart_coords[0], [3.38014845, 1.05428585, 2.06775453]) self.structure.translate_sites([0], [0.5, 0.5, 0.5], frac_coords=True, to_unit_cell=False) self.assertArrayAlmostEqual(self.structure.frac_coords[0], [1.00187517, 1.25665291, 1.15946374]) def test_mul(self): self.structure *= [2, 1, 1] self.assertEqual(self.structure.formula, "Si4") s = [2, 1, 1] * self.structure self.assertEqual(s.formula, "Si8") self.assertIsInstance(s, Structure) s = self.structure * [[1, 0, 0], [2, 1, 0], [0, 0, 2]] self.assertEqual(s.formula, "Si8") self.assertArrayAlmostEqual(s.lattice.abc, [7.6803959, 17.5979979, 7.6803959]) def test_make_supercell(self): self.structure.make_supercell([2, 1, 1]) self.assertEqual(self.structure.formula, "Si4") self.structure.make_supercell([[1, 0, 0], [2, 1, 0], [0, 0, 1]]) self.assertEqual(self.structure.formula, "Si4") self.structure.make_supercell(2) self.assertEqual(self.structure.formula, "Si32") self.assertArrayAlmostEqual(self.structure.lattice.abc, [15.360792, 35.195996, 7.680396], 5) def test_disordered_supercell_primitive_cell(self): l = Lattice.cubic(2) f = [[0.5, 0.5, 0.5]] sp = [{'Si': 0.54738}] s = Structure(l, sp, f) #this supercell often breaks things s.make_supercell([[0,-1,1],[-1,1,0],[1,1,1]]) self.assertEqual(len(s.get_primitive_structure()), 1) def test_another_supercell(self): #this is included b/c for some reason the old algo was failing on it s = self.structure.copy() s.make_supercell([[0, 2, 2], [2, 0, 2], [2, 2, 0]]) self.assertEqual(s.formula, "Si32") s = self.structure.copy() s.make_supercell([[0, 2, 0], [1, 0, 0], [0, 0, 1]]) self.assertEqual(s.formula, "Si4") def test_to_from_dict(self): d = self.structure.as_dict() s2 = Structure.from_dict(d) self.assertEqual(type(s2), Structure) def test_to_from_file_string(self): for fmt in ["cif", "json", "poscar", "cssr", "yaml", "xsf"]: s = self.structure.to(fmt=fmt) self.assertIsNotNone(s) ss = Structure.from_str(s, fmt=fmt) self.assertArrayAlmostEqual( ss.lattice.lengths_and_angles, self.structure.lattice.lengths_and_angles, decimal=5) self.assertArrayAlmostEqual(ss.frac_coords, self.structure.frac_coords) self.assertIsInstance(ss, Structure) self.structure.to(filename="POSCAR.testing") self.assertTrue(os.path.exists("POSCAR.testing")) os.remove("POSCAR.testing") self.structure.to(filename="structure_testing.json") self.assertTrue(os.path.exists("structure_testing.json")) s = Structure.from_file("structure_testing.json") self.assertEqual(s, self.structure) os.remove("structure_testing.json") 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_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() 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]) def test_properties(self): self.assertEqual(self.structure.num_sites, len(self.structure)) self.structure.make_supercell(2) self.structure[1] = "C" sites = list(self.structure.group_by_types()) self.assertEqual(sites[-1].specie.symbol, "C") self.structure.add_oxidation_state_by_element({"Si": 4, "C": 2}) self.assertEqual(self.structure.charge, 62) def test_init_error(self): self.assertRaises(StructureError, Structure, Lattice.cubic(3), ["Si"], [[0, 0, 0], [0.5, 0.5, 0.5]]) def test_from_sites(self): self.structure.add_site_property("hello", [1, 2]) s = Structure.from_sites(self.structure, to_unit_cell=True) self.assertEqual(s.site_properties["hello"][1], 2) def test_magic(self): s = Structure.from_sites(self.structure) self.assertEqual(s, self.structure) self.assertNotEqual(s, None) s.apply_strain(0.5) self.assertNotEqual(s, self.structure) self.assertNotEqual(self.structure * 2, self.structure)
# standard Crystal Toolkit import import crystal_toolkit.components as ctc # create Dash app as normal app = dash.Dash() # create the Structure object structure = Structure(Lattice.cubic(4.2), ["Na", "K"], [[0, 0, 0], [0.5, 0.5, 0.5]]) from pymatgen.ext.matproj import MPRester # create an input structure as an example structure = MPRester().get_structure_by_material_id("mp-804") structure_in = dcc.Store(id="structure_in", data=structure.as_dict()) # patch, this should be a JSON component ... structure_in.id = lambda: "structure_in" # and the transformation component itself transformation_component = ctc.AllTransformationsComponent( transformations=[ "AutoOxiStateDecorationTransformationComponent", "SupercellTransformationComponent", # "SlabTransformationComponent", # "SubstitutionTransformationComponent", "CubicSupercellTransformationComponent", # "GrainBoundaryTransformationComponent" ], input_structure=structure_in, )
class StructureTest(PymatgenTest): def setUp(self): coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = Lattice([[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]]) self.structure = Structure(lattice, ["Si", "Si"], coords) def test_mutable_sequence_methods(self): s = self.structure s[0] = "Fe" self.assertEqual(s.formula, "Fe1 Si1") s[0] = "Fe", [0.5, 0.5, 0.5] self.assertEqual(s.formula, "Fe1 Si1") self.assertArrayAlmostEqual(s[0].frac_coords, [0.5, 0.5, 0.5]) s.reverse() self.assertEqual(s[0].specie, Element("Si")) self.assertArrayAlmostEqual(s[0].frac_coords, [0.75, 0.5, 0.75]) s[0] = {"Mn": 0.5} self.assertEqual(s.formula, "Mn0.5 Fe1") del s[1] self.assertEqual(s.formula, "Mn0.5") s[0] = "Fe", [0.9, 0.9, 0.9], {"magmom": 5} self.assertEqual(s.formula, "Fe1") self.assertEqual(s[0].magmom, 5) # Test atomic replacement. s["Fe"] = "Mn" self.assertEqual(s.formula, "Mn1") # Test slice replacement. s = PymatgenTest.get_structure("Li2O") s[1:3] = "S" self.assertEqual(s.formula, "Li1 S2") def test_non_hash(self): self.assertRaises(TypeError, dict, [(self.structure, 1)]) def test_sort(self): s = self.structure s[0] = "F" s.sort() self.assertEqual(s[0].species_string, "Si") self.assertEqual(s[1].species_string, "F") s.sort(key=lambda site: site.species_string) self.assertEqual(s[0].species_string, "F") self.assertEqual(s[1].species_string, "Si") s.sort(key=lambda site: site.species_string, reverse=True) self.assertEqual(s[0].species_string, "Si") self.assertEqual(s[1].species_string, "F") def test_append_insert_remove_replace(self): s = self.structure s.insert(1, "O", [0.5, 0.5, 0.5]) self.assertEqual(s.formula, "Si2 O1") self.assertTrue(s.ntypesp == 2) self.assertTrue(s.symbol_set == ("Si", "O")) self.assertTrue(s.indices_from_symbol("Si") == (0, 2)) self.assertTrue(s.indices_from_symbol("O") == (1, )) del s[2] self.assertEqual(s.formula, "Si1 O1") self.assertTrue(s.indices_from_symbol("Si") == (0, )) self.assertTrue(s.indices_from_symbol("O") == (1, )) s.append("N", [0.25, 0.25, 0.25]) self.assertEqual(s.formula, "Si1 N1 O1") self.assertTrue(s.ntypesp == 3) self.assertTrue(s.symbol_set == ("Si", "O", "N")) self.assertTrue(s.indices_from_symbol("Si") == (0, )) self.assertTrue(s.indices_from_symbol("O") == (1, )) self.assertTrue(s.indices_from_symbol("N") == (2, )) s[0] = "Ge" self.assertEqual(s.formula, "Ge1 N1 O1") self.assertTrue(s.symbol_set == ("Ge", "O", "N")) s.replace_species({"Ge": "Si"}) self.assertEqual(s.formula, "Si1 N1 O1") self.assertTrue(s.ntypesp == 3) s.replace_species({"Si": {"Ge": 0.5, "Si": 0.5}}) self.assertEqual(s.formula, "Si0.5 Ge0.5 N1 O1") #this should change the .5Si .5Ge sites to .75Si .25Ge s.replace_species({"Ge": {"Ge": 0.5, "Si": 0.5}}) self.assertEqual(s.formula, "Si0.75 Ge0.25 N1 O1") # In this case, s.ntypesp is ambiguous. # for the time being, we raise AttributeError. with self.assertRaises(AttributeError): s.ntypesp s.remove_species(["Si"]) self.assertEqual(s.formula, "Ge0.25 N1 O1") s.remove_sites([1, 2]) self.assertEqual(s.formula, "Ge0.25") def test_add_site_property(self): s = self.structure s.add_site_property("charge", [4.1, -5]) self.assertEqual(s[0].charge, 4.1) self.assertEqual(s[1].charge, -5) s.add_site_property("magmom", [3, 2]) self.assertEqual(s[0].charge, 4.1) self.assertEqual(s[0].magmom, 3) def test_propertied_structure(self): #Make sure that site properties are set to None for missing values. s = self.structure s.add_site_property("charge", [4.1, -5]) s.append("Li", [0.3, 0.3, 0.3]) self.assertEqual(len(s.site_properties["charge"]), 3) def test_perturb(self): d = 0.1 pre_perturbation_sites = self.structure.sites[:] self.structure.perturb(distance=d) post_perturbation_sites = self.structure.sites for i, x in enumerate(pre_perturbation_sites): self.assertAlmostEqual(x.distance(post_perturbation_sites[i]), d, 3, "Bad perturbation distance") def test_add_oxidation_states(self): oxidation_states = {"Si": -4} self.structure.add_oxidation_state_by_element(oxidation_states) for site in self.structure: for k in site.species_and_occu.keys(): self.assertEqual(k.oxi_state, oxidation_states[k.symbol], "Wrong oxidation state assigned!") oxidation_states = {"Fe": 2} self.assertRaises(ValueError, self.structure.add_oxidation_state_by_element, oxidation_states) self.structure.add_oxidation_state_by_site([2, -4]) self.assertEqual(self.structure[0].specie.oxi_state, 2) self.assertRaises(ValueError, self.structure.add_oxidation_state_by_site, [1]) def test_remove_oxidation_states(self): co_elem = Element("Co") o_elem = Element("O") co_specie = Specie("Co", 2) o_specie = Specie("O", -2) coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = Lattice.cubic(10) s_elem = Structure(lattice, [co_elem, o_elem], coords) s_specie = Structure(lattice, [co_specie, o_specie], coords) s_specie.remove_oxidation_states() self.assertEqual(s_elem, s_specie, "Oxidation state remover " "failed") def test_apply_operation(self): op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 90) s = self.structure.copy() s.apply_operation(op) self.assertArrayAlmostEqual( s.lattice.matrix, [[0.000000, 3.840198, 0.000000], [-3.325710, 1.920099, 0.000000], [2.217138, -0.000000, 3.135509]], 5) op = SymmOp([[1, 1, 0, 0.5], [1, 0, 0, 0.5], [0, 0, 1, 0.5], [0, 0, 0, 1]]) s = self.structure.copy() s.apply_operation(op, fractional=True) self.assertArrayAlmostEqual( s.lattice.matrix, [[5.760297, 3.325710, 0.000000], [3.840198, 0.000000, 0.000000], [0.000000, -2.217138, 3.135509]], 5) def test_apply_strain(self): s = self.structure initial_coord = s[1].coords s.apply_strain(0.01) self.assertAlmostEqual( s.lattice.abc, (3.8785999130369997, 3.878600984287687, 3.8785999130549516)) self.assertArrayAlmostEqual(s[1].coords, initial_coord * 1.01) a1, b1, c1 = s.lattice.abc s.apply_strain([0.1, 0.2, 0.3]) a2, b2, c2 = s.lattice.abc self.assertAlmostEqual(a2 / a1, 1.1) self.assertAlmostEqual(b2 / b1, 1.2) self.assertAlmostEqual(c2 / c1, 1.3) def test_scale_lattice(self): initial_coord = self.structure[1].coords self.structure.scale_lattice(self.structure.volume * 1.01**3) self.assertArrayAlmostEqual( self.structure.lattice.abc, (3.8785999130369997, 3.878600984287687, 3.8785999130549516)) self.assertArrayAlmostEqual(self.structure[1].coords, initial_coord * 1.01) def test_translate_sites(self): self.structure.translate_sites([0, 1], [0.5, 0.5, 0.5], frac_coords=True) self.assertArrayEqual(self.structure.frac_coords[0], [0.5, 0.5, 0.5]) self.structure.translate_sites([0], [0.5, 0.5, 0.5], frac_coords=False) self.assertArrayAlmostEqual(self.structure.cart_coords[0], [3.38014845, 1.05428585, 2.06775453]) self.structure.translate_sites([0], [0.5, 0.5, 0.5], frac_coords=True, to_unit_cell=False) self.assertArrayAlmostEqual(self.structure.frac_coords[0], [1.00187517, 1.25665291, 1.15946374]) def test_mul(self): self.structure *= [2, 1, 1] self.assertEqual(self.structure.formula, "Si4") s = [2, 1, 1] * self.structure self.assertEqual(s.formula, "Si8") self.assertIsInstance(s, Structure) s = self.structure * [[1, 0, 0], [2, 1, 0], [0, 0, 2]] self.assertEqual(s.formula, "Si8") self.assertArrayAlmostEqual(s.lattice.abc, [7.6803959, 17.5979979, 7.6803959]) def test_make_supercell(self): self.structure.make_supercell([2, 1, 1]) self.assertEqual(self.structure.formula, "Si4") self.structure.make_supercell([[1, 0, 0], [2, 1, 0], [0, 0, 1]]) self.assertEqual(self.structure.formula, "Si4") self.structure.make_supercell(2) self.assertEqual(self.structure.formula, "Si32") self.assertArrayAlmostEqual(self.structure.lattice.abc, [15.360792, 35.195996, 7.680396], 5) def test_disordered_supercell_primitive_cell(self): l = Lattice.cubic(2) f = [[0.5, 0.5, 0.5]] sp = [{'Si': 0.54738}] s = Structure(l, sp, f) #this supercell often breaks things s.make_supercell([[0, -1, 1], [-1, 1, 0], [1, 1, 1]]) self.assertEqual(len(s.get_primitive_structure()), 1) def test_another_supercell(self): #this is included b/c for some reason the old algo was failing on it s = self.structure.copy() s.make_supercell([[0, 2, 2], [2, 0, 2], [2, 2, 0]]) self.assertEqual(s.formula, "Si32") s = self.structure.copy() s.make_supercell([[0, 2, 0], [1, 0, 0], [0, 0, 1]]) self.assertEqual(s.formula, "Si4") def test_to_from_dict(self): d = self.structure.as_dict() s2 = Structure.from_dict(d) self.assertEqual(type(s2), Structure) def test_to_from_abivars(self): """Test as_dict, from_dict with fmt == abivars.""" d = self.structure.as_dict(fmt="abivars") s2 = Structure.from_dict(d, fmt="abivars") self.assertEqual(s2, self.structure) self.assertEqual(type(s2), Structure) def test_to_from_file_string(self): for fmt in ["cif", "json", "poscar", "cssr", "yaml", "xsf"]: s = self.structure.to(fmt=fmt) self.assertIsNotNone(s) ss = Structure.from_str(s, fmt=fmt) self.assertArrayAlmostEqual( ss.lattice.lengths_and_angles, self.structure.lattice.lengths_and_angles, decimal=5) self.assertArrayAlmostEqual(ss.frac_coords, self.structure.frac_coords) self.assertIsInstance(ss, Structure) self.structure.to(filename="POSCAR.testing") self.assertTrue(os.path.exists("POSCAR.testing")) os.remove("POSCAR.testing") self.structure.to(filename="structure_testing.json") self.assertTrue(os.path.exists("structure_testing.json")) s = Structure.from_file("structure_testing.json") self.assertEqual(s, self.structure) os.remove("structure_testing.json") 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_from_magnetic_spacegroup(self): # AFM MnF s1 = Structure.from_magnetic_spacegroup( "P4_2'/mnm'", Lattice.tetragonal(4.87, 3.30), ["Mn", "F"], [[0, 0, 0], [0.30, 0.30, 0.00]], {'magmom': [4, 0]}) self.assertEqual(s1.formula, "Mn2 F4") self.assertEqual(sum(map(float, s1.site_properties['magmom'])), 0) self.assertEqual(max(map(float, s1.site_properties['magmom'])), 4) self.assertEqual(min(map(float, s1.site_properties['magmom'])), -4) # AFM LaMnO3, ordered on (001) planes s2 = Structure.from_magnetic_spacegroup( "Pn'ma'", Lattice.orthorhombic(5.75, 7.66, 5.53), ["La", "Mn", "O", "O"], [[0.05, 0.25, 0.99], [0.00, 0.00, 0.50], [0.48, 0.25, 0.08], [0.31, 0.04, 0.72]], {'magmom': [0, Magmom([4, 0, 0]), 0, 0]}) self.assertEqual(s2.formula, "La4 Mn4 O12") self.assertEqual(sum(map(float, s2.site_properties['magmom'])), 0) self.assertEqual(max(map(float, s2.site_properties['magmom'])), 4) self.assertEqual(min(map(float, s2.site_properties['magmom'])), -4) 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_properties(self): self.assertEqual(self.structure.num_sites, len(self.structure)) self.structure.make_supercell(2) self.structure[1] = "C" sites = list(self.structure.group_by_types()) self.assertEqual(sites[-1].specie.symbol, "C") self.structure.add_oxidation_state_by_element({"Si": 4, "C": 2}) self.assertEqual(self.structure.charge, 62) def test_set_item(self): s = self.structure.copy() s[0] = "C" self.assertEqual(s.formula, "Si1 C1") s[(0, 1)] = "Ge" self.assertEqual(s.formula, "Ge2") s[0:2] = "Sn" self.assertEqual(s.formula, "Sn2") s = self.structure.copy() s["Si"] = "C" self.assertEqual(s.formula, "C2") s["C"] = "C0.25Si0.5" self.assertEqual(s.formula, "Si1 C0.5") s["C"] = "C0.25Si0.5" self.assertEqual(s.formula, "Si1.25 C0.125") def test_init_error(self): self.assertRaises(StructureError, Structure, Lattice.cubic(3), ["Si"], [[0, 0, 0], [0.5, 0.5, 0.5]]) def test_from_sites(self): self.structure.add_site_property("hello", [1, 2]) s = Structure.from_sites(self.structure, to_unit_cell=True) self.assertEqual(s.site_properties["hello"][1], 2) def test_magic(self): s = Structure.from_sites(self.structure) self.assertEqual(s, self.structure) self.assertNotEqual(s, None) s.apply_strain(0.5) self.assertNotEqual(s, self.structure) self.assertNotEqual(self.structure * 2, self.structure)
class StructureTest(PymatgenTest): def setUp(self): coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = Lattice([[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]]) self.structure = Structure(lattice, ["Si", "Si"], coords) def test_mutable_sequence_methods(self): s = self.structure s[0] = "Fe" self.assertEqual(s.formula, "Fe1 Si1") s[0] = "Fe", [0.5, 0.5, 0.5] self.assertEqual(s.formula, "Fe1 Si1") self.assertArrayAlmostEqual(s[0].frac_coords, [0.5, 0.5, 0.5]) s.reverse() self.assertEqual(s[0].specie, Element("Si")) self.assertArrayAlmostEqual(s[0].frac_coords, [0.75, 0.5, 0.75]) s[0] = {"Mn": 0.5} self.assertEqual(s.formula, "Mn0.5 Fe1") del s[1] self.assertEqual(s.formula, "Mn0.5") s[0] = "Fe", [0.9, 0.9, 0.9], {"magmom": 5} self.assertEqual(s.formula, "Fe1") self.assertEqual(s[0].magmom, 5) def test_non_hash(self): self.assertRaises(TypeError, dict, [(self.structure, 1)]) def test_sort(self): s = self.structure s[0] = "F" s.sort() self.assertEqual(s[0].species_string, "Si") self.assertEqual(s[1].species_string, "F") s.sort(key=lambda site: site.species_string) self.assertEqual(s[0].species_string, "F") self.assertEqual(s[1].species_string, "Si") s.sort(key=lambda site: site.species_string, reverse=True) self.assertEqual(s[0].species_string, "Si") self.assertEqual(s[1].species_string, "F") def test_append_insert_remove_replace(self): s = self.structure s.insert(1, "O", [0.5, 0.5, 0.5]) self.assertEqual(s.formula, "Si2 O1") self.assertTrue(s.ntypesp == 2) self.assertTrue(s.symbol_set == ("Si", "O")) self.assertTrue(s.indices_from_symbol("Si") == (0, 2)) self.assertTrue(s.indices_from_symbol("O") == (1, )) del s[2] self.assertEqual(s.formula, "Si1 O1") self.assertTrue(s.indices_from_symbol("Si") == (0, )) self.assertTrue(s.indices_from_symbol("O") == (1, )) s.append("N", [0.25, 0.25, 0.25]) self.assertEqual(s.formula, "Si1 N1 O1") self.assertTrue(s.ntypesp == 3) self.assertTrue(s.symbol_set == ("Si", "O", "N")) self.assertTrue(s.indices_from_symbol("Si") == (0, )) self.assertTrue(s.indices_from_symbol("O") == (1, )) self.assertTrue(s.indices_from_symbol("N") == (2, )) s[0] = "Ge" self.assertEqual(s.formula, "Ge1 N1 O1") self.assertTrue(s.symbol_set == ("Ge", "O", "N")) s.replace_species({"Ge": "Si"}) self.assertEqual(s.formula, "Si1 N1 O1") self.assertTrue(s.ntypesp == 3) s.replace_species({"Si": {"Ge": 0.5, "Si": 0.5}}) self.assertEqual(s.formula, "Si0.5 Ge0.5 N1 O1") #this should change the .5Si .5Ge sites to .75Si .25Ge s.replace_species({"Ge": {"Ge": 0.5, "Si": 0.5}}) self.assertEqual(s.formula, "Si0.75 Ge0.25 N1 O1") # In this case, s.ntypesp is ambiguous. # for the time being, we raise AttributeError. with self.assertRaises(AttributeError): s.ntypesp s.remove_species(["Si"]) self.assertEqual(s.formula, "Ge0.25 N1 O1") s.remove_sites([1, 2]) self.assertEqual(s.formula, "Ge0.25") def test_add_site_property(self): s = self.structure s.add_site_property("charge", [4.1, -5]) self.assertEqual(s[0].charge, 4.1) self.assertEqual(s[1].charge, -5) s.add_site_property("magmom", [3, 2]) self.assertEqual(s[0].charge, 4.1) self.assertEqual(s[0].magmom, 3) def test_propertied_structure(self): #Make sure that site properties are set to None for missing values. s = self.structure s.add_site_property("charge", [4.1, -5]) s.append("Li", [0.3, 0.3, 0.3]) self.assertEqual(len(s.site_properties["charge"]), 3) def test_perturb(self): d = 0.1 pre_perturbation_sites = self.structure.sites[:] self.structure.perturb(distance=d) post_perturbation_sites = self.structure.sites for i, x in enumerate(pre_perturbation_sites): self.assertAlmostEqual(x.distance(post_perturbation_sites[i]), d, 3, "Bad perturbation distance") def test_add_oxidation_states(self): oxidation_states = {"Si": -4} self.structure.add_oxidation_state_by_element(oxidation_states) for site in self.structure: for k in site.species_and_occu.keys(): self.assertEqual(k.oxi_state, oxidation_states[k.symbol], "Wrong oxidation state assigned!") oxidation_states = {"Fe": 2} self.assertRaises(ValueError, self.structure.add_oxidation_state_by_element, oxidation_states) self.structure.add_oxidation_state_by_site([2, -4]) self.assertEqual(self.structure[0].specie.oxi_state, 2) self.assertRaises(ValueError, self.structure.add_oxidation_state_by_site, [1]) def test_remove_oxidation_states(self): co_elem = Element("Co") o_elem = Element("O") co_specie = Specie("Co", 2) o_specie = Specie("O", -2) coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = Lattice.cubic(10) s_elem = Structure(lattice, [co_elem, o_elem], coords) s_specie = Structure(lattice, [co_specie, o_specie], coords) s_specie.remove_oxidation_states() self.assertEqual(s_elem, s_specie, "Oxidation state remover " "failed") def test_apply_operation(self): op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 90) self.structure.apply_operation(op) self.assertArrayAlmostEqual( self.structure.lattice.matrix, [[0.000000, 3.840198, 0.000000], [-3.325710, 1.920099, 0.000000], [2.217138, -0.000000, 3.135509]], 5) def test_apply_strain(self): s = self.structure initial_coord = s[1].coords s.apply_strain(0.01) self.assertAlmostEqual( s.lattice.abc, (3.8785999130369997, 3.878600984287687, 3.8785999130549516)) self.assertArrayAlmostEqual(s[1].coords, initial_coord * 1.01) a1, b1, c1 = s.lattice.abc s.apply_strain([0.1, 0.2, 0.3]) a2, b2, c2 = s.lattice.abc self.assertAlmostEqual(a2 / a1, 1.1) self.assertAlmostEqual(b2 / b1, 1.2) self.assertAlmostEqual(c2 / c1, 1.3) def test_scale_lattice(self): initial_coord = self.structure[1].coords self.structure.scale_lattice(self.structure.volume * 1.01**3) self.assertArrayAlmostEqual( self.structure.lattice.abc, (3.8785999130369997, 3.878600984287687, 3.8785999130549516)) self.assertArrayAlmostEqual(self.structure[1].coords, initial_coord * 1.01) def test_translate_sites(self): self.structure.translate_sites([0, 1], [0.5, 0.5, 0.5], frac_coords=True) self.assertArrayEqual(self.structure.frac_coords[0], [0.5, 0.5, 0.5]) self.structure.translate_sites([0], [0.5, 0.5, 0.5], frac_coords=False) self.assertArrayAlmostEqual(self.structure.cart_coords[0], [3.38014845, 1.05428585, 2.06775453]) self.structure.translate_sites([0], [0.5, 0.5, 0.5], frac_coords=True, to_unit_cell=False) self.assertArrayAlmostEqual(self.structure.frac_coords[0], [1.00187517, 1.25665291, 1.15946374]) def test_make_supercell(self): self.structure.make_supercell([2, 1, 1]) self.assertEqual(self.structure.formula, "Si4") self.structure.make_supercell([[1, 0, 0], [2, 1, 0], [0, 0, 1]]) self.assertEqual(self.structure.formula, "Si4") self.structure.make_supercell(2) self.assertEqual(self.structure.formula, "Si32") self.assertArrayAlmostEqual(self.structure.lattice.abc, [15.360792, 35.195996, 7.680396], 5) def test_disordered_supercell_primitive_cell(self): l = Lattice.cubic(2) f = [[0.5, 0.5, 0.5]] sp = [{'Si': 0.54738}] s = Structure(l, sp, f) #this supercell often breaks things s.make_supercell([[0, -1, 1], [-1, 1, 0], [1, 1, 1]]) self.assertEqual(len(s.get_primitive_structure()), 1) def test_another_supercell(self): #this is included b/c for some reason the old algo was failing on it s = self.structure.copy() s.make_supercell([[0, 2, 2], [2, 0, 2], [2, 2, 0]]) self.assertEqual(s.formula, "Si32") s = self.structure.copy() s.make_supercell([[0, 2, 0], [1, 0, 0], [0, 0, 1]]) self.assertEqual(s.formula, "Si4") def test_to_from_dict(self): d = self.structure.as_dict() s2 = Structure.from_dict(d) self.assertEqual(type(s2), Structure) def test_propertied_structure_mod(self): prop_structure = Structure(self.structure.lattice, ["Si"] * 2, self.structure.frac_coords, site_properties={'magmom': [5, -5]}) prop_structure.append("C", [0.25, 0.25, 0.25]) d = prop_structure.as_dict() with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") s2 = Structure.from_dict(d) self.assertEqual(len(w), 1) self.assertEqual( str(w[0].message), 'Not all sites have property magmom. Missing values are set ' 'to None.') def test_to_from_file_string(self): for fmt in ["cif", "json", "poscar", "cssr", "yaml"]: s = self.structure.to(fmt=fmt) self.assertIsNotNone(s) ss = Structure.from_str(s, fmt=fmt) self.assertArrayAlmostEqual( ss.lattice.lengths_and_angles, self.structure.lattice.lengths_and_angles, decimal=5) self.assertArrayAlmostEqual(ss.frac_coords, self.structure.frac_coords) self.assertIsInstance(ss, Structure) self.structure.to(filename="POSCAR.testing") self.assertTrue(os.path.exists("POSCAR.testing")) os.remove("POSCAR.testing") self.structure.to(filename="structure_testing.json") self.assertTrue(os.path.exists("structure_testing.json")) s = Structure.from_file("structure_testing.json") self.assertEqual(s, self.structure) os.remove("structure_testing.json") 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_merge_sites(self): species = [{'Ag': 0.5}, {'Cl': 0.35}, {'Ag': 0.5}, {'F': 0.25}] coords = [[0, 0, 0], [0.5, 0.5, 0.5], [0, 0, 0], [0.5, 0.5, 1.501]] s = Structure(Lattice.cubic(1), species, coords) s.merge_sites() 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])