Exemple #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!")
Exemple #2
0
def create_saturated_interstitial_structure(interstitial_def, dist_tol=0.1):
    """
    this takes a Interstitial defect object and generates the
    sublattice for it based on the structure's space group.
    Useful for understanding multiplicity of an interstitial
    defect in thermodynamic analysis.

    NOTE: if large relaxation happens to interstitial or
        defect involves a complex then there may be additional
        degrees of freedom that need to be considered for
        the multiplicity.

    Args:
        dist_tol: changing distance tolerance of saturated structure,
                allowing for possibly overlapping sites
                but ensuring space group is maintained

    Returns:
        Structure object decorated with interstitial site equivalents
    """
    sga = SpacegroupAnalyzer(interstitial_def.bulk_structure.copy())
    sg_ops = sga.get_symmetry_operations(cartesian=True)

    # copy bulk structure to make saturated interstitial structure out of
    # artificially lower distance_tolerance to allow for distinct interstitials
    # with lower symmetry to be replicated - This is OK because one would never
    # actually use this structure for a practical calcualtion...
    saturated_defect_struct = interstitial_def.bulk_structure.copy()
    saturated_defect_struct.DISTANCE_TOLERANCE = dist_tol

    for sgo in sg_ops:
        new_interstit_coords = sgo.operate(interstitial_def.site.coords[:])
        poss_new_site = PeriodicSite(
            interstitial_def.site.specie,
            new_interstit_coords,
            saturated_defect_struct.lattice,
            to_unit_cell=True,
            coords_are_cartesian=True,
        )
        try:
            # will raise value error if site already exists in structure
            saturated_defect_struct.append(
                poss_new_site.specie,
                poss_new_site.coords,
                coords_are_cartesian=True,
                validate_proximity=True,
            )
        except ValueError:
            pass

    # do final space group analysis to make sure symmetry not lowered by saturating defect structure
    saturated_sga = SpacegroupAnalyzer(saturated_defect_struct)
    if saturated_sga.get_space_group_number() != sga.get_space_group_number():
        raise ValueError(
            "Warning! Interstitial sublattice generation "
            "has changed space group symmetry. Recommend "
            "reducing dist_tol and trying again..."
        )

    return saturated_defect_struct
    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!")
Exemple #4
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(PymatgenTest.TEST_FILES_DIR, "POSCAR.tricky_symmetry"))
     sa = SpacegroupAnalyzer(s, 0.1)
     sa.get_space_group_symbol()
     sa.get_space_group_number()
     sa.get_point_group_symbol()
     sa.get_crystal_system()
     sa.get_hall()
Exemple #5
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_space_group_symbol()
     sa.get_space_group_number()
     sa.get_point_group_symbol()
     sa.get_crystal_system()
     sa.get_hall()
Exemple #6
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(test_dir / 'POSCAR.tricky_symmetry')
     sa = SpacegroupAnalyzer(s, 0.1)
     sa.get_space_group_symbol()
     sa.get_space_group_number()
     sa.get_point_group_symbol()
     sa.get_crystal_system()
     sa.get_hall()
Exemple #7
0
def create_saturated_interstitial_structure( interstitial_def, dist_tol=0.1):
    """
    this takes a Interstitial defect object and generates the
    sublattice for it based on the structure's space group.
    Useful for understanding multiplicity of an interstitial
    defect in thermodynamic analysis.

    NOTE: if large relaxation happens to interstitial or
        defect involves a complex then there may be additional
        degrees of freedom that need to be considered for
        the multiplicity.

    Args:
        dist_tol: changing distance tolerance of saturated structure,
                allowing for possibly overlapping sites
                but ensuring space group is maintained

    Returns:
        Structure object decorated with interstitial site equivalents
    """
    sga = SpacegroupAnalyzer( interstitial_def.bulk_structure.copy())
    sg_ops = sga.get_symmetry_operations( cartesian=True)

    # copy bulk structure to make saturated interstitial structure out of
    # artificially lower distance_tolerance to allow for distinct interstitials
    # with lower symmetry to be replicated - This is OK because one would never
    # actually use this structure for a practical calcualtion...
    saturated_defect_struct = interstitial_def.bulk_structure.copy()
    saturated_defect_struct.DISTANCE_TOLERANCE = dist_tol

    for sgo in sg_ops:
        new_interstit_coords = sgo.operate( interstitial_def.site.coords[:])
        poss_new_site = PeriodicSite(
                interstitial_def.site.specie,
                new_interstit_coords,
                saturated_defect_struct.lattice,
                to_unit_cell=True,
                coords_are_cartesian=True)
        try:
            #will raise value error if site already exists in structure
            saturated_defect_struct.append(
                        poss_new_site.specie, poss_new_site.coords,
                        coords_are_cartesian=True, validate_proximity=True)
        except ValueError:
            pass

    # do final space group analysis to make sure symmetry not lowered by saturating defect structure
    saturated_sga = SpacegroupAnalyzer( saturated_defect_struct)
    if saturated_sga.get_space_group_number() != sga.get_space_group_number():
        raise ValueError("Warning! Interstitial sublattice generation "
                         "has changed space group symmetry. Recommend "
                         "reducing dist_tol and trying again...")

    return saturated_defect_struct
Exemple #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]
Exemple #9
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()
Exemple #10
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")
    def __init__(self,
                 band: BandStructureSymmLine,
                 band2: BandStructureSymmLine = None,
                 absolute: bool = False,
                 y_range: list = None,
                 legend: bool = False,
                 symprec: float = SYMMETRY_TOLERANCE,
                 angle_tolerance: float = ANGLE_TOL):

        bs_plotter = ModBSPlotter(band)
        composition = str(band.structure.composition)
        sga = SpacegroupAnalyzer(structure=band.structure,
                                 symprec=symprec,
                                 angle_tolerance=angle_tolerance)

        sg_symbol = sga.get_space_group_symbol()
        sg_num = sga.get_space_group_number()

        kwargs = {
            "ylim": y_range,
            "legend": legend,
            "zero_to_efermi": absolute,
            "title": f"{composition} SG: {sg_symbol} ({sg_num})"
        }

        if not band2:
            self.plotter = bs_plotter.get_plot(**kwargs)
        else:
            bs_plotter2 = ModBSPlotter(band2)
            self.plotter = bs_plotter2.plot_compare(bs_plotter, **kwargs)
Exemple #12
0
def get_structure_data(structure):
    sga = SpacegroupAnalyzer(structure)
    return {
        "xtal_system": sga.get_crystal_system(),
        "spacegroup_sym": sga.get_space_group_symbol(),
        "spacegroup_num": sga.get_space_group_number()
    }
Exemple #13
0
    def from_structure(cls, structure: Structure) -> "SymmetryData":
        symprec = SETTINGS.SYMPREC
        sg = SpacegroupAnalyzer(structure, symprec=symprec)
        symmetry: Dict[str, Any] = {"symprec": symprec}
        if not sg.get_symmetry_dataset():
            sg = SpacegroupAnalyzer(structure, 1e-3, 1)
            symmetry["symprec"] = 1e-3

        symmetry.update({
            "source":
            "spglib",
            "symbol":
            sg.get_space_group_symbol(),
            "number":
            sg.get_space_group_number(),
            "point_group":
            sg.get_point_group_symbol(),
            "crystal_system":
            CrystalSystem(sg.get_crystal_system().title()),
            "hall":
            sg.get_hall(),
            "version":
            spglib.__version__,
        })

        return SymmetryData(**symmetry)
Exemple #14
0
    def poscar(self):
        """   generating poscar for relaxation calculations   """
        print(
            '--------------------------------------------------------------------------------------------------------'
        )
        print("Generation of VASP files for the cell relaxation:")
        print(
            '--------------------------------------------------------------------------------------------------------'
        )

        self.symData.structure = Structure.from_file(self.args.pos[0])
        sym1 = float(self.args.sympre[0])
        sym2 = float(self.args.symang[0])
        aa = SpacegroupAnalyzer(self.symData.structure,
                                symprec=sym1,
                                angle_tolerance=sym2)
        self.symData.space_group = aa.get_space_group_number()
        print("Space group number =", self.symData.space_group)
        spg = aa.get_space_group_symbol()
        print("Space group symbol =", str(spg))
        self.symData.number_of_species = len(self.symData.structure.species)
        print("Number of atoms = {}".format(len(
            self.symData.structure.species)))

        pos_name = "POSCAR"
        structure00 = Poscar(self.symData.structure)
        structure00.write_file(filename=pos_name, significant_figures=16)

        return self.symData
Exemple #15
0
 def get_energy(self, structure):
     """
     :param structure: Structure
     :return: Energy value
     """
     f = SpacegroupAnalyzer(structure, symprec=self.symprec, angle_tolerance=self.angle_tolerance)
     return -f.get_space_group_number()
Exemple #16
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()
Exemple #17
0
    def test_apply_transformation(self):
        trans = MagOrderingTransformation({"Fe": 5})
        p = Poscar.from_file(os.path.join(test_dir, 'POSCAR.LiFePO4'),
                             check_for_POTCAR=False)
        s = p.structure
        alls = trans.apply_transformation(s, 10)
        self.assertEqual(len(alls), 3)
        f = SpacegroupAnalyzer(alls[0]["structure"], 0.1)
        self.assertEqual(f.get_space_group_number(), 31)

        model = IsingModel(5, 5)
        trans = MagOrderingTransformation({"Fe": 5},
                                          energy_model=model)
        alls2 = trans.apply_transformation(s, 10)
        # Ising model with +J penalizes similar neighbor magmom.
        self.assertNotEqual(alls[0]["structure"], alls2[0]["structure"])
        self.assertEqual(alls[0]["structure"], alls2[2]["structure"])

        s = self.get_structure('Li2O')
        # Li2O doesn't have magnetism of course, but this is to test the
        # enumeration.
        trans = MagOrderingTransformation({"Li+": 1}, max_cell_size=3)
        alls = trans.apply_transformation(s, 100)
        # TODO: check this is correct, unclear what len(alls) should be
        self.assertEqual(len(alls), 12)

        trans = MagOrderingTransformation({"Ni": 5})
        alls = trans.apply_transformation(self.NiO.get_primitive_structure(),
                                          return_ranked_list=10)

        self.assertArrayAlmostEqual(self.NiO_AFM_111.lattice.parameters,
                                    alls[0]["structure"].lattice.parameters)
        self.assertArrayAlmostEqual(self.NiO_AFM_001.lattice.parameters,
                                    alls[1]["structure"].lattice.parameters)
    def __init__(self,
                 group_uuid,
                 structure,
                 sc_size,
                 process_label,
                 energy_threshold=0.01,
                 symprec=1e-3,
                 if_with_energy=True):
        """
        Parameters:
        -----------
        uuid : int 
               A uuid of a given group to generate the cluster
        structure : Structure 
                    A structure object to generate the symmetry operations
        sc_size : int 
                  A list of supercell size to generate symmetry operations
        process_label : str
                        workchain name to query calculation from
        energy_threshold : float 
                     Tolerance of energy difference threshold. Default = 0.01
        symprec : float 
                  Tolerance in atomic distance to test if atoms are symmetrically similar. 
                  Default = 0.1 (if for positions obtain from electronic structure)        
        if_with_energy : bool
                      If False, to not query energy . Default=True                      
        """

        self.group_uuid = group_uuid
        self.structure = structure
        self.process_label = process_label
        self.energy_threshold = energy_threshold
        self.symprec = symprec
        self.if_with_energy = if_with_energy
        #self.frac_coords = frac_coords

        if sc_size is None or sc_size == "":
            self.sc_size = "1 1 1"
        else:
            self.sc_size = sc_size

        self.structure_sc = structure.copy()
        self.structure_sc.make_supercell(
            [int(x) for x in self.sc_size.split()])

        # Query nodes, energy, positions
        QG = QueryCalculationsFromGroup(self.group_uuid, self.process_label)

        self.uuid = QG.get_relaxed_nodes()
        self.positions = QG.get_positions()
        if self.if_with_energy:
            self.energies = QG.get_energies()
        else:
            self.energies = np.zeros([len(self.uuid)])
        """#To find the space group symmetry operations of the structure 
        """
        SA = SpacegroupAnalyzer(self.structure_sc)
        self.SG = SpacegroupOperations(
            SA.get_space_group_number(), SA.get_space_group_symbol(),
            SA.get_symmetry_operations(cartesian=False))
    def test_apply_transformation(self):
        trans = MagOrderingTransformation({"Fe": 5})
        p = Poscar.from_file(os.path.join(test_dir, 'POSCAR.LiFePO4'),
                             check_for_POTCAR=False)
        s = p.structure
        alls = trans.apply_transformation(s, 10)
        self.assertEqual(len(alls), 3)
        f = SpacegroupAnalyzer(alls[0]["structure"], 0.1)
        self.assertEqual(f.get_space_group_number(), 31)

        model = IsingModel(5, 5)
        trans = MagOrderingTransformation({"Fe": 5},
                                          energy_model=model)
        alls2 = trans.apply_transformation(s, 10)
        # Ising model with +J penalizes similar neighbor magmom.
        self.assertNotEqual(alls[0]["structure"], alls2[0]["structure"])
        self.assertEqual(alls[0]["structure"], alls2[2]["structure"])

        s = self.get_structure('Li2O')
        # Li2O doesn't have magnetism of course, but this is to test the
        # enumeration.
        trans = MagOrderingTransformation({"Li+": 1}, max_cell_size=3)
        alls = trans.apply_transformation(s, 100)
        # TODO: check this is correct, unclear what len(alls) should be
        self.assertEqual(len(alls), 12)

        trans = MagOrderingTransformation({"Ni": 5})
        alls = trans.apply_transformation(self.NiO.get_primitive_structure(),
                                          return_ranked_list=10)
        self.assertEqual(self.NiO_AFM_111.lattice, alls[0]["structure"].lattice)
        self.assertEqual(self.NiO_AFM_001.lattice, alls[1]["structure"].lattice)
Exemple #20
0
 def set_material_data_from_structure(self,
                                      structure,
                                      space_group=True,
                                      symprec=1e-3,
                                      angle_tolerance=5):
     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")
Exemple #21
0
def print_info(struc):
    """
	Read a Structure object and print structure information.

	Args: 
	    struc : pymatgen Structure object.

	Returns:
		None.
	"""

    print(struc)

    print('\n')

    sga = SpacegroupAnalyzer(struc)

    print('The space group: {} {}\n'.format(sga.get_space_group_number(),
                                            sga.get_space_group_symbol()))

    equi_sites = sga.get_symmetrized_structure().equivalent_sites
    for sites in equi_sites:
        print('the symmtry equivalent sites are \n{}\n'.format(sites))

    sym_operations = sga.get_symmetry_operations()
    print('there are {} symmetry operations: \n {} \n'.format(
        len(sym_operations), sym_operations))
Exemple #22
0
    def __init__(self, folder_name):
        """
        Run irvsp to compute irreducible representations (irreps) of electronic states from wavefunctions (WAVECAR) and
        symmetry operations (OUTCAR).

        Requires a calculation with ISYM=1,2 and LWAVE=.TRUE.

        Something like "phonopy --tolerance 0.01 --symmetry -c POSCAR" should be used to ensure
        the crystal is in a standard setting before the calculation.

        irvsp v2 is needed to handle all 230 space groups (including nonsymmorphic sgs).

        Args:
            folder_name (str): Path to directory with POSCAR, OUTCAR and WAVECAR at kpts where irreps should be computed.
        """

        # Check for OUTCAR and WAVECAR
        if (not path.isfile(folder_name + "/OUTCAR")
                or not path.isfile(folder_name + "/WAVECAR")
                or not path.isfile(folder_name + "/POSCAR")):
            raise FileNotFoundError()

        os.chdir(folder_name)

        # Get sg number of structure
        s = Structure.from_file("POSCAR")
        sga = SpacegroupAnalyzer(s, symprec=0.01)
        sgn = sga.get_space_group_number()
        v = 1  # version 1 of irvsp, symmorphic symmetries

        # Check if symmorphic (same symm elements as corresponding point group)
        # REF: http://kuchem.kyoto-u.ac.jp/kinso/weda/data/group/space.pdf
        fpath = os.path.join(os.path.dirname(__file__),
                             "symmorphic_spacegroups.json")
        ssgs = loadfn(fpath)["ssgs"]

        # Remove SGOs from OUTCAR other than identity and inversion to avoid errors

        #if sgn not in ssgs:  # non-symmorphic; this doesn't work!

        self.modify_outcar()
        sgn = 2  # SG 2 (only E and I)

        # Call irvsp
        cmd_list = ["irvsp", "-sg", str(sgn), "-v", str(v)]
        with open("outir.txt", "w") as out, open("err.txt", "w") as err:
            process = subprocess.Popen(cmd_list, stdout=out, stderr=err)

        process.communicate()  # pause while irvsp is executing

        self.output = None

        # Process output
        if path.isfile("outir.txt"):
            self.output = IRVSPOutput("outir.txt")

        else:
            raise FileNotFoundError()
Exemple #23
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)
    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)
 def print_spg(src='POSCAR'):
     """
     space group を return
     """
     srcpos = Poscar.from_file(src)
     finder = SpacegroupAnalyzer(srcpos.structure,
                                 symprec=5e-2, angle_tolerance=8)
     spg = finder.get_space_group_symbol()
     spg_num = finder.get_space_group_number()
     return spg, spg_num
Exemple #26
0
    def debye_find(self):
        hit = []
        phases = []
        count = []
        for i in self.items:
            mm = i['metadata']
            if mm in hit:
                count[hit.index(mm)] += 1
            else:
                hit.append(mm)
                count.append(1)
                structure = Structure.from_dict(i['structure'])
                formula_pretty = structure.composition.reduced_formula
                try:
                    formula2composition(formula_pretty)
                except:
                    formula_pretty = reduced_formula(
                        structure.composition.alphabetical_formula)
                sa = SpacegroupAnalyzer(structure)
                phasename = formula_pretty+'_'\
                    + sa.get_space_group_symbol().replace('/','.')+'_'+str(sa.get_space_group_number())
                if phasename in phases:
                    for jj in range(10000):
                        nphasename = phasename + "#" + str(jj)
                        if nphasename in phases: continue
                        phasename = nphasename
                        break
                phases.append(phasename)

        print("\nfound complete calculations in the collection:", self.qhamode,
              "\n")
        all_static_calculations = list((self.vasp_db).db['tasks'].\
            find({'$and':[{'metadata': { "$exists": True }}, {'adopted': True} ]},\
            {'metadata':1, 'output':1, 'input':1, 'orig_inputs':1}))
        for i, m in enumerate(hit):
            if self.skipby(phases[i], m['tag']): continue
            static_calculations = [
                f for f in all_static_calculations
                if f['metadata']['tag'] == m['tag']
            ]
            for ii, calc in enumerate(static_calculations):
                potsoc = get_used_pot(calc)
                if self.qhamode == 'qha': potsoc += "_debye"
                pname = phases[i].split('#')
                if len(pname) > 1:
                    phases[i] = pname[0] + potsoc + '#' + pname[1]
                else:
                    phases[i] = pname[0] + potsoc
                break
            print(m, ":", phases[i])
            self.tags.append({'tag': m['tag'], 'phasename': phases[i]})
Exemple #27
0
def get_spacegroup(strt=""):
    """
    Get spacegroup of a Structure pbject
    
    Args:
        strt: Structure object
    Returns:
           num: spacegroup number
           symb: spacegroup symbol
    """
    finder = SpacegroupAnalyzer(strt)
    num = finder.get_space_group_number()
    symb = finder.get_space_group_symbol()
    return num, symb
def main():
    # get args
    args = parse_arguments()

    # make output directory
    out_dir = args.out_dir
    out_dir_path = path.normpath(path.join(getcwd(), out_dir))
    makedirs(out_dir_path, exist_ok=True)
    cell_dir_path = path.join(out_dir_path, 'cell_image')
    makedirs(cell_dir_path, exist_ok=True)

    # load raw dataset
    structure_path = path.normpath(path.join(getcwd(), args.structure_path))
    csv_path = path.normpath(path.join(getcwd(), args.csv_path))
    mp_ids_path = path.normpath(path.join(getcwd(), args.mp_ids))
    structure_data = h5py.File(structure_path, "r")
    table_data = pd.read_csv(csv_path, index_col=False)
    mp_ids = np.load(mp_ids_path)
    table_data = table_data[table_data['material_id'].isin(mp_ids)]
    assert len(mp_ids) == len(table_data)

    cell_nbins = 32
    length = len(table_data['material_id'].values)
    cell_csv = pd.DataFrame(
        [],
        columns=['mp_id', 'crystal_system', 'space_group', 'image_name'],
        index=range(length))
    for i, mp_id in tqdm(enumerate(table_data['material_id'].values)):
        crystal = Structure.from_str(structure_data[mp_id].value, args.fmt)
        ase_atoms = AseAtomsAdaptor.get_atoms(crystal)
        cell_atoms = cell_translate(ase_atoms)
        cell_image, _ = ase_atoms_to_image(cell_atoms, cell_nbins,
                                           args.atom_list, args.jobs)

        # save cell image
        image_name = mp_id.replace('-', '_')
        cell_save_path = path.join(cell_dir_path, image_name)
        np.save('{}.npy'.format(cell_save_path), cell_image)

        # save basis image
        finder = SpacegroupAnalyzer(crystal)
        crystal_system = finder.get_crystal_system()
        space_group_num = finder.get_space_group_number()
        cell_csv.iloc[i] = [mp_id, crystal_system, space_group_num, image_name]

    # save
    cell_csv_save_path = path.join(out_dir_path, 'cell_image.csv')
    cell_csv.to_csv(cell_csv_save_path)

    return True
Exemple #29
0
def print_spg(src='POSCAR'):
    """
    空間群を出力
    """
    srcpos = Poscar.from_file(src)
    # srcpos.structure | fnc.echo
    finder = SpacegroupAnalyzer(srcpos.structure,
                                symprec=5e-2, angle_tolerance=8)
    # dir(finder) | fnc.echo
    # srcpos | fnc.echo
    # help(finder.get_space_group_symbol)
    # finder._space_group_data | fnc.echo
    spg = finder.get_space_group_symbol()
    spg_num = finder.get_space_group_number()
    print(spg)
    print(spg_num)
Exemple #30
0
def analyze_symmetry(request):
    results = {}
    symprec = float(request.POST["symprec"])
    angle_tolerance = float(request.POST["angle_tolerance"])
    for name, f in request.FILES.items():
        name, s = get_structure(f)
        a = SpacegroupAnalyzer(s,
                               symprec=symprec,
                               angle_tolerance=angle_tolerance)
        d = {}
        d["international"] = a.get_space_group_symbol()
        d["number"] = a.get_space_group_number()
        d["hall"] = a.get_hall()
        d["point_group"] = a.get_point_group()
        d["crystal_system"] = a.get_crystal_system()
        results[name] = d
    return results
Exemple #31
0
    def featurize(self, s):
        sga = SpacegroupAnalyzer(s)
        output = []

        if "spacegroup_num" in self.features:
            output.append(sga.get_space_group_number())

        if "crystal_system" in self.features:
            output.append(sga.get_crystal_system())

        if "crystal_system_int" in self.features:
            output.append(GlobalSymmetryFeatures.crystal_idx[
                              sga.get_crystal_system()])

        if "is_centrosymmetric" in self.features:
            output.append(sga.is_laue())

        return output
Exemple #32
0
 def debye_find(self):
     hit = []
     phases = []
     count = []
     for i in self.items:
         """
         try:
             ii = len(i['debye'])
             mm = i['metadata']
         except:
             continue
         if ii < 6: continue
         """
         mm = i['metadata']
         if mm in hit:
             count[hit.index(mm)] += 1
         else:
             hit.append(mm)
             count.append(1)
             structure = Structure.from_dict(i['structure'])
             formula_pretty = structure.composition.reduced_formula
             try:
                 formula2composition(formula_pretty)
             except:
                 formula_pretty = reduced_formula(
                     structure.composition.alphabetical_formula)
             sa = SpacegroupAnalyzer(structure)
             phasename = formula_pretty+'_'\
                 + sa.get_space_group_symbol().replace('/','.')+'_'+str(sa.get_space_group_number())
             if phasename in phases:
                 for jj in range(10000):
                     nphasename = phasename + "#" + str(jj)
                     if nphasename in phases: continue
                     phasename = nphasename
                     break
             phases.append(phasename)
     print("\nfound complete calculations in the collection:", self.qhamode,
           "\n")
     for i, m in enumerate(hit):
         if self.skipby(phases[i], m['tag']): continue
         print(m, ":", phases[i])
         self.tags.append({'tag': m['tag'], 'phasename': phases[i]})
Exemple #33
0
 def get_raman_modes(self) -> List[int]:
     space_group_calculater = SpacegroupAnalyzer(self.structure)
     symmetrized_structure = space_group_calculater.get_symmetrized_structure()
     space_group = space_group_calculater.get_space_group_number()
     wyckoff = symmetrized_structure.wyckoff_symbols
     with open("utils/reformed_raman_modes.json") as f:
         raman_table = json.load(f)
     all_modes = raman_table["all_modes"]
     mode_check_table = raman_table["all_spgp"][space_group-1]["modes"]
     mode_check_table = DataFrame.from_dict(mode_check_table)
     keys = mode_check_table.keys()
     for i in range(len(all_modes)):
         mode = all_modes[i]
         all_modes[i] = 0
         if mode in keys:
             modes_with_wyckoff = mode_check_table[mode]
             for wp in wyckoff:
                 if modes_with_wyckoff[wp] != 0:
                     all_modes[i] = 1
     return all_modes
Exemple #34
0
    def test_single_specie(self):
        # print("test_h2o")
        struc = molecular_crystal(36, ["H2O"], [4], sites=[["8b"]])
        struc.to_file()
        self.assertTrue(struc.valid)

        # test space group
        pmg_struc = struc.to_pymatgen()
        sga = SpacegroupAnalyzer(pmg_struc)
        # print(sga.get_space_group_symbol())
        self.assertTrue(sga.get_space_group_number() >= 36)
        # print(pmg_struc.frac_coords[:3])

        # test rotation
        ax = struc.mol_sites[0].orientation.axis
        struc.mol_sites[0].rotate(axis=[1, 0, 0], angle=90)
        pmg_struc = struc.to_pymatgen()
        sga = SpacegroupAnalyzer(pmg_struc)
        pmg_struc.to("cif", "1.cif")
        self.assertTrue(sga.get_space_group_symbol() == "Cmc2_1")
Exemple #35
0
def redundancy_check(blank_coords, adsonly_positions, fp_dict,
                     repeat_unit_cell, symmetry_tol):

    inv_ruc = np.linalg.inv(repeat_unit_cell)

    atoms = Atoms()
    for c in blank_coords:
        atoms.append(Atom(c[0], c[1]))

    formula = atoms.get_chemical_formula()
    atoms.set_cell(repeat_unit_cell.T)
    atoms.pbc = True
    struct = AseAtomsAdaptor.get_structure(atoms)
    sga = SpacegroupAnalyzer(struct, symprec=symmetry_tol)
    sgs = sga.get_space_group_symbol()
    sgn = sga.get_space_group_number()

    adsonly_positions = np.asarray(adsonly_positions)

    dists = []
    for i in range(len(adsonly_positions)):
        icoord = np.dot(inv_ruc, adsonly_positions[i])
        for j in range(i + 1, len(adsonly_positions)):
            jcoord = np.dot(inv_ruc, adsonly_positions[j])
            fdist, sym = PBC3DF_sym(icoord, jcoord)
            dist = np.linalg.norm(np.dot(repeat_unit_cell, fdist))
            dists.append(dist)
    dists.sort()

    index = 0
    advance = True
    for ind in range(len(fp_dict[sgn])):
        fp = fp_dict[sgn][ind]
        if len(fp) == len(dists):
            if np.allclose(fp, dists):
                index = ind
                advance = False
                break
    index = str(index)

    return advance, index, sgs, sgn, dists, atoms, formula
    def test_apply_transformation(self):
        trans = MagOrderingTransformation({"Fe": 5})
        p = Poscar.from_file(os.path.join(test_dir, "POSCAR.LiFePO4"), check_for_POTCAR=False)
        s = p.structure
        alls = trans.apply_transformation(s, 10)
        self.assertEqual(len(alls), 3)
        f = SpacegroupAnalyzer(alls[0]["structure"], 0.1)
        self.assertEqual(f.get_space_group_number(), 31)

        model = IsingModel(5, 5)
        trans = MagOrderingTransformation({"Fe": 5}, energy_model=model)
        alls2 = trans.apply_transformation(s, 10)
        # Ising model with +J penalizes similar neighbor magmom.
        self.assertNotEqual(alls[0]["structure"], alls2[0]["structure"])
        self.assertEqual(alls[0]["structure"], alls2[2]["structure"])

        s = self.get_structure("Li2O")
        # Li2O doesn't have magnetism of course, but this is to test the
        # enumeration.
        trans = MagOrderingTransformation({"Li+": 1}, max_cell_size=3)
        alls = trans.apply_transformation(s, 100)
        self.assertEqual(len(alls), 10)
Exemple #37
0
def add_cifs(doc):
    struc = Structure.from_dict(doc["structure"])
    sym_finder = SpacegroupAnalyzer(struc, symprec=0.1)
    doc["cif"] = str(CifWriter(struc))
    doc["cifs"] = {}
    if sym_finder.get_hall():
        primitive = sym_finder.get_primitive_standard_structure()
        conventional = sym_finder.get_conventional_standard_structure()
        refined = sym_finder.get_refined_structure()
        doc["cifs"]["primitive"] = str(CifWriter(primitive))
        doc["cifs"]["refined"] = str(CifWriter(refined))
        doc["cifs"]["conventional_standard"] = str(CifWriter(conventional))
        doc["cifs"]["computed"] = str(CifWriter(struc))
        doc["spacegroup"]["symbol"] = sym_finder.get_space_group_symbol()
        doc["spacegroup"]["number"] = sym_finder.get_space_group_number()
        doc["spacegroup"]["point_group"] = sym_finder.get_point_group_symbol()
        doc["spacegroup"]["crystal_system"] = sym_finder.get_crystal_system()
        doc["spacegroup"]["hall"] = sym_finder.get_hall()
    else:
        doc["cifs"]["primitive"] = None
        doc["cifs"]["refined"] = None
        doc["cifs"]["conventional_standard"] = None
def prepare_spacegroup(spg: SpacegroupAnalyzer):
    """Given a spacegroup pypatgen object, return a dictionary to be sent to jinja.

    This includes the international number, and the name in Hermann-Mauguin notation
    nicely formatted in HTML (so, will need the `safe` filter)."""
    return {
        "international_number":
        spg.get_space_group_number(),
        "hm_name":
        spg.get_space_group_symbol().replace(
            "-1", '<span style="text-decoration:overline;">1</span>').replace(
                "-3",
                '<span style="text-decoration:overline;">3</span>').replace(
                    "-4", '<span style="text-decoration:overline;">4</span>').
        replace("-6",
                '<span style="text-decoration:overline;">6</span>').replace(
                    "_1",
                    "<sub>1</sub>").replace("_2", "<sub>2</sub>").replace(
                        "_3",
                        "<sub>3</sub>").replace("_4", "<sub>4</sub>").replace(
                            "_5", "<sub>5</sub>"),
    }
Exemple #39
0
def structure_symmetry():
    structs, fnames = read_structures()
    multi_structs(structs, fnames)
    for struct, fname in zip(structs, fnames):
        if isinstance(struct, Structure):
            sa = SpacegroupAnalyzer(struct)
            print("file name: {}".format(fname))
            print("{} : {}".format('Structure Type', 'periodicity'))
            print("{} : {}".format('Lattice Type', sa.get_lattice_type()))
            print("{} : {}".format('Space Group ID',
                                   sa.get_space_group_number()))
            print("{} : {}".format('International Symbol',
                                   sa.get_space_group_symbol()))
            print("{} : {}".format('Hall Symbol', sa.get_hall()))
            sepline()
        if isinstance(struct, Molecule):
            print("file name: {}".format(fname))
            sa = PointGroupAnalyzer(struct)
            print("{} : {}".format('Structure Type', 'non-periodicity'))
            print("{} : {}".format('International Symbol',
                                   ast.get_pointgroup()))
    return True
Exemple #40
0
def create(**kwargs):
    """
    Generate deformed structures for calculating deformation potentials.
    """
    from pymatgen.core.structure import Structure
    from pymatgen.core.tensors import symmetry_reduce
    from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
    from pymatgen.util.string import unicodeify_spacegroup

    from amset.deformation.common import get_formatted_tensors
    from amset.deformation.generation import get_deformations, get_deformed_structures
    from amset.deformation.io import write_deformed_poscars

    symprec = _parse_symprec(kwargs["symprec"])

    structure = Structure.from_file(kwargs["filename"])

    click.echo("Generating deformations:")
    click.echo("  - Strain distance: {:g}".format(kwargs["distance"]))

    deformations = get_deformations(kwargs["distance"])
    click.echo("  - # Total deformations: {}".format(len(deformations)))

    if symprec is not None:
        sga = SpacegroupAnalyzer(structure, symprec=symprec)
        spg_symbol = unicodeify_spacegroup(sga.get_space_group_symbol())
        spg_number = sga.get_space_group_number()
        click.echo("  - Spacegroup: {} ({})".format(spg_symbol, spg_number))

        deformations = list(symmetry_reduce(deformations, structure, symprec=symprec))
        click.echo("  - # Inequivalent deformations: {}".format(len(deformations)))

    click.echo("\nDeformations:")
    click.echo("  - " + "\n  - ".join(get_formatted_tensors(deformations)))

    deformed_structures = get_deformed_structures(structure, deformations)

    write_deformed_poscars(deformed_structures, directory=kwargs["directory"])
    click.echo("\nDeformed structures have been created")
Exemple #41
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]
Exemple #42
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_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.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)
        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, '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)
    def analyze(self):

        from aiida.orm.data.parameter import ParameterData
        import numpy as np

        x_material = self.get_parameter("x_material")
        a_sweep = self.get_attribute("a_sweep")

        aiidalogger.info("Retrieving a_sweep as {0}".format(a_sweep))

        # Get calculations
        start_calcs = self.get_step_calculations(self.stress_tensor)  # .get_calculations()

        # Calculate results
        #-----------------------------------------
        alat_steps = params['alat_steps']

        s_calcs = np.linspace(-0.002, 0.002, alat_steps).tolist()

        e_calcs = [c.res.energy for c in start_calcs]
        v_calcs = [c.res.volume for c in start_calcs]

        e_calcs = zip(*sorted(zip(a_sweep, e_calcs)))[1]
        v_calcs = zip(*sorted(zip(a_sweep, v_calcs)))[1]

        s_calcs = zip(*sorted(zip(a_sweep, s_calcs)))[1]

        #  Add to report
        #-----------------------------------------
        for i in range(len(a_sweep)):
            self.append_to_report(x_material + "Ti03 simulated with a=" + str(a_sweep[i]) + ", s=" + str(s_calcs[i]) + ", e=" + str(e_calcs[i]))

        s_pymatgen = s.get_pymatgen()

        import pymatgen as mg
        from pymatgen.symmetry.analyzer import SpacegroupAnalyzer

        finder = SpacegroupAnalyzer(s_pymatgen)

        SGN = finder.get_space_group_number()

#%!%!%--- Classify the Space-Group Number ---%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!
        if (1 <= SGN and SGN <= 2):      # Triclinic
            LC = 'N'
            SCs= 6
        
        elif(3 <= SGN and SGN <= 15):    # Monoclinic
            LC = 'M'
            SCs= 4
        
        elif(16 <= SGN and SGN <= 74):   # Orthorhombic
            LC = 'O'
            SCs=  3
        
        elif(75 <= SGN and SGN <= 88):   # Tetragonal II
            LC = 'TII'
            SCs=  2
          
        elif(89 <= SGN and SGN <= 142):  # Tetragonal I
            LC = 'TI'
            SCs=  2
            
        elif(143 <= SGN and SGN <= 148): # Rhombohedral II 
            LC = 'RII'
            SCs=  2
            
        elif(149 <= SGN and SGN <= 167): # Rhombohedral I
            LC = 'RI'
            SCs=  2
            
        elif(168 <= SGN and SGN <= 176): # Hexagonal II
            LC = 'HII'
            SCs=  2
            
        elif(177 <= SGN and SGN <= 194): # Hexagonal I
            LC = 'HI'
            SCs=  2
            
        elif(195 <= SGN and SGN <= 206): # Cubic II
            LC = 'CII'
            SCs=  1
            
        elif(207 <= SGN and SGN <= 230): # Cubic I
            LC = 'CI'
            SCs=  1
            
        else: sys.exit('\n ... Oops ERROR: WRONG Space-Group Number !?!?!?\n')


#%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%#
#%!%!% ------------ Calculating the first derivative and Cross-Validation Error ------------ %!%!%#
#%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%#

        A1 = []
        
        mdri   = 0.002
        ordri  = 1
        
        strain = []
        energy = []

        strain = copy.copy(s_calcs)
        energy = copy.copy(e_calcs)
        
        coeffs = np.polyfit(strain, energy, ordri)
        A1.append(coeffs[ordri-1])
        
        A1 = np.array(A1)
        if (len(A1) != SCs):
            sys.exit('\n ... Oops ERROR: The number of data is NOT equal to ' + \
            str(SCs)+'\n')
        
        S = zeros((3,3))
        
#%!%!%--- Cubic structures ---%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%
        if (LC == 'CI' or \
            LC == 'CII'):
            S[0,0] = A1[0]/3.
            S[1,1] = S[0,0]
            S[2,2] = S[0,0]
#--------------------------------------------------------------------------------------------------

#%!%!%--- Hexagonal, Rhombohedral, and Tetragonal structures ---%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%
        if (LC == 'HI' or \
            LC == 'HII'or \
            LC == 'RI' or \
            LC == 'RII'or \
            LC == 'TI' or \
            LC == 'TII'):
            S[0,0] = (A1[0] - 1.*A1[1])/3.
            S[1,1] = S[0,0]
            S[2,2] = (A1[0] + 2.*A1[1])/3.
#--------------------------------------------------------------------------------------------------

#%!%!%--- Orthorhombic structures ---%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!
        if (LC == 'O'):
            S[0,0] = (A1[0] - 2.*A1[1] - 2.*A1[2])/3. 
            S[1,1] = (A1[0] + 2.*A1[1])/3.
            S[2,2] = (A1[0] + 2.*A1[2])/3.
#--------------------------------------------------------------------------------------------------

#%!%!%--- Monoclinic structures ---%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!
        if (LC == 'M'):
            S[0,0] = (A1[0] - 2.*A1[1] - 2.*A1[2])/3. 
            S[1,1] = (A1[0] + 2.*A1[1])/3.
            S[2,2] = (A1[0] + 2.*A1[2])/3.
        
            if (unique_axis == 'a'): S[1,2] = A1[3]/2.
            if (unique_axis == 'b'): S[0,2] = A1[3]/2.
            if (unique_axis == 'c'): S[0,1] = A1[3]/2.
#--------------------------------------------------------------------------------------------------

#%!%!%--- Triclinic structures ---%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%
        if (LC == 'N'):
            S[0,0] = (A1[0] + 2.* A1[2])/3.,
            S[1,1] = (A1[0] + 2.* A1[1])/3.,
            S[2,2] = (A1[0] - 2.*(A1[1] + A1[2]))/3.,
            S[1,2] = A1[3]/2.,
            S[0,2] = A1[4]/2.,
            S[0,1] = A1[5]/2.
#--------------------------------------------------------------------------------------------------

#%!%!%--- Calculating the Pressure ---%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%

        for i in range(2):
            for j in range(i+1, 3):
                S[j,i] = S[i,j] 

        eV_over_ang3_toGPa = 160.21766208
        v0i = int((alat_steps + 1) / 2)
        V0 = v_calcs [v0i]
        S = S / V0 * eV_over_ang3_toGPa
        P = (S[0,0]+S[1,1]+S[2,2])/-3.*eV_over_ang3_toGPa
#--------------------------------------------------------------------------------------------------

        self.append_to_report(x_material + "Ti03 simulated with a=" + str(a_sweep[v0i]) + ", e=" + str(e_calcs[v0i]))

        self.append_to_report("stress tensor matrix = " + str(S[0,0]) + str(S[0,1]) + str(S[0,2]))
        self.append_to_report("stress tensor matrix = " + str(S[1,0]) + str(S[1,1]) + str(S[1,2]))
        self.append_to_report("stress tensor matrix = " + str(S[2,0]) + str(S[2,1]) + str(S[2,2]))

        self.append_to_report("external pressure in GPa = " + str(P) )

        self.next(self.exit)
Exemple #44
0
    def __init__(self, struct, symprec=None):
        format_str = "{:.8f}"

        block = OrderedDict()
        loops = []
        spacegroup = ("P 1", 1)
        if symprec is not None:
            sf = SpacegroupAnalyzer(struct, symprec)
            spacegroup = (sf.get_space_group_symbol(),
                          sf.get_space_group_number())
            # Needs the refined struture when using symprec. This converts
            # primitive to conventional structures, the standard for CIF.
            struct = sf.get_refined_structure()

        latt = struct.lattice
        comp = struct.composition
        no_oxi_comp = comp.element_composition
        block["_symmetry_space_group_name_H-M"] = spacegroup[0]
        for cell_attr in ['a', 'b', 'c']:
            block["_cell_length_" + cell_attr] = format_str.format(
                getattr(latt, cell_attr))
        for cell_attr in ['alpha', 'beta', 'gamma']:
            block["_cell_angle_" + cell_attr] = format_str.format(
                getattr(latt, cell_attr))
        block["_symmetry_Int_Tables_number"] = spacegroup[1]
        block["_chemical_formula_structural"] = no_oxi_comp.reduced_formula
        block["_chemical_formula_sum"] = no_oxi_comp.formula
        block["_cell_volume"] = latt.volume.__str__()

        reduced_comp, fu = no_oxi_comp.get_reduced_composition_and_factor()
        block["_cell_formula_units_Z"] = str(int(fu))

        if symprec is None:
            block["_symmetry_equiv_pos_site_id"] = ["1"]
            block["_symmetry_equiv_pos_as_xyz"] = ["x, y, z"]
        else:
            sf = SpacegroupAnalyzer(struct, symprec)

            def round_symm_trans(i):

                for t in TRANSLATIONS.values():
                    if abs(i - t) < symprec:
                        return t
                if abs(i - round(i)) < symprec:
                    return 0
                raise ValueError("Invalid translation!")

            symmops = []
            for op in sf.get_symmetry_operations():
                v = op.translation_vector
                v = [round_symm_trans(i) for i in v]
                symmops.append(SymmOp.from_rotation_and_translation(
                    op.rotation_matrix, v))

            ops = [op.as_xyz_string() for op in symmops]
            block["_symmetry_equiv_pos_site_id"] = \
                ["%d" % i for i in range(1, len(ops) + 1)]
            block["_symmetry_equiv_pos_as_xyz"] = ops

        loops.append(["_symmetry_equiv_pos_site_id",
                      "_symmetry_equiv_pos_as_xyz"])

        contains_oxidation = True
        try:
            symbol_to_oxinum = OrderedDict([
                (el.__str__(), float(el.oxi_state))
                for el in sorted(comp.elements)])
        except AttributeError:
            symbol_to_oxinum = OrderedDict([(el.symbol, 0) for el in
                                            sorted(comp.elements)])
            contains_oxidation = False
        if contains_oxidation:
            block["_atom_type_symbol"] = symbol_to_oxinum.keys()
            block["_atom_type_oxidation_number"] = symbol_to_oxinum.values()
            loops.append(["_atom_type_symbol", "_atom_type_oxidation_number"])

        atom_site_type_symbol = []
        atom_site_symmetry_multiplicity = []
        atom_site_fract_x = []
        atom_site_fract_y = []
        atom_site_fract_z = []
        atom_site_label = []
        atom_site_occupancy = []
        count = 1
        if symprec is None:
            for site in struct:
                for sp, occu in site.species_and_occu.items():
                    atom_site_type_symbol.append(sp.__str__())
                    atom_site_symmetry_multiplicity.append("1")
                    atom_site_fract_x.append("{0:f}".format(site.a))
                    atom_site_fract_y.append("{0:f}".format(site.b))
                    atom_site_fract_z.append("{0:f}".format(site.c))
                    atom_site_label.append("{}{}".format(sp.symbol, count))
                    atom_site_occupancy.append(occu.__str__())
                    count += 1
        else:
            # The following just presents a deterministic ordering.
            unique_sites = [
                (sorted(sites, key=lambda s: tuple([abs(x) for x in
                                                   s.frac_coords]))[0],
                 len(sites))
                for sites in sf.get_symmetrized_structure().equivalent_sites
            ]
            for site, mult in sorted(
                    unique_sites,
                    key=lambda t: (t[0].species_and_occu.average_electroneg,
                                   -t[1], t[0].a, t[0].b, t[0].c)):
                for sp, occu in site.species_and_occu.items():
                    atom_site_type_symbol.append(sp.__str__())
                    atom_site_symmetry_multiplicity.append("%d" % mult)
                    atom_site_fract_x.append("{0:f}".format(site.a))
                    atom_site_fract_y.append("{0:f}".format(site.b))
                    atom_site_fract_z.append("{0:f}".format(site.c))
                    atom_site_label.append("{}{}".format(sp.symbol, count))
                    atom_site_occupancy.append(occu.__str__())
                    count += 1

        block["_atom_site_type_symbol"] = atom_site_type_symbol
        block["_atom_site_label"] = atom_site_label
        block["_atom_site_symmetry_multiplicity"] = \
            atom_site_symmetry_multiplicity
        block["_atom_site_fract_x"] = atom_site_fract_x
        block["_atom_site_fract_y"] = atom_site_fract_y
        block["_atom_site_fract_z"] = atom_site_fract_z
        block["_atom_site_occupancy"] = atom_site_occupancy
        loops.append(["_atom_site_type_symbol",
                      "_atom_site_label",
                      "_atom_site_symmetry_multiplicity",
                      "_atom_site_fract_x",
                      "_atom_site_fract_y",
                      "_atom_site_fract_z",
                      "_atom_site_occupancy"])
        d = OrderedDict()
        d[comp.reduced_formula] = CifBlock(block, loops, comp.reduced_formula)
        self._cf = CifFile(d)
Exemple #45
0
 def get_energy(self, structure):
     f = SpacegroupAnalyzer(structure, symprec=self.symprec,
                        angle_tolerance=self.angle_tolerance)
     return -f.get_space_group_number()
Exemple #46
0
 def get_sg(s):
     finder = SpacegroupAnalyzer(s, symprec=self.symprec)
     return finder.get_space_group_number()
Exemple #47
0
 def get_sg_info(ss):
     finder = SpacegroupAnalyzer(Structure.from_sites(ss),
                                 self.symm_prec)
     return finder.get_space_group_number()
Exemple #48
0
    def _gen_input_file(self):
        """
        Generate the necessary struct_enum.in file for enumlib. See enumlib
        documentation for details.
        """
        coord_format = "{:.6f} {:.6f} {:.6f}"
        # Using symmetry finder, get the symmetrically distinct sites.
        fitter = SpacegroupAnalyzer(self.structure, self.symm_prec)
        symmetrized_structure = fitter.get_symmetrized_structure()
        logger.debug("Spacegroup {} ({}) with {} distinct sites".format(
            fitter.get_space_group_symbol(),
            fitter.get_space_group_number(),
            len(symmetrized_structure.equivalent_sites))
        )

        """
        Enumlib doesn"t work when the number of species get too large. To
        simplify matters, we generate the input file only with disordered sites
        and exclude the ordered sites from the enumeration. The fact that
        different disordered sites with the exact same species may belong to
        different equivalent sites is dealt with by having determined the
        spacegroup earlier and labelling the species differently.
        """

        # index_species and index_amounts store mappings between the indices
        # used in the enum input file, and the actual species and amounts.
        index_species = []
        index_amounts = []

        # Stores the ordered sites, which are not enumerated.
        ordered_sites = []
        disordered_sites = []
        coord_str = []
        for sites in symmetrized_structure.equivalent_sites:
            if sites[0].is_ordered:
                ordered_sites.append(sites)
            else:
                sp_label = []
                species = {k: v for k, v in sites[0].species_and_occu.items()}
                if sum(species.values()) < 1 - EnumlibAdaptor.amount_tol:
                    # Let us first make add a dummy element for every single
                    # site whose total occupancies don't sum to 1.
                    species[DummySpecie("X")] = 1 - sum(species.values())
                for sp in species.keys():
                    if sp not in index_species:
                        index_species.append(sp)
                        sp_label.append(len(index_species) - 1)
                        index_amounts.append(species[sp] * len(sites))
                    else:
                        ind = index_species.index(sp)
                        sp_label.append(ind)
                        index_amounts[ind] += species[sp] * len(sites)
                sp_label = "/".join(["{}".format(i) for i in sorted(sp_label)])
                for site in sites:
                    coord_str.append("{} {}".format(
                        coord_format.format(*site.coords),
                        sp_label))
                disordered_sites.append(sites)

        def get_sg_info(ss):
            finder = SpacegroupAnalyzer(Structure.from_sites(ss),
                                        self.symm_prec)
            return finder.get_space_group_number()

        curr_sites = list(itertools.chain.from_iterable(disordered_sites))
        min_sgnum = get_sg_info(curr_sites)
        logger.debug("Disordered sites has sgnum %d" % (
            min_sgnum))
        # It could be that some of the ordered sites has a lower symmetry than
        # the disordered sites.  So we consider the lowest symmetry sites as
        # disordered in our enumeration.
        self.ordered_sites = []
        to_add = []

        if self.check_ordered_symmetry:
            for sites in ordered_sites:
                temp_sites = list(curr_sites) + sites
                sgnum = get_sg_info(temp_sites)
                if sgnum < min_sgnum:
                    logger.debug("Adding {} to sites to be ordered. "
                                 "New sgnum {}"
                                 .format(sites, sgnum))
                    to_add = sites
                    min_sgnum = sgnum

        for sites in ordered_sites:
            if sites == to_add:
                index_species.append(sites[0].specie)
                index_amounts.append(len(sites))
                sp_label = len(index_species) - 1
                logger.debug("Lowest symmetry {} sites are included in enum."
                             .format(sites[0].specie))
                for site in sites:
                    coord_str.append("{} {}".format(
                        coord_format.format(*site.coords),
                        sp_label))
                disordered_sites.append(sites)
            else:
                self.ordered_sites.extend(sites)

        self.index_species = index_species

        lattice = self.structure.lattice

        output = [self.structure.formula, "bulk"]
        for vec in lattice.matrix:
            output.append(coord_format.format(*vec))
        output.append("{}".format(len(index_species)))
        output.append("{}".format(len(coord_str)))
        output.extend(coord_str)

        output.append("{} {}".format(self.min_cell_size, self.max_cell_size))
        output.append(str(self.enum_precision_parameter))
        output.append("partial")

        ndisordered = sum([len(s) for s in disordered_sites])

        base = int(ndisordered*reduce(lcm,
                                      [f.limit_denominator(
                                          ndisordered *
                                          self.max_cell_size).denominator
                                       for f in map(fractions.Fraction,
                                                    index_amounts)]))
        # base = ndisordered #10 ** int(math.ceil(math.log10(ndisordered)))
        # To get a reasonable number of structures, we fix concentrations to the
        # range expected in the original structure.
        total_amounts = sum(index_amounts)
        for amt in index_amounts:
            conc = amt / total_amounts
            if abs(conc * base - round(conc * base)) < 1e-5:
                output.append("{} {} {}".format(int(round(conc * base)),
                                                int(round(conc * base)),
                                                base))
            else:
                min_conc = int(math.floor(conc * base))
                output.append("{} {} {}".format(min_conc - 1, min_conc + 1,
                                                base))
        output.append("")
        logger.debug("Generated input file:\n{}".format("\n".join(output)))
        with open("struct_enum.in", "w") as f:
            f.write("\n".join(output))
Exemple #49
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
Exemple #50
0
    def _gen_input_file(self):
        """
        Generate the necessary struct_enum.in file for enumlib. See enumlib
        documentation for details.
        """
        coord_format = "{:.6f} {:.6f} {:.6f}"
        # Using symmetry finder, get the symmetrically distinct sites.
        fitter = SpacegroupAnalyzer(self.structure, self.symm_prec)
        symmetrized_structure = fitter.get_symmetrized_structure()
        logger.debug("Spacegroup {} ({}) with {} distinct sites".format(
            fitter.get_space_group_symbol(),
            fitter.get_space_group_number(),
            len(symmetrized_structure.equivalent_sites))
        )

        """
        Enumlib doesn"t work when the number of species get too large. To
        simplify matters, we generate the input file only with disordered sites
        and exclude the ordered sites from the enumeration. The fact that
        different disordered sites with the exact same species may belong to
        different equivalent sites is dealt with by having determined the
        spacegroup earlier and labelling the species differently.
        """

        # index_species and index_amounts store mappings between the indices
        # used in the enum input file, and the actual species and amounts.
        index_species = []
        index_amounts = []

        # Stores the ordered sites, which are not enumerated.
        ordered_sites = []
        disordered_sites = []
        coord_str = []
        for sites in symmetrized_structure.equivalent_sites:
            if sites[0].is_ordered:
                ordered_sites.append(sites)
            else:
                sp_label = []
                species = {k: v for k, v in sites[0].species.items()}
                if sum(species.values()) < 1 - EnumlibAdaptor.amount_tol:
                    # Let us first make add a dummy element for every single
                    # site whose total occupancies don't sum to 1.
                    species[DummySpecie("X")] = 1 - sum(species.values())
                for sp in species.keys():
                    if sp not in index_species:
                        index_species.append(sp)
                        sp_label.append(len(index_species) - 1)
                        index_amounts.append(species[sp] * len(sites))
                    else:
                        ind = index_species.index(sp)
                        sp_label.append(ind)
                        index_amounts[ind] += species[sp] * len(sites)
                sp_label = "/".join(["{}".format(i) for i in sorted(sp_label)])
                for site in sites:
                    coord_str.append("{} {}".format(
                        coord_format.format(*site.coords),
                        sp_label))
                disordered_sites.append(sites)

        def get_sg_info(ss):
            finder = SpacegroupAnalyzer(Structure.from_sites(ss),
                                        self.symm_prec)
            return finder.get_space_group_number()

        target_sgnum = get_sg_info(symmetrized_structure.sites)
        curr_sites = list(itertools.chain.from_iterable(disordered_sites))
        sgnum = get_sg_info(curr_sites)
        ordered_sites = sorted(ordered_sites, key=lambda sites: len(sites))
        logger.debug("Disordered sites has sg # %d" % (sgnum))
        self.ordered_sites = []

        # progressively add ordered sites to our disordered sites
        # until we match the symmetry of our input structure
        if self.check_ordered_symmetry:
            while sgnum != target_sgnum and len(ordered_sites) > 0:
                sites = ordered_sites.pop(0)
                temp_sites = list(curr_sites) + sites
                new_sgnum = get_sg_info(temp_sites)
                if sgnum != new_sgnum:
                    logger.debug("Adding %s in enum. New sg # %d"
                                 % (sites[0].specie, new_sgnum))
                    index_species.append(sites[0].specie)
                    index_amounts.append(len(sites))
                    sp_label = len(index_species) - 1
                    for site in sites:
                        coord_str.append("{} {}".format(
                            coord_format.format(*site.coords),
                            sp_label))
                    disordered_sites.append(sites)
                    curr_sites = temp_sites
                    sgnum = new_sgnum
                else:
                    self.ordered_sites.extend(sites)

        for sites in ordered_sites:
            self.ordered_sites.extend(sites)

        self.index_species = index_species

        lattice = self.structure.lattice

        output = [self.structure.formula, "bulk"]
        for vec in lattice.matrix:
            output.append(coord_format.format(*vec))
        output.append("%d" % len(index_species))
        output.append("%d" % len(coord_str))
        output.extend(coord_str)

        output.append("{} {}".format(self.min_cell_size, self.max_cell_size))
        output.append(str(self.enum_precision_parameter))
        output.append("partial")

        ndisordered = sum([len(s) for s in disordered_sites])
        base = int(ndisordered*lcm(*[f.limit_denominator(ndisordered *
                                          self.max_cell_size).denominator
                                       for f in map(fractions.Fraction,
                                                    index_amounts)]))

        # This multiplicative factor of 10 is to prevent having too small bases
        # which can lead to rounding issues in the next step.
        # An old bug was that a base was set to 8, with a conc of 0.4:0.6. That
        # resulted in a range that overlaps and a conc of 0.5 satisfying this
        # enumeration. See Cu7Te5.cif test file.
        base *= 10

        # base = ndisordered #10 ** int(math.ceil(math.log10(ndisordered)))
        # To get a reasonable number of structures, we fix concentrations to the
        # range expected in the original structure.
        total_amounts = sum(index_amounts)
        for amt in index_amounts:
            conc = amt / total_amounts

            if abs(conc * base - round(conc * base)) < 1e-5:
                output.append("{} {} {}".format(int(round(conc * base)),
                                                int(round(conc * base)),
                                                base))
            else:
                min_conc = int(math.floor(conc * base))
                output.append("{} {} {}".format(min_conc - 1, min_conc + 1,
                                                base))
        output.append("")
        logger.debug("Generated input file:\n{}".format("\n".join(output)))
        with open("struct_enum.in", "w") as f:
            f.write("\n".join(output))