Beispiel #1
0
    def add_snl(self, snl, force_new=False, snlgroup_guess=None):
        try:
            self.lock_db()
            snl_id = self._get_next_snl_id()

            spstruc = snl.structure.copy()
            spstruc.remove_oxidation_states()
            sf = SpacegroupAnalyzer(spstruc, SPACEGROUP_TOLERANCE)
            sf.get_space_group_operations()
            sgnum = sf.get_space_group_number() if sf.get_space_group_number() \
                else -1
            sgsym = sf.get_space_group_symbol() if sf.get_space_group_symbol() \
                else 'unknown'
            sghall = sf.get_hall() if sf.get_hall() else 'unknown'
            sgxtal = sf.get_crystal_system() if sf.get_crystal_system() \
                else 'unknown'
            sglatt = sf.get_lattice_type() if sf.get_lattice_type() else 'unknown'
            sgpoint = sf.get_point_group_symbol()

            mpsnl = MPStructureNL.from_snl(snl, snl_id, sgnum, sgsym, sghall,
                                           sgxtal, sglatt, sgpoint)
            snlgroup, add_new, spec_group = self.add_mpsnl(mpsnl, force_new, snlgroup_guess)
            self.release_lock()
            return mpsnl, snlgroup.snlgroup_id, spec_group
        except:
            self.release_lock()
            traceback.print_exc()
            raise ValueError("Error while adding SNL!")
Beispiel #2
0
 def test_tricky_structure(self):
     # for some reason this structure kills spglib1.9
     # 1.7 can't find symmetry either, but at least doesn't kill python
     s = Structure.from_file(os.path.join(test_dir, 'POSCAR.tricky_symmetry'))
     sa = SpacegroupAnalyzer(s, 0.1)
     sa.get_spacegroup_symbol()
     sa.get_spacegroup_number()
     sa.get_point_group()
     sa.get_crystal_system()
     sa.get_hall()
Beispiel #3
0
    def set_material_data_from_structure(self, structure, space_group=True, symprec=1e-3, angle_tolerance=5):
        """
        Sets the fields of the Document using a Structure and Spglib to determine the space group properties

        Args:
            structure: A |Structure|
            space_group: if True sets the spacegroup fields using spglib_.
            symprec (float): Tolerance for symmetry finding.
            angle_tolerance (float): Angle tolerance for symmetry finding.
        """

        comp = structure.composition
        el_amt = structure.composition.get_el_amt_dict()
        self.unit_cell_formula = comp.as_dict()
        self.reduced_cell_formula = comp.to_reduced_dict
        self.elements = list(el_amt.keys())
        self.nelements = len(el_amt)
        self.pretty_formula = comp.reduced_formula
        self.anonymous_formula = comp.anonymized_formula
        self.nsites = comp.num_atoms
        self.chemsys = "-".join(sorted(el_amt.keys()))
        if space_group:
            sym = SpacegroupAnalyzer(structure, symprec=symprec, angle_tolerance=angle_tolerance)
            self.spacegroup = SpaceGroupDocument(crystal_system=sym.get_crystal_system(), hall=sym.get_hall(),
                                                 number=sym.get_space_group_number(), point_group=sym.get_point_group_symbol(),
                                                 symbol=sym.get_space_group_symbol(), source="spglib")
Beispiel #4
0
 def set_space_group_from_structure(self, structure):
     spga = SpacegroupAnalyzer(structure=structure)
     self.crystal_system = spga.get_crystal_system()
     self.hall = spga.get_hall()
     self.number = spga.get_space_group_number()
     self.source = "spglib"
     self.symbol = spga.get_space_group_symbol()
Beispiel #5
0
def cif2geom_sym2(cif):
  parser=CifParser.from_string(cif)
  struct=parser.get_structures()[0]
  sg = SpacegroupAnalyzer(struct)
  struct = sg.get_conventional_standard_structure()
  sg = SpacegroupAnalyzer(struct)

  geomlines=["CRYSTAL"]
  geomlines += ["0 0 1"]
  geomlines += [str(sg.get_spacegroup_number())]
  cry_sys = sg.get_crystal_system()
  lattice = struct.lattice

  if cry_sys == 'trigonal' or cry_sys == 'hexagonal' or cry_sys == 'tetragonal':
    geomlines += ["%s %s" %(lattice.a,lattice.c)]
  elif cry_sys == 'cubic':
    geomlines += ["%s" %(lattice.a)]
  elif cry_sys == 'triclinic':
    geomlines += ["%s %s %s %s %s %s" %(lattice.a,lattice.b,lattice.c,lattice.alpha,lattice.beta,lattice.gamma)]
  elif cry_sys == 'monoclinic':
    geomlines += ["%s %s %s %s" %(lattice.a,lattice.b,lattice.c,lattice.beta)]
  elif cry_sys == 'orthorhombic':
    geomlines += ["%s %s %s" %(lattice.a,lattice.b,lattice.c)]
  else:
    print('Error printing symmetrized structure.')
    quit()
  
  ds = sg.get_symmetry_dataset()
  eq_sites = np.unique(ds['equivalent_atoms'])
  geomlines += [str(len(eq_sites))]
  for eq_site in eq_sites:
    site = struct.sites[eq_site]
    geomlines += ["%s %s %s %s" %(site.specie.Z+200,site.a,site.b,site.c)]

  return geomlines,struct
Beispiel #6
0
def create_structure_db_info(structure, spacegroup=None):
    # Figure out the symmetry group
    if not spacegroup:
        spacegroup = SpacegroupAnalyzer(structure, normalised_symmetry_precision(structure), -1)

    d = dict()
    # Set the composition and formulas for the system
    comp = structure.composition
    el_amt = structure.composition.get_el_amt_dict()
    d.update({"unit_cell_formula": comp.to_dict,
              "reduced_cell_formula": comp.to_reduced_dict,
              "elements": list(el_amt.keys()),
              "nelements": len(el_amt),
              "pretty_formula": comp.reduced_formula,
              "anonymous_formula": comp.anonymized_formula,
              "nsites": comp.num_atoms,
              "chemsys": "-".join(sorted(el_amt.keys()))})

    d["spacegroup"] = {"symbol": unicode(spacegroup.get_spacegroup_symbol(),
                                         errors="ignore"),
                       "number": spacegroup.get_spacegroup_number(),
                       "point_group": unicode(spacegroup.get_point_group(),
                                              errors="ignore"),
                       "source": "spglib",
                       "crystal_system": spacegroup.get_crystal_system(),
                       "hall": spacegroup.get_hall()}

    return d
Beispiel #7
0
    def run_task(self, fw_spec):
        additional_fields = self.get("additional_fields", {})

        # pass the additional_fields first to avoid overriding BoltztrapAnalyzer items
        d = additional_fields.copy()

        btrap_dir = os.path.join(os.getcwd(), "boltztrap")
        d["boltztrap_dir"] = btrap_dir

        bta = BoltztrapAnalyzer.from_files(btrap_dir)
        d.update(bta.as_dict())
        d["scissor"] = bta.intrans["scissor"]

        # trim the output
        for x in ['cond', 'seebeck', 'kappa', 'hall', 'mu_steps', 'mu_doping', 'carrier_conc']:
            del d[x]

        if not self.get("hall_doping"):
            del d["hall_doping"]

        bandstructure_dir = os.getcwd()
        d["bandstructure_dir"] = bandstructure_dir

        # add the structure
        v, o = get_vasprun_outcar(bandstructure_dir, parse_eigen=False, parse_dos=False)
        structure = v.final_structure
        d["structure"] = structure.as_dict()
        d["formula_pretty"] = structure.composition.reduced_formula
        d.update(get_meta_from_structure(structure))

        # add the spacegroup
        sg = SpacegroupAnalyzer(Structure.from_dict(d["structure"]), 0.1)
        d["spacegroup"] = {"symbol": sg.get_space_group_symbol(),
                           "number": sg.get_space_group_number(),
                           "point_group": sg.get_point_group_symbol(),
                           "source": "spglib",
                           "crystal_system": sg.get_crystal_system(),
                           "hall": sg.get_hall()}

        d["created_at"] = datetime.utcnow()

        db_file = env_chk(self.get('db_file'), fw_spec)

        if not db_file:
            del d["dos"]
            with open(os.path.join(btrap_dir, "boltztrap.json"), "w") as f:
                f.write(json.dumps(d, default=DATETIME_HANDLER))
        else:
            mmdb = VaspCalcDb.from_db_file(db_file, admin=True)

            # dos gets inserted into GridFS
            dos = json.dumps(d["dos"], cls=MontyEncoder)
            fsid, compression = mmdb.insert_gridfs(dos, collection="dos_boltztrap_fs",
                                                   compress=True)
            d["dos_boltztrap_fs_id"] = fsid
            del d["dos"]

            mmdb.db.boltztrap.insert(d)
Beispiel #8
0
 def set_output_data(self, d_calc, d):
     """
     set the 'output' key
     """
     d["output"] = {
         "structure": d_calc["output"]["structure"],
         "density": d_calc.pop("density"),
         "energy": d_calc["output"]["energy"],
         "energy_per_atom": d_calc["output"]["energy_per_atom"]}
     d["output"].update(self.get_basic_processed_data(d))
     sg = SpacegroupAnalyzer(Structure.from_dict(d_calc["output"]["structure"]), 0.1)
     if not sg.get_symmetry_dataset():
         sg = SpacegroupAnalyzer(Structure.from_dict(d_calc["output"]["structure"]), 1e-3, 1)
     d["output"]["spacegroup"] = {
         "source": "spglib",
         "symbol": sg.get_space_group_symbol(),
         "number": sg.get_space_group_number(),
         "point_group": sg.get_point_group_symbol(),
         "crystal_system": sg.get_crystal_system(),
         "hall": sg.get_hall()}
     if d["input"]["parameters"].get("LEPSILON"):
         for k in ['epsilon_static', 'epsilon_static_wolfe', 'epsilon_ionic']:
             d["output"][k] = d_calc["output"][k]
Beispiel #9
0
class SpacegroupAnalyzerTest(PymatgenTest):

    def setUp(self):
        p = Poscar.from_file(os.path.join(test_dir, 'POSCAR'))
        self.structure = p.structure
        self.sg = SpacegroupAnalyzer(self.structure, 0.001)
        self.disordered_structure = self.get_structure('Li10GeP2S12')
        self.disordered_sg = SpacegroupAnalyzer(self.disordered_structure, 0.001)
        s = p.structure.copy()
        site = s[0]
        del s[0]
        s.append(site.species_and_occu, site.frac_coords)
        self.sg3 = SpacegroupAnalyzer(s, 0.001)
        graphite = self.get_structure('Graphite')
        graphite.add_site_property("magmom", [0.1] * len(graphite))
        self.sg4 = SpacegroupAnalyzer(graphite, 0.001)

    def test_get_space_symbol(self):
        self.assertEqual(self.sg.get_spacegroup_symbol(), "Pnma")
        self.assertEqual(self.disordered_sg.get_spacegroup_symbol(),
                         "P4_2/nmc")
        self.assertEqual(self.sg3.get_spacegroup_symbol(), "Pnma")
        self.assertEqual(self.sg4.get_spacegroup_symbol(), "R-3m")

    def test_get_space_number(self):
        self.assertEqual(self.sg.get_spacegroup_number(), 62)
        self.assertEqual(self.disordered_sg.get_spacegroup_number(), 137)
        self.assertEqual(self.sg4.get_spacegroup_number(), 166)

    def test_get_hall(self):
        self.assertEqual(self.sg.get_hall(), '-P 2ac 2n')
        self.assertEqual(self.disordered_sg.get_hall(), 'P 4n 2n -1n')

    def test_get_pointgroup(self):
        self.assertEqual(self.sg.get_point_group(), 'mmm')
        self.assertEqual(self.disordered_sg.get_point_group(), '4/mmm')

    def test_get_symmetry_dataset(self):
        ds = self.sg.get_symmetry_dataset()
        self.assertEqual(ds['international'], 'Pnma')

    def test_get_crystal_system(self):
        crystal_system = self.sg.get_crystal_system()
        self.assertEqual('orthorhombic', crystal_system)
        self.assertEqual('tetragonal', self.disordered_sg.get_crystal_system())

    def test_get_symmetry_operations(self):
        fracsymmops = self.sg.get_symmetry_operations()
        symmops = self.sg.get_symmetry_operations(True)
        self.assertEqual(len(symmops), 8)
        latt = self.structure.lattice
        for fop, op in zip(fracsymmops, symmops):
            for site in self.structure:
                newfrac = fop.operate(site.frac_coords)
                newcart = op.operate(site.coords)
                self.assertTrue(np.allclose(latt.get_fractional_coords(newcart),
                                            newfrac))
                found = False
                newsite = PeriodicSite(site.species_and_occu, newcart, latt,
                                       coords_are_cartesian=True)
                for testsite in self.structure:
                    if newsite.is_periodic_image(testsite, 1e-3):
                        found = True
                        break
                self.assertTrue(found)

    def test_get_refined_structure(self):
        for a in self.sg.get_refined_structure().lattice.angles:
            self.assertEqual(a, 90)
        refined = self.disordered_sg.get_refined_structure()
        for a in refined.lattice.angles:
            self.assertEqual(a, 90)
        self.assertEqual(refined.lattice.a, refined.lattice.b)
        s = self.get_structure('Li2O')
        sg = SpacegroupAnalyzer(s, 0.001)
        self.assertEqual(sg.get_refined_structure().num_sites, 4 * s.num_sites)

    def test_get_symmetrized_structure(self):
        symm_struct = self.sg.get_symmetrized_structure()
        for a in symm_struct.lattice.angles:
            self.assertEqual(a, 90)
        self.assertEqual(len(symm_struct.equivalent_sites), 5)

        symm_struct = self.disordered_sg.get_symmetrized_structure()
        self.assertEqual(len(symm_struct.equivalent_sites), 8)
        self.assertEqual([len(i) for i in symm_struct.equivalent_sites],
                         [16,4,8,4,2,8,8,8])
        s1 = symm_struct.equivalent_sites[1][1]
        s2 = symm_struct[symm_struct.equivalent_indices[1][1]]
        self.assertEqual(s1, s2)
        self.assertEqual(self.sg4.get_symmetrized_structure()[0].magmom, 0.1)

    def test_find_primitive(self):
        """
        F m -3 m Li2O testing of converting to primitive cell
        """
        parser = CifParser(os.path.join(test_dir, 'Li2O.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure)
        primitive_structure = s.find_primitive()
        self.assertEqual(primitive_structure.formula, "Li2 O1")
        # This isn't what is expected. All the angles should be 60
        self.assertAlmostEqual(primitive_structure.lattice.alpha, 60)
        self.assertAlmostEqual(primitive_structure.lattice.beta, 60)
        self.assertAlmostEqual(primitive_structure.lattice.gamma, 60)
        self.assertAlmostEqual(primitive_structure.lattice.volume,
                               structure.lattice.volume / 4.0)

    def test_get_ir_reciprocal_mesh(self):
        grid=self.sg.get_ir_reciprocal_mesh()
        self.assertEqual(len(grid), 216)
        self.assertAlmostEquals(grid[1][0][0], 0.1)
        self.assertAlmostEquals(grid[1][0][1], 0.0)
        self.assertAlmostEquals(grid[1][0][2], 0.0)
        self.assertEqual(grid[1][1], 2)

    def test_get_conventional_standard_structure(self):
        parser = CifParser(os.path.join(test_dir, 'bcc_1927.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 9.1980270633769461)
        self.assertAlmostEqual(conv.lattice.b, 9.1980270633769461)
        self.assertAlmostEqual(conv.lattice.c, 9.1980270633769461)

        parser = CifParser(os.path.join(test_dir, 'btet_1915.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 5.0615106678044235)
        self.assertAlmostEqual(conv.lattice.b, 5.0615106678044235)
        self.assertAlmostEqual(conv.lattice.c, 4.2327080177761687)

        parser = CifParser(os.path.join(test_dir, 'orci_1010.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 2.9542233922299999)
        self.assertAlmostEqual(conv.lattice.b, 4.6330325651443296)
        self.assertAlmostEqual(conv.lattice.c, 5.373703587040775)

        parser = CifParser(os.path.join(test_dir, 'orcc_1003.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 4.1430033493799998)
        self.assertAlmostEqual(conv.lattice.b, 31.437979757624728)
        self.assertAlmostEqual(conv.lattice.c, 3.99648651)

        parser = CifParser(os.path.join(test_dir, 'monoc_1028.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 117.53832420192903)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 14.033435583000625)
        self.assertAlmostEqual(conv.lattice.b, 3.96052850731)
        self.assertAlmostEqual(conv.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'rhomb_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 120)
        self.assertAlmostEqual(conv.lattice.a, 3.699919902005897)
        self.assertAlmostEqual(conv.lattice.b, 3.699919902005897)
        self.assertAlmostEqual(conv.lattice.c, 6.9779585500000003)

    def test_get_primitive_standard_structure(self):
        parser = CifParser(os.path.join(test_dir, 'bcc_1927.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.beta, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.gamma, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.a, 7.9657251015812145)
        self.assertAlmostEqual(prim.lattice.b, 7.9657251015812145)
        self.assertAlmostEqual(prim.lattice.c, 7.9657251015812145)

        parser = CifParser(os.path.join(test_dir, 'btet_1915.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 105.015053349)
        self.assertAlmostEqual(prim.lattice.beta, 105.015053349)
        self.assertAlmostEqual(prim.lattice.gamma, 118.80658411899999)
        self.assertAlmostEqual(prim.lattice.a, 4.1579321075608791)
        self.assertAlmostEqual(prim.lattice.b, 4.1579321075608791)
        self.assertAlmostEqual(prim.lattice.c, 4.1579321075608791)

        parser = CifParser(os.path.join(test_dir, 'orci_1010.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 134.78923546600001)
        self.assertAlmostEqual(prim.lattice.beta, 105.856239333)
        self.assertAlmostEqual(prim.lattice.gamma, 91.276341676000001)
        self.assertAlmostEqual(prim.lattice.a, 3.8428217771014852)
        self.assertAlmostEqual(prim.lattice.b, 3.8428217771014852)
        self.assertAlmostEqual(prim.lattice.c, 3.8428217771014852)

        parser = CifParser(os.path.join(test_dir, 'orcc_1003.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 90)
        self.assertAlmostEqual(prim.lattice.beta, 90)
        self.assertAlmostEqual(prim.lattice.gamma, 164.985257335)
        self.assertAlmostEqual(prim.lattice.a, 15.854897098324196)
        self.assertAlmostEqual(prim.lattice.b, 15.854897098324196)
        self.assertAlmostEqual(prim.lattice.c, 3.99648651)

        parser = CifParser(os.path.join(test_dir, 'monoc_1028.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 63.579155761999999)
        self.assertAlmostEqual(prim.lattice.beta, 116.42084423747779)
        self.assertAlmostEqual(prim.lattice.gamma, 148.47965136208569)
        self.assertAlmostEqual(prim.lattice.a, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.b, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'rhomb_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 90)
        self.assertAlmostEqual(prim.lattice.beta, 90)
        self.assertAlmostEqual(prim.lattice.gamma, 120)
        self.assertAlmostEqual(prim.lattice.a, 3.699919902005897)
        self.assertAlmostEqual(prim.lattice.b, 3.699919902005897)
        self.assertAlmostEqual(prim.lattice.c, 6.9779585500000003)
Beispiel #10
0
    def convert_to_ieee(self, structure):
        """
        Given a structure associated with a tensor, attempts a
        calculation of the tensor in IEEE format according to
        the 1987 IEEE standards.

        Args:
            structure (Structure): a structure associated with the
                tensor to be converted to the IEEE standard
        """
        def get_uvec(vec):
            """ Gets a unit vector parallel to input vector"""
            return vec / np.linalg.norm(vec)

        # Check conventional setting:
        sga = SpacegroupAnalyzer(structure)
        dataset = sga.get_symmetry_dataset()
        trans_mat = dataset['transformation_matrix']
        conv_latt = Lattice(np.transpose(np.dot(np.transpose(
            structure.lattice.matrix), np.linalg.inv(trans_mat))))
        xtal_sys = sga.get_crystal_system()
        
        vecs = conv_latt.matrix
        lengths = np.array(conv_latt.abc)
        angles = np.array(conv_latt.angles)
        a = b = c = None
        rotation = np.zeros((3,3))

        # IEEE rules: a,b,c || x1,x2,x3
        if xtal_sys == "cubic":
            rotation = [vecs[i]/lengths[i] for i in range(3)]

        # IEEE rules: a=b in length; c,a || x3, x1
        elif xtal_sys == "tetragonal":
            rotation = np.array([vec/mag for (mag, vec) in 
                                 sorted(zip(lengths, vecs),
                                        key = lambda x: x[0])])
            if abs(lengths[2] - lengths[1]) < abs(lengths[1] - lengths[0]):
                rotation[0], rotation[2] = rotation[2], rotation[0].copy()
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: c<a<b; c,a || x3,x1
        elif xtal_sys == "orthorhombic":
            rotation = [vec/mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis = 0)

        # IEEE rules: c,a || x3,x1, c is threefold axis
        # Note this also includes rhombohedral crystal systems
        elif xtal_sys in ("trigonal", "hexagonal"):
            # find threefold axis:
            tf_index = np.argmin(abs(angles - 120.))
            non_tf_mask = np.logical_not(angles == angles[tf_index])
            rotation[2] = get_uvec(vecs[tf_index])
            rotation[0] = get_uvec(vecs[non_tf_mask][0])
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: b,c || x2,x3; alpha=beta=90, c<a
        elif xtal_sys == "monoclinic":
            # Find unique axis
            u_index = np.argmax(abs(angles - 90.))
            n_umask = np.logical_not(angles == angles[u_index])
            rotation[1] = get_uvec(vecs[u_index])
            # Shorter of remaining lattice vectors for c axis
            c = [vec/mag for (mag, vec) in 
                 sorted(zip(lengths[n_umask], vecs[n_umask]))][0]
            rotation[2] = np.array(c)
            rotation[0] = np.cross(rotation[1], rotation[2])
        
        # IEEE rules: c || x3
        elif xtal_sys == "triclinic":
            rotation = [vec/mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis = 0)
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[1]))
            rotation[0] = np.cross(rotation[1], rotation[2])

        return self.rotate(rotation, tol=1e-2)
Beispiel #11
0
class SpacegroupAnalyzerTest(PymatgenTest):

    def setUp(self):
        p = Poscar.from_file(os.path.join(test_dir, 'POSCAR'))
        self.structure = p.structure
        self.sg = SpacegroupAnalyzer(self.structure, 0.001)
        self.disordered_structure = self.get_structure('Li10GeP2S12')
        self.disordered_sg = SpacegroupAnalyzer(self.disordered_structure, 0.001)
        s = p.structure.copy()
        site = s[0]
        del s[0]
        s.append(site.species_and_occu, site.frac_coords)
        self.sg3 = SpacegroupAnalyzer(s, 0.001)
        graphite = self.get_structure('Graphite')
        graphite.add_site_property("magmom", [0.1] * len(graphite))
        self.sg4 = SpacegroupAnalyzer(graphite, 0.001)
        self.structure4 = graphite

    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 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_magnetic(self):
        lfp = PymatgenTest.get_structure("LiFePO4")
        sg = SpacegroupAnalyzer(lfp, 0.1)
        self.assertEqual(sg.get_space_group_symbol(), "Pnma")
        magmoms = [0] * len(lfp)
        magmoms[4] = 1
        magmoms[5] = -1
        magmoms[6] = 1
        magmoms[7] = -1
        lfp.add_site_property("magmom", magmoms)
        sg = SpacegroupAnalyzer(lfp, 0.1)
        self.assertEqual(sg.get_space_group_symbol(), "Pnma")

    def test_get_space_symbol(self):
        self.assertEqual(self.sg.get_space_group_symbol(), "Pnma")
        self.assertEqual(self.disordered_sg.get_space_group_symbol(),
                         "P4_2/nmc")
        self.assertEqual(self.sg3.get_space_group_symbol(), "Pnma")
        self.assertEqual(self.sg4.get_space_group_symbol(), "P6_3/mmc")

    def test_get_space_number(self):
        self.assertEqual(self.sg.get_space_group_number(), 62)
        self.assertEqual(self.disordered_sg.get_space_group_number(), 137)
        self.assertEqual(self.sg4.get_space_group_number(), 194)

    def test_get_hall(self):
        self.assertEqual(self.sg.get_hall(), '-P 2ac 2n')
        self.assertEqual(self.disordered_sg.get_hall(), 'P 4n 2n -1n')

    def test_get_pointgroup(self):
        self.assertEqual(self.sg.get_point_group_symbol(), 'mmm')
        self.assertEqual(self.disordered_sg.get_point_group_symbol(), '4/mmm')

    def test_get_symmetry_dataset(self):
        ds = self.sg.get_symmetry_dataset()
        self.assertEqual(ds['international'], 'Pnma')

    def test_get_crystal_system(self):
        crystal_system = self.sg.get_crystal_system()
        self.assertEqual('orthorhombic', crystal_system)
        self.assertEqual('tetragonal', self.disordered_sg.get_crystal_system())

    def test_get_symmetry_operations(self):
        for sg, structure in [(self.sg, self.structure),
                              (self.sg4, self.structure4)]:

            pgops = sg.get_point_group_operations()
            fracsymmops = sg.get_symmetry_operations()
            symmops = sg.get_symmetry_operations(True)
            latt = structure.lattice
            for fop, op, pgop in zip(fracsymmops, symmops, pgops):
                # translation vector values should all be 0 or 0.5
                t = fop.translation_vector * 2
                self.assertArrayAlmostEqual(t - np.round(t), 0)

                self.assertArrayAlmostEqual(fop.rotation_matrix,
                                            pgop.rotation_matrix)
                for site in structure:
                    newfrac = fop.operate(site.frac_coords)
                    newcart = op.operate(site.coords)
                    self.assertTrue(np.allclose(latt.get_fractional_coords(newcart),
                                                newfrac))
                    found = False
                    newsite = PeriodicSite(site.species_and_occu, newcart, latt,
                                           coords_are_cartesian=True)
                    for testsite in structure:
                        if newsite.is_periodic_image(testsite, 1e-3):
                            found = True
                            break
                    self.assertTrue(found)

                # Make sure this works for any position, not just the atomic
                # ones.
                random_fcoord = np.random.uniform(size=(3))
                random_ccoord = latt.get_cartesian_coords(random_fcoord)
                newfrac = fop.operate(random_fcoord)
                newcart = op.operate(random_ccoord)
                self.assertTrue(np.allclose(latt.get_fractional_coords(newcart),
                                            newfrac))

    def test_get_refined_structure(self):
        for a in self.sg.get_refined_structure().lattice.angles:
            self.assertEqual(a, 90)
        refined = self.disordered_sg.get_refined_structure()
        for a in refined.lattice.angles:
            self.assertEqual(a, 90)
        self.assertEqual(refined.lattice.a, refined.lattice.b)
        s = self.get_structure('Li2O')
        sg = SpacegroupAnalyzer(s, 0.01)
        self.assertEqual(sg.get_refined_structure().num_sites, 4 * s.num_sites)

    def test_get_symmetrized_structure(self):
        symm_struct = self.sg.get_symmetrized_structure()
        for a in symm_struct.lattice.angles:
            self.assertEqual(a, 90)
        self.assertEqual(len(symm_struct.equivalent_sites), 5)

        symm_struct = self.disordered_sg.get_symmetrized_structure()
        self.assertEqual(len(symm_struct.equivalent_sites), 8)
        self.assertEqual([len(i) for i in symm_struct.equivalent_sites],
                         [16,4,8,4,2,8,8,8])
        s1 = symm_struct.equivalent_sites[1][1]
        s2 = symm_struct[symm_struct.equivalent_indices[1][1]]
        self.assertEqual(s1, s2)
        self.assertEqual(self.sg4.get_symmetrized_structure()[0].magmom, 0.1)
        self.assertEqual(symm_struct.wyckoff_symbols[0], '16h')
        # self.assertEqual(symm_struct[0].wyckoff, "16h")

    def test_find_primitive(self):
        """
        F m -3 m Li2O testing of converting to primitive cell
        """
        parser = CifParser(os.path.join(test_dir, 'Li2O.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure)
        primitive_structure = s.find_primitive()
        self.assertEqual(primitive_structure.formula, "Li2 O1")
        # This isn't what is expected. All the angles should be 60
        self.assertAlmostEqual(primitive_structure.lattice.alpha, 60)
        self.assertAlmostEqual(primitive_structure.lattice.beta, 60)
        self.assertAlmostEqual(primitive_structure.lattice.gamma, 60)
        self.assertAlmostEqual(primitive_structure.lattice.volume,
                               structure.lattice.volume / 4.0)

    def test_get_ir_reciprocal_mesh(self):
        grid = self.sg.get_ir_reciprocal_mesh()
        self.assertEqual(len(grid), 216)
        self.assertAlmostEqual(grid[1][0][0], 0.1)
        self.assertAlmostEqual(grid[1][0][1], 0.0)
        self.assertAlmostEqual(grid[1][0][2], 0.0)
        self.assertAlmostEqual(grid[1][1], 2)

    def test_get_conventional_standard_structure(self):
        parser = CifParser(os.path.join(test_dir, 'bcc_1927.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 9.1980270633769461)
        self.assertAlmostEqual(conv.lattice.b, 9.1980270633769461)
        self.assertAlmostEqual(conv.lattice.c, 9.1980270633769461)

        parser = CifParser(os.path.join(test_dir, 'btet_1915.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 5.0615106678044235)
        self.assertAlmostEqual(conv.lattice.b, 5.0615106678044235)
        self.assertAlmostEqual(conv.lattice.c, 4.2327080177761687)

        parser = CifParser(os.path.join(test_dir, 'orci_1010.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 2.9542233922299999)
        self.assertAlmostEqual(conv.lattice.b, 4.6330325651443296)
        self.assertAlmostEqual(conv.lattice.c, 5.373703587040775)

        parser = CifParser(os.path.join(test_dir, 'orcc_1003.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 4.1430033493799998)
        self.assertAlmostEqual(conv.lattice.b, 31.437979757624728)
        self.assertAlmostEqual(conv.lattice.c, 3.99648651)

        parser = CifParser(os.path.join(test_dir, 'orac_632475.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 3.1790663399999999)
        self.assertAlmostEqual(conv.lattice.b, 9.9032878699999998)
        self.assertAlmostEqual(conv.lattice.c, 3.5372412099999999)

        parser = CifParser(os.path.join(test_dir, 'monoc_1028.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 117.53832420192903)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 14.033435583000625)
        self.assertAlmostEqual(conv.lattice.b, 3.96052850731)
        self.assertAlmostEqual(conv.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'hex_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 120)
        self.assertAlmostEqual(conv.lattice.a, 3.699919902005897)
        self.assertAlmostEqual(conv.lattice.b, 3.699919902005897)
        self.assertAlmostEqual(conv.lattice.c, 6.9779585500000003)

    def test_get_primitive_standard_structure(self):
        parser = CifParser(os.path.join(test_dir, 'bcc_1927.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.beta, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.gamma, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.a, 7.9657251015812145)
        self.assertAlmostEqual(prim.lattice.b, 7.9657251015812145)
        self.assertAlmostEqual(prim.lattice.c, 7.9657251015812145)

        parser = CifParser(os.path.join(test_dir, 'btet_1915.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 105.015053349)
        self.assertAlmostEqual(prim.lattice.beta, 105.015053349)
        self.assertAlmostEqual(prim.lattice.gamma, 118.80658411899999)
        self.assertAlmostEqual(prim.lattice.a, 4.1579321075608791)
        self.assertAlmostEqual(prim.lattice.b, 4.1579321075608791)
        self.assertAlmostEqual(prim.lattice.c, 4.1579321075608791)

        parser = CifParser(os.path.join(test_dir, 'orci_1010.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 134.78923546600001)
        self.assertAlmostEqual(prim.lattice.beta, 105.856239333)
        self.assertAlmostEqual(prim.lattice.gamma, 91.276341676000001)
        self.assertAlmostEqual(prim.lattice.a, 3.8428217771014852)
        self.assertAlmostEqual(prim.lattice.b, 3.8428217771014852)
        self.assertAlmostEqual(prim.lattice.c, 3.8428217771014852)

        parser = CifParser(os.path.join(test_dir, 'orcc_1003.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 90)
        self.assertAlmostEqual(prim.lattice.beta, 90)
        self.assertAlmostEqual(prim.lattice.gamma, 164.985257335)
        self.assertAlmostEqual(prim.lattice.a, 15.854897098324196)
        self.assertAlmostEqual(prim.lattice.b, 15.854897098324196)
        self.assertAlmostEqual(prim.lattice.c, 3.99648651)

        parser = CifParser(os.path.join(test_dir, 'orac_632475.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 90)
        self.assertAlmostEqual(prim.lattice.beta, 90)
        self.assertAlmostEqual(prim.lattice.gamma, 144.40557588533386)
        self.assertAlmostEqual(prim.lattice.a, 5.2005185662155391)
        self.assertAlmostEqual(prim.lattice.b, 5.2005185662155391)
        self.assertAlmostEqual(prim.lattice.c, 3.5372412099999999)

        parser = CifParser(os.path.join(test_dir, 'monoc_1028.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 63.579155761999999)
        self.assertAlmostEqual(prim.lattice.beta, 116.42084423747779)
        self.assertAlmostEqual(prim.lattice.gamma, 148.47965136208569)
        self.assertAlmostEqual(prim.lattice.a, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.b, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'hex_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 90)
        self.assertAlmostEqual(prim.lattice.beta, 90)
        self.assertAlmostEqual(prim.lattice.gamma, 120)
        self.assertAlmostEqual(prim.lattice.a, 3.699919902005897)
        self.assertAlmostEqual(prim.lattice.b, 3.699919902005897)
        self.assertAlmostEqual(prim.lattice.c, 6.9779585500000003)

        parser = CifParser(os.path.join(test_dir, 'rhomb_3478_conv.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 28.049186140546812)
        self.assertAlmostEqual(prim.lattice.beta, 28.049186140546812)
        self.assertAlmostEqual(prim.lattice.gamma, 28.049186140546812)
        self.assertAlmostEqual(prim.lattice.a, 5.9352627428399982)
        self.assertAlmostEqual(prim.lattice.b, 5.9352627428399982)
        self.assertAlmostEqual(prim.lattice.c, 5.9352627428399982)
Beispiel #12
0
    def convert_to_ieee(self, structure, atol = 0.1, ltol = 0.05):
        """
        Given a structure associated with a tensor, attempts a
        calculation of the tensor in IEEE format according to
        the 1987 IEEE standards.

        Args:
            structure (Structure): a structure associated with the
                tensor to be converted to the IEEE standard
            atol (float): angle tolerance for conversion routines
            ltol (float): length tolerance for conversion routines
        """
        def get_uvec(vec):
            """ Gets a unit vector parallel to input vector"""
            return vec / np.linalg.norm(vec)

        vecs = structure.lattice.matrix
        lengths = np.array(structure.lattice.abc)
        angles = np.array(structure.lattice.angles)

        # Check conventional setting:
        sga = SpacegroupAnalyzer(structure)
        xtal_sys = sga.get_crystal_system()
        conv_struct = sga.get_refined_structure()
        conv_lengths = np.array(conv_struct.lattice.abc)
        conv_angles = np.array(conv_struct.lattice.angles)
        rhombohedral = xtal_sys == "trigonal" and \
                (angles - angles[0] < atol).all()
        if ((np.sort(lengths) - np.sort(conv_lengths) > ltol).any() \
           or (np.sort(angles) - np.sort(conv_angles) > atol).any() \
           or len(structure.sites) != len(conv_struct.sites)) \
           and not rhombohedral:
            raise ValueError("{} structure not in conventional cell, IEEE "\
                             "conversion from non-conventional settings "\
                             "is not yet supported.".format(xtal_sys))

        a = b = c = None
        rotation = np.zeros((3,3))

        # IEEE rules: a,b,c || x1,x2,x3
        if xtal_sys == "cubic":
            rotation = [vecs[i]/lengths[i] for i in range(3)]

        # IEEE rules: a=b in length; c,a || x3, x1
        elif xtal_sys == "tetragonal":            
            rotation = np.array([vec/mag for (mag, vec) in 
                                 sorted(zip(lengths, vecs))])
            if abs(lengths[2] - lengths[1]) < ltol:
                rotation[0], rotation[2] = rotation[2], rotation[0].copy()
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: c<a<b; c,a || x3,x1
        elif xtal_sys == "orthorhombic":
            rotation = [vec/mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis = 0)

        # IEEE rules: c,a || x3,x1, c is threefold axis
        elif xtal_sys in ("trigonal", "hexagonal"):
            # Rhombohedral lattice
            if rhombohedral:
                rotation[0] = get_uvec(vecs[2] - vecs[0])
                rotation[2] = get_uvec(np.sum(vecs, axis=0))
                rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))
            # Standard hexagonal lattice
            else:
                # find threefold axis:
                tf_mask = np.where(abs(angles-120.0) < atol)
                non_tf_mask = np.logical_not(tf_mask)
                rotation[2] = get_uvec(vecs[tf_mask])
                rotation[0] = get_uvec(vecs[non_tf_mask][0])
                rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: b,c || x2,x3; alpha=beta=90, c<a
        elif xtal_sys == "monoclinic":
            # Find unique axis
            umask = abs(angles - 90.0) > atol
            n_umask = np.logical_not(umask)
            rotation[1] = get_uvec(vecs[umask])
            # Shorter of remaining lattice vectors for c axis
            c = [vec/mag for (mag, vec) in 
                 sorted(zip(lengths[n_umask], vecs[n_umask]))][0]
            rotation[2] = np.array(c)
            rotation[0] = np.cross(rotation[1], rotation[2])
        
        # IEEE rules: c || x3
        elif xtal_sys == "triclinic":
            rotation = [vec/mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis = 0)
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[1]))
            rotation[0] = np.cross(rotation[1], rotation[2])
        
        return self.rotate(rotation)
Beispiel #13
0
    features = np.zeros((len(battery_table), NUM_OF_FEATURE))
    for i, (id_charge, id_discharge, ion) in tqdm(
            enumerate(
                zip(battery_table['id_charge'], battery_table['id_discharge'],
                    battery_table['working_ion']))):

        # load crystal object from cif
        charge_crystal = Structure.from_str(cif_data[id_charge].value, 'cif')
        discharge_crystal = Structure.from_str(cif_data[id_discharge].value,
                                               'cif')

        # specific features
        finder = SpacegroupAnalyzer(charge_crystal)
        space_group_feat = np.array([finder.get_space_group_number()])
        crystal_system_feat = create_feature_from_crystal_system(
            finder.get_crystal_system())
        ion_feat = create_feature_from_wokring_ion(ion)
        dischr_comp = Composition(discharge_crystal.formula)
        ion_concentrate = np.array(
            [dischr_comp.get_atomic_fraction(Element(ion))])

        # calculate features from element property
        charge_formula = charge_crystal.formula
        discharge_formula = discharge_crystal.formula
        feature_from_chr_formula = create_feature_from_formula(
            charge_formula, element_data)
        feature_from_dischr_formula = create_feature_from_formula(
            discharge_formula, element_data)
        feature_from_ion = create_feature_from_formula(ion, element_data)

        # if charge_formula is a single element
Beispiel #14
0
    def generate_doc(self, dir_name, vasprun_files, outcar_files):
        """
        Adapted from matgendb.creator.generate_doc
        """
        try:
            # basic properties, incl. calcs_reversed and run_stats
            fullpath = os.path.abspath(dir_name)
            d = jsanitize(self.additional_fields, strict=True)
            d["schema"] = {"code": "atomate", "version": VaspDrone.__version__}
            d["dir_name"] = fullpath
            d["calcs_reversed"] = [
                self.process_vasprun(dir_name, taskname, filename)
                for taskname, filename in vasprun_files.items()
            ]
            outcar_data = [
                Outcar(os.path.join(dir_name, filename)).as_dict()
                for taskname, filename in outcar_files.items()
            ]
            run_stats = {}
            for i, d_calc in enumerate(d["calcs_reversed"]):
                run_stats[d_calc["task"]["name"]] = outcar_data[i].pop(
                    "run_stats")
                if d_calc.get("output"):
                    d_calc["output"].update({"outcar": outcar_data[i]})
                else:
                    d_calc["output"] = {"outcar": outcar_data[i]}
            try:
                overall_run_stats = {}
                for key in [
                        "Total CPU time used (sec)", "User time (sec)",
                        "System time (sec)", "Elapsed time (sec)"
                ]:
                    overall_run_stats[key] = sum(
                        [v[key] for v in run_stats.values()])
                run_stats["overall"] = overall_run_stats
            except:
                logger.error("Bad run stats for {}.".format(fullpath))
            d["run_stats"] = run_stats

            # reverse the calculations data order so newest calc is first
            d["calcs_reversed"].reverse()

            # set root formula/composition keys based on initial and final calcs
            d_calc_init = d["calcs_reversed"][-1]
            d_calc_final = d["calcs_reversed"][0]
            d["chemsys"] = "-".join(sorted(d_calc_final["elements"]))
            comp = Composition(d_calc_final["composition_unit_cell"])
            d["formula_anonymous"] = comp.anonymized_formula
            d["formula_reduced_abc"] = comp.reduced_composition.alphabetical_formula
            for root_key in [
                    "completed_at", "nsites", "composition_unit_cell",
                    "composition_reduced", "formula_pretty", "elements",
                    "nelements"
            ]:
                d[root_key] = d_calc_final[root_key]

            # store the input key based on initial calc
            # store any overrides to the exchange correlation functional
            xc = d_calc_init["input"]["incar"].get("GGA")
            if xc:
                xc = xc.upper()
            p = d_calc_init["input"]["potcar_type"][0].split("_")
            pot_type = p[0]
            functional = "lda" if len(pot_type) == 1 else "_".join(p[1:])
            d["input"] = {
                "structure": d_calc_init["input"]["structure"],
                "is_hubbard": d_calc_init.pop("is_hubbard"),
                "hubbards": d_calc_init.pop("hubbards"),
                "is_lasph": d_calc_init["input"]["incar"].get("LASPH", False),
                "potcar_spec": d_calc_init["input"].get("potcar_spec"),
                "xc_override": xc,
                "pseudo_potential": {
                    "functional": functional.lower(),
                    "pot_type": pot_type.lower(),
                    "labels": d_calc_init["input"]["potcar"]
                },
                "parameters": d_calc_init["input"]["parameters"],
                "incar": d_calc_init["input"]["incar"]
            }

            # store the output key based on final calc
            d["output"] = {
                "structure": d_calc_final["output"]["structure"],
                "density": d_calc_final.pop("density"),
                "energy": d_calc_final["output"]["energy"],
                "energy_per_atom": d_calc_final["output"]["energy_per_atom"],
                "forces":
                d_calc_final["output"]["ionic_steps"][-1].get("forces"),
                "stress":
                d_calc_final["output"]["ionic_steps"][-1].get("stress")
            }

            # patch calculated magnetic moments into final structure
            if len(d_calc_final["output"]["outcar"]["magnetization"]) != 0:
                magmoms = [
                    m["tot"]
                    for m in d_calc_final["output"]["outcar"]["magnetization"]
                ]
                s = Structure.from_dict(d["output"]["structure"])
                s.add_site_property('magmom', magmoms)
                d["output"]["structure"] = s.as_dict()

            calc = d["calcs_reversed"][0]

            # copy band gap and properties into output
            d["output"].update({
                "bandgap": calc["output"]["bandgap"],
                "cbm": calc["output"]["cbm"],
                "vbm": calc["output"]["vbm"],
                "is_gap_direct": calc["output"]["is_gap_direct"]
            })
            try:
                d["output"].update({"is_metal": calc["output"]["is_metal"]})
                if not calc["output"]["is_gap_direct"]:
                    d["output"]["direct_gap"] = calc["output"]["direct_gap"]
                if "transition" in calc["output"]:
                    d["output"]["transition"] = calc["output"]["transition"]

            except Exception:
                if self.bandstructure_mode is True:
                    logger.error(traceback.format_exc())
                    logger.error("Error in " + os.path.abspath(dir_name) +
                                 ".\n" + traceback.format_exc())
                    raise

            # Store symmetry information
            sg = SpacegroupAnalyzer(
                Structure.from_dict(d_calc_final["output"]["structure"]), 0.1)
            if not sg.get_symmetry_dataset():
                sg = SpacegroupAnalyzer(
                    Structure.from_dict(d_calc_final["output"]["structure"]),
                    1e-3, 1)
            d["output"]["spacegroup"] = {
                "source": "spglib",
                "symbol": sg.get_space_group_symbol(),
                "number": sg.get_space_group_number(),
                "point_group": sg.get_point_group_symbol(),
                "crystal_system": sg.get_crystal_system(),
                "hall": sg.get_hall()
            }

            # store dieelctric and piezo information
            if d["input"]["parameters"].get("LEPSILON"):
                for k in [
                        'epsilon_static', 'epsilon_static_wolfe',
                        'epsilon_ionic'
                ]:
                    d["output"][k] = d_calc_final["output"][k]
                if SymmOp.inversion() not in sg.get_symmetry_operations():
                    for k in ["piezo_ionic_tensor", "piezo_tensor"]:
                        d["output"][k] = d_calc_final["output"]["outcar"][k]

            d["state"] = "successful" if d_calc[
                "has_vasp_completed"] else "unsuccessful"

            self.set_analysis(d)

            d["last_updated"] = datetime.datetime.utcnow()
            return d

        except Exception:
            logger.error(traceback.format_exc())
            logger.error("Error in " + os.path.abspath(dir_name) + ".\n" +
                         traceback.format_exc())
            raise
Beispiel #15
0
        def update_contents(data, symprec, angle_tolerance):

            if not data:
                return html.Div()

            struct = self.from_data(data)

            if not isinstance(struct, Structure):
                return html.Div(
                    "Can only analyze symmetry of crystal structures at present."
                )

            kwargs = self.reconstruct_kwargs_from_state(
                callback_context.inputs)
            symprec = kwargs["symprec"]
            angle_tolerance = kwargs["angle_tolerance"]

            sga = SpacegroupAnalyzer(struct,
                                     symprec=symprec,
                                     angle_tolerance=angle_tolerance)

            try:
                data = dict()
                data["Crystal System"] = sga.get_crystal_system().title()
                data["Lattice System"] = sga.get_lattice_type().title()
                data["Hall Number"] = sga.get_hall()
                data["International Number"] = sga.get_space_group_number()
                data["Symbol"] = unicodeify_spacegroup(
                    sga.get_space_group_symbol())
                data["Point Group"] = unicodeify_spacegroup(
                    sga.get_point_group_symbol())

                sym_struct = sga.get_symmetrized_structure()
            except Exception:
                return html.Span(
                    f"Failed to calculate symmetry with this combination of "
                    f"symmetry-finding ({symprec}) and angle tolerances ({angle_tolerance})."
                )

            datalist = get_data_list(data)

            wyckoff_contents = []

            wyckoff_data = sorted(
                zip(sym_struct.wyckoff_symbols, sym_struct.equivalent_sites),
                key=lambda x: "".join(filter(lambda w: w.isalpha(), x[0])),
            )

            for symbol, equiv_sites in wyckoff_data:
                wyckoff_contents.append(
                    html.Label(
                        f"{symbol}, {unicodeify_species(equiv_sites[0].species_string)}",
                        className="mpc-label",
                    ))
                site_data = [(
                    self.pretty_frac_format(site.frac_coords[0]),
                    self.pretty_frac_format(site.frac_coords[1]),
                    self.pretty_frac_format(site.frac_coords[2]),
                ) for site in equiv_sites]
                wyckoff_contents.append(get_table(site_data))

            return Columns([
                Column([H5("Overview"), datalist]),
                Column([H5("Wyckoff Positions"),
                        html.Div(wyckoff_contents)]),
            ])
Beispiel #16
0
    def get_ieee_rotation(structure, refine_rotation=True):
        """
        Given a structure associated with a tensor, determines
        the rotation matrix for IEEE conversion according to
        the 1987 IEEE standards.

        Args:
            structure (Structure): a structure associated with the
                tensor to be converted to the IEEE standard
            refine_rotation (bool): whether to refine the rotation
                using SquareTensor.refine_rotation
        """
        # Check conventional setting:
        sga = SpacegroupAnalyzer(structure)
        dataset = sga.get_symmetry_dataset()
        trans_mat = dataset['transformation_matrix']
        conv_latt = Lattice(np.transpose(np.dot(np.transpose(
            structure.lattice.matrix), np.linalg.inv(trans_mat))))
        xtal_sys = sga.get_crystal_system()

        vecs = conv_latt.matrix
        lengths = np.array(conv_latt.abc)
        angles = np.array(conv_latt.angles)
        rotation = np.zeros((3, 3))

        # IEEE rules: a,b,c || x1,x2,x3
        if xtal_sys == "cubic":
            rotation = [vecs[i] / lengths[i] for i in range(3)]

        # IEEE rules: a=b in length; c,a || x3, x1
        elif xtal_sys == "tetragonal":
            rotation = np.array([vec / mag for (mag, vec) in
                                 sorted(zip(lengths, vecs),
                                        key=lambda x: x[0])])
            if abs(lengths[2] - lengths[1]) < abs(lengths[1] - lengths[0]):
                rotation[0], rotation[2] = rotation[2], rotation[0].copy()
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: c<a<b; c,a || x3,x1
        elif xtal_sys == "orthorhombic":
            rotation = [vec / mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis=0)

        # IEEE rules: c,a || x3,x1, c is threefold axis
        # Note this also includes rhombohedral crystal systems
        elif xtal_sys in ("trigonal", "hexagonal"):
            # find threefold axis:
            tf_index = np.argmin(abs(angles - 120.))
            non_tf_mask = np.logical_not(angles == angles[tf_index])
            rotation[2] = get_uvec(vecs[tf_index])
            rotation[0] = get_uvec(vecs[non_tf_mask][0])
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: b,c || x2,x3; alpha=beta=90, c<a
        elif xtal_sys == "monoclinic":
            # Find unique axis
            u_index = np.argmax(abs(angles - 90.))
            n_umask = np.logical_not(angles == angles[u_index])
            rotation[1] = get_uvec(vecs[u_index])
            # Shorter of remaining lattice vectors for c axis
            c = [vec / mag for (mag, vec) in
                 sorted(zip(lengths[n_umask], vecs[n_umask]))][0]
            rotation[2] = np.array(c)
            rotation[0] = np.cross(rotation[1], rotation[2])

        # IEEE rules: c || x3
        elif xtal_sys == "triclinic":
            rotation = [vec / mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis=0)
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[1]))
            rotation[0] = np.cross(rotation[1], rotation[2])

        rotation = SquareTensor(rotation)
        if refine_rotation:
            rotation = rotation.refine_rotation()

        return rotation
Beispiel #17
0
    def generate_doc(self, dir_name, vasprun_files):
        """
        Process aflow style runs, where each run is actually a combination of
        two vasp runs.
        """
        try:
            fullpath = os.path.abspath(dir_name)
            #Defensively copy the additional fields first.  This is a MUST.
            #Otherwise, parallel updates will see the same object and inserts
            #will be overridden!!
            d = {k: v for k, v in self.additional_fields.items()}
            d["dir_name"] = fullpath
            d["schema_version"] = VaspToDbTaskDrone.__version__
            d["calculations"] = [
                self.process_vasprun(dir_name, taskname, filename)
                for taskname, filename in vasprun_files.items()]
            d1 = d["calculations"][0]
            d2 = d["calculations"][-1]

            #Now map some useful info to the root level.
            for root_key in ["completed_at", "nsites", "unit_cell_formula",
                             "reduced_cell_formula", "pretty_formula",
                             "elements", "nelements", "cif", "density",
                             "is_hubbard", "hubbards", "run_type"]:
                d[root_key] = d2[root_key]
            d["chemsys"] = "-".join(sorted(d2["elements"]))

            #store any overrides to the exchange correlation functional
            xc = d2["input"]["incar"].get("GGA")
            if xc:
                xc = xc.upper()
            d["input"] = {"crystal": d1["input"]["crystal"],
                          "is_lasph": d2["input"]["incar"].get("LASPH", False),
                          "potcar_spec": d1["input"].get("potcar_spec"),
                          "xc_override": xc}
            vals = sorted(d2["reduced_cell_formula"].values())
            d["anonymous_formula"] = {string.ascii_uppercase[i]: float(vals[i])
                                      for i in range(len(vals))}
            d["output"] = {
                "crystal": d2["output"]["crystal"],
                "final_energy": d2["output"]["final_energy"],
                "final_energy_per_atom": d2["output"]["final_energy_per_atom"]}
            d["name"] = "aflow"
            p = d2["input"]["potcar_type"][0].split("_")
            pot_type = p[0]
            functional = "lda" if len(pot_type) == 1 else "_".join(p[1:])
            d["pseudo_potential"] = {"functional": functional.lower(),
                                     "pot_type": pot_type.lower(),
                                     "labels": d2["input"]["potcar"]}
            if len(d["calculations"]) == len(self.runs) or \
                    list(vasprun_files.keys())[0] != "relax1":
                d["state"] = "successful" if d2["has_vasp_completed"] \
                    else "unsuccessful"
            else:
                d["state"] = "stopped"
            d["analysis"] = get_basic_analysis_and_error_checks(d)

            sg = SpacegroupAnalyzer(Structure.from_dict(d["output"]["crystal"]),
                                    0.1)
            d["spacegroup"] = {"symbol": sg.get_space_group_symbol(),
                               "number": sg.get_space_group_number(),
                               "point_group": sg.get_point_group_symbol(),
                               "source": "spglib",
                               "crystal_system": sg.get_crystal_system(),
                               "hall": sg.get_hall()}
            d["last_updated"] = datetime.datetime.today()
            return d
        except Exception as ex:
            import traceback
            print(traceback.format_exc())
            logger.error("Error in " + os.path.abspath(dir_name) +
                         ".\n" + traceback.format_exc())

            return None
Beispiel #18
0
    def convert_to_ieee(self, structure, atol = 0.1, ltol = 0.05):
        """
        Given a structure associated with a tensor, attempts a
        calculation of the tensor in IEEE format according to
        the 1987 IEEE standards.

        Args:
            structure (Structure): a structure associated with the
                tensor to be converted to the IEEE standard
            atol (float): angle tolerance for conversion routines
            ltol (float): length tolerance for conversion routines
        """
        def get_uvec(vec):
            """ Gets a unit vector parallel to input vector"""
            return vec / np.linalg.norm(vec)

        # Check conventional setting:
        sga = SpacegroupAnalyzer(structure)
        dataset = sga.get_symmetry_dataset()
        trans_mat = dataset['transformation_matrix']
        conv_latt = Lattice(np.transpose(np.dot(np.transpose(
            structure.lattice.matrix), np.linalg.inv(trans_mat))))
        xtal_sys = sga.get_crystal_system()
        
        vecs = conv_latt.matrix
        lengths = np.array(conv_latt.abc)
        angles = np.array(conv_latt.angles)
        a = b = c = None
        rotation = np.zeros((3,3))

        # IEEE rules: a,b,c || x1,x2,x3
        if xtal_sys == "cubic":
            rotation = [vecs[i]/lengths[i] for i in range(3)]

        # IEEE rules: a=b in length; c,a || x3, x1
        elif xtal_sys == "tetragonal":
            rotation = np.array([vec/mag for (mag, vec) in 
                                 sorted(zip(lengths, vecs))])
            if abs(lengths[2] - lengths[1]) < ltol:
                rotation[0], rotation[2] = rotation[2], rotation[0].copy()
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: c<a<b; c,a || x3,x1
        elif xtal_sys == "orthorhombic":
            rotation = [vec/mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis = 0)

        # IEEE rules: c,a || x3,x1, c is threefold axis
        # Note this also includes rhombohedral crystal systems
        elif xtal_sys in ("trigonal", "hexagonal"):
            # find threefold axis:
            tf_mask = abs(angles-120.0) < atol
            non_tf_mask = np.logical_not(tf_mask)
            rotation[2] = get_uvec(vecs[tf_mask][0])
            rotation[0] = get_uvec(vecs[non_tf_mask][0])
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: b,c || x2,x3; alpha=beta=90, c<a
        elif xtal_sys == "monoclinic":
            # Find unique axis
            umask = abs(angles - 90.0) > atol
            n_umask = np.logical_not(umask)
            rotation[1] = get_uvec(vecs[umask])
            # Shorter of remaining lattice vectors for c axis
            c = [vec/mag for (mag, vec) in 
                 sorted(zip(lengths[n_umask], vecs[n_umask]))][0]
            rotation[2] = np.array(c)
            rotation[0] = np.cross(rotation[1], rotation[2])
        
        # IEEE rules: c || x3
        elif xtal_sys == "triclinic":
            rotation = [vec/mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis = 0)
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[1]))
            rotation[0] = np.cross(rotation[1], rotation[2])
        
        return self.rotate(rotation)
Beispiel #19
0
    def convert_to_ieee(self, structure, initial_fit=True):
        """
        Given a structure associated with a tensor, attempts a
        calculation of the tensor in IEEE format according to
        the 1987 IEEE standards.

        Args:
            structure (Structure): a structure associated with the
                tensor to be converted to the IEEE standard
            initial_fit (bool): flag to indicate whether initial
                tensor is fit to the symmetry of the structure.
                Defaults to true. Note that if false, inconsistent
                results may be obtained due to symmetrically
                equivalent, but distinct transformations
                being used in different versions of spglib.
        """

        def get_uvec(v):
            """ Gets a unit vector parallel to input vector"""
            l = np.linalg.norm(v)
            if l < 1e-8:
                return v
            return v / l

        # Check conventional setting:
        sga = SpacegroupAnalyzer(structure)
        dataset = sga.get_symmetry_dataset()
        trans_mat = dataset['transformation_matrix']
        conv_latt = Lattice(np.transpose(np.dot(np.transpose(
            structure.lattice.matrix), np.linalg.inv(trans_mat))))
        xtal_sys = sga.get_crystal_system()

        vecs = conv_latt.matrix
        lengths = np.array(conv_latt.abc)
        angles = np.array(conv_latt.angles)
        rotation = np.zeros((3, 3))

        # IEEE rules: a,b,c || x1,x2,x3
        if xtal_sys == "cubic":
            rotation = [vecs[i] / lengths[i] for i in range(3)]

        # IEEE rules: a=b in length; c,a || x3, x1
        elif xtal_sys == "tetragonal":
            rotation = np.array([vec / mag for (mag, vec) in
                                 sorted(zip(lengths, vecs),
                                        key=lambda x: x[0])])
            if abs(lengths[2] - lengths[1]) < abs(lengths[1] - lengths[0]):
                rotation[0], rotation[2] = rotation[2], rotation[0].copy()
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: c<a<b; c,a || x3,x1
        elif xtal_sys == "orthorhombic":
            rotation = [vec / mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis=0)

        # IEEE rules: c,a || x3,x1, c is threefold axis
        # Note this also includes rhombohedral crystal systems
        elif xtal_sys in ("trigonal", "hexagonal"):
            # find threefold axis:
            tf_index = np.argmin(abs(angles - 120.))
            non_tf_mask = np.logical_not(angles == angles[tf_index])
            rotation[2] = get_uvec(vecs[tf_index])
            rotation[0] = get_uvec(vecs[non_tf_mask][0])
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: b,c || x2,x3; alpha=beta=90, c<a
        elif xtal_sys == "monoclinic":
            # Find unique axis
            u_index = np.argmax(abs(angles - 90.))
            n_umask = np.logical_not(angles == angles[u_index])
            rotation[1] = get_uvec(vecs[u_index])
            # Shorter of remaining lattice vectors for c axis
            c = [vec / mag for (mag, vec) in
                 sorted(zip(lengths[n_umask], vecs[n_umask]))][0]
            rotation[2] = np.array(c)
            rotation[0] = np.cross(rotation[1], rotation[2])

        # IEEE rules: c || x3
        elif xtal_sys == "triclinic":
            rotation = [vec / mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis=0)
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[1]))
            rotation[0] = np.cross(rotation[1], rotation[2])

        result = self.copy()
        if initial_fit:
            result = result.fit_to_structure(structure)
        return result.rotate(rotation, tol=1e-2)
Beispiel #20
0
class SpacegroupAnalyzerTest(PymatgenTest):
    def setUp(self):
        p = Poscar.from_file(os.path.join(test_dir, 'POSCAR'))
        self.structure = p.structure
        self.sg = SpacegroupAnalyzer(self.structure, 0.001)
        self.disordered_structure = self.get_structure('Li10GeP2S12')
        self.disordered_sg = SpacegroupAnalyzer(self.disordered_structure,
                                                0.001)
        s = p.structure.copy()
        site = s[0]
        del s[0]
        s.append(site.species_and_occu, site.frac_coords)
        self.sg3 = SpacegroupAnalyzer(s, 0.001)
        graphite = self.get_structure('Graphite')
        graphite.add_site_property("magmom", [0.1] * len(graphite))
        self.sg4 = SpacegroupAnalyzer(graphite, 0.001)
        self.structure4 = graphite

    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 test_magnetic(self):
        lfp = PymatgenTest.get_structure("LiFePO4")
        sg = SpacegroupAnalyzer(lfp, 0.1)
        self.assertEqual(sg.get_spacegroup_symbol(), "Pnma")
        magmoms = [0] * len(lfp)
        magmoms[4] = 1
        magmoms[5] = -1
        magmoms[6] = 1
        magmoms[7] = -1
        lfp.add_site_property("magmom", magmoms)
        sg = SpacegroupAnalyzer(lfp, 0.1)
        self.assertEqual(sg.get_spacegroup_symbol(), "Pnma")

    def test_get_space_symbol(self):
        self.assertEqual(self.sg.get_spacegroup_symbol(), "Pnma")
        self.assertEqual(self.disordered_sg.get_spacegroup_symbol(),
                         "P4_2/nmc")
        self.assertEqual(self.sg3.get_spacegroup_symbol(), "Pnma")
        self.assertEqual(self.sg4.get_spacegroup_symbol(), "P6_3/mmc")

    def test_get_space_number(self):
        self.assertEqual(self.sg.get_spacegroup_number(), 62)
        self.assertEqual(self.disordered_sg.get_spacegroup_number(), 137)
        self.assertEqual(self.sg4.get_spacegroup_number(), 194)

    def test_get_hall(self):
        self.assertEqual(self.sg.get_hall(), '-P 2ac 2n')
        self.assertEqual(self.disordered_sg.get_hall(), 'P 4n 2n -1n')

    def test_get_pointgroup(self):
        self.assertEqual(self.sg.get_point_group(), 'mmm')
        self.assertEqual(self.disordered_sg.get_point_group(), '4/mmm')

    def test_get_symmetry_dataset(self):
        ds = self.sg.get_symmetry_dataset()
        self.assertEqual(ds['international'], 'Pnma')

    def test_get_crystal_system(self):
        crystal_system = self.sg.get_crystal_system()
        self.assertEqual('orthorhombic', crystal_system)
        self.assertEqual('tetragonal', self.disordered_sg.get_crystal_system())

    def test_get_symmetry_operations(self):
        for sg, structure in [(self.sg, self.structure),
                              (self.sg4, self.structure4)]:

            pgops = sg.get_point_group_operations()
            fracsymmops = sg.get_symmetry_operations()
            symmops = sg.get_symmetry_operations(True)
            latt = structure.lattice
            for fop, op, pgop in zip(fracsymmops, symmops, pgops):
                self.assertArrayAlmostEqual(fop.rotation_matrix,
                                            pgop.rotation_matrix)
                for site in structure:
                    newfrac = fop.operate(site.frac_coords)
                    newcart = op.operate(site.coords)
                    self.assertTrue(
                        np.allclose(latt.get_fractional_coords(newcart),
                                    newfrac))
                    found = False
                    newsite = PeriodicSite(site.species_and_occu,
                                           newcart,
                                           latt,
                                           coords_are_cartesian=True)
                    for testsite in structure:
                        if newsite.is_periodic_image(testsite, 1e-3):
                            found = True
                            break
                    self.assertTrue(found)

                # Make sure this works for any position, not just the atomic
                # ones.
                random_fcoord = np.random.uniform(size=(3))
                random_ccoord = latt.get_cartesian_coords(random_fcoord)
                newfrac = fop.operate(random_fcoord)
                newcart = op.operate(random_ccoord)
                self.assertTrue(
                    np.allclose(latt.get_fractional_coords(newcart), newfrac))

    def test_get_refined_structure(self):
        for a in self.sg.get_refined_structure().lattice.angles:
            self.assertEqual(a, 90)
        refined = self.disordered_sg.get_refined_structure()
        for a in refined.lattice.angles:
            self.assertEqual(a, 90)
        self.assertEqual(refined.lattice.a, refined.lattice.b)
        s = self.get_structure('Li2O')
        sg = SpacegroupAnalyzer(s, 0.001)
        self.assertEqual(sg.get_refined_structure().num_sites, 4 * s.num_sites)

    def test_get_symmetrized_structure(self):
        symm_struct = self.sg.get_symmetrized_structure()
        for a in symm_struct.lattice.angles:
            self.assertEqual(a, 90)
        self.assertEqual(len(symm_struct.equivalent_sites), 5)

        symm_struct = self.disordered_sg.get_symmetrized_structure()
        self.assertEqual(len(symm_struct.equivalent_sites), 8)
        self.assertEqual([len(i) for i in symm_struct.equivalent_sites],
                         [16, 4, 8, 4, 2, 8, 8, 8])
        s1 = symm_struct.equivalent_sites[1][1]
        s2 = symm_struct[symm_struct.equivalent_indices[1][1]]
        self.assertEqual(s1, s2)
        self.assertEqual(self.sg4.get_symmetrized_structure()[0].magmom, 0.1)

    def test_find_primitive(self):
        """
        F m -3 m Li2O testing of converting to primitive cell
        """
        parser = CifParser(os.path.join(test_dir, 'Li2O.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure)
        primitive_structure = s.find_primitive()
        self.assertEqual(primitive_structure.formula, "Li2 O1")
        # This isn't what is expected. All the angles should be 60
        self.assertAlmostEqual(primitive_structure.lattice.alpha, 60)
        self.assertAlmostEqual(primitive_structure.lattice.beta, 60)
        self.assertAlmostEqual(primitive_structure.lattice.gamma, 60)
        self.assertAlmostEqual(primitive_structure.lattice.volume,
                               structure.lattice.volume / 4.0)

    def test_get_ir_reciprocal_mesh(self):
        grid = self.sg.get_ir_reciprocal_mesh()
        self.assertEqual(len(grid), 216)
        self.assertAlmostEquals(grid[1][0][0], 0.1)
        self.assertAlmostEquals(grid[1][0][1], 0.0)
        self.assertAlmostEquals(grid[1][0][2], 0.0)
        self.assertAlmostEquals(grid[1][1], 2)

    def test_get_conventional_standard_structure(self):
        parser = CifParser(os.path.join(test_dir, 'bcc_1927.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 9.1980270633769461)
        self.assertAlmostEqual(conv.lattice.b, 9.1980270633769461)
        self.assertAlmostEqual(conv.lattice.c, 9.1980270633769461)

        parser = CifParser(os.path.join(test_dir, 'btet_1915.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 5.0615106678044235)
        self.assertAlmostEqual(conv.lattice.b, 5.0615106678044235)
        self.assertAlmostEqual(conv.lattice.c, 4.2327080177761687)

        parser = CifParser(os.path.join(test_dir, 'orci_1010.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 2.9542233922299999)
        self.assertAlmostEqual(conv.lattice.b, 4.6330325651443296)
        self.assertAlmostEqual(conv.lattice.c, 5.373703587040775)

        parser = CifParser(os.path.join(test_dir, 'orcc_1003.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 4.1430033493799998)
        self.assertAlmostEqual(conv.lattice.b, 31.437979757624728)
        self.assertAlmostEqual(conv.lattice.c, 3.99648651)

        parser = CifParser(os.path.join(test_dir, 'monoc_1028.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 117.53832420192903)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 14.033435583000625)
        self.assertAlmostEqual(conv.lattice.b, 3.96052850731)
        self.assertAlmostEqual(conv.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'hex_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 90)
        self.assertAlmostEqual(conv.lattice.gamma, 120)
        self.assertAlmostEqual(conv.lattice.a, 3.699919902005897)
        self.assertAlmostEqual(conv.lattice.b, 3.699919902005897)
        self.assertAlmostEqual(conv.lattice.c, 6.9779585500000003)

    def test_get_primitive_standard_structure(self):
        parser = CifParser(os.path.join(test_dir, 'bcc_1927.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.beta, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.gamma, 109.47122063400001)
        self.assertAlmostEqual(prim.lattice.a, 7.9657251015812145)
        self.assertAlmostEqual(prim.lattice.b, 7.9657251015812145)
        self.assertAlmostEqual(prim.lattice.c, 7.9657251015812145)

        parser = CifParser(os.path.join(test_dir, 'btet_1915.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 105.015053349)
        self.assertAlmostEqual(prim.lattice.beta, 105.015053349)
        self.assertAlmostEqual(prim.lattice.gamma, 118.80658411899999)
        self.assertAlmostEqual(prim.lattice.a, 4.1579321075608791)
        self.assertAlmostEqual(prim.lattice.b, 4.1579321075608791)
        self.assertAlmostEqual(prim.lattice.c, 4.1579321075608791)

        parser = CifParser(os.path.join(test_dir, 'orci_1010.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 134.78923546600001)
        self.assertAlmostEqual(prim.lattice.beta, 105.856239333)
        self.assertAlmostEqual(prim.lattice.gamma, 91.276341676000001)
        self.assertAlmostEqual(prim.lattice.a, 3.8428217771014852)
        self.assertAlmostEqual(prim.lattice.b, 3.8428217771014852)
        self.assertAlmostEqual(prim.lattice.c, 3.8428217771014852)

        parser = CifParser(os.path.join(test_dir, 'orcc_1003.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 90)
        self.assertAlmostEqual(prim.lattice.beta, 90)
        self.assertAlmostEqual(prim.lattice.gamma, 164.985257335)
        self.assertAlmostEqual(prim.lattice.a, 15.854897098324196)
        self.assertAlmostEqual(prim.lattice.b, 15.854897098324196)
        self.assertAlmostEqual(prim.lattice.c, 3.99648651)

        parser = CifParser(os.path.join(test_dir, 'monoc_1028.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 63.579155761999999)
        self.assertAlmostEqual(prim.lattice.beta, 116.42084423747779)
        self.assertAlmostEqual(prim.lattice.gamma, 148.47965136208569)
        self.assertAlmostEqual(prim.lattice.a, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.b, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'hex_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 90)
        self.assertAlmostEqual(prim.lattice.beta, 90)
        self.assertAlmostEqual(prim.lattice.gamma, 120)
        self.assertAlmostEqual(prim.lattice.a, 3.699919902005897)
        self.assertAlmostEqual(prim.lattice.b, 3.699919902005897)
        self.assertAlmostEqual(prim.lattice.c, 6.9779585500000003)

        parser = CifParser(os.path.join(test_dir, 'rhomb_3478_conv.cif'))
        structure = parser.get_structures(False)[0]
        s = SpacegroupAnalyzer(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 28.049186140546812)
        self.assertAlmostEqual(prim.lattice.beta, 28.049186140546812)
        self.assertAlmostEqual(prim.lattice.gamma, 28.049186140546812)
        self.assertAlmostEqual(prim.lattice.a, 5.9352627428399982)
        self.assertAlmostEqual(prim.lattice.b, 5.9352627428399982)
        self.assertAlmostEqual(prim.lattice.c, 5.9352627428399982)