Ejemplo n.º 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 = SymmetryFinder(spstruc, SPACEGROUP_TOLERANCE)
            sf.get_spacegroup()
            sgnum = sf.get_spacegroup_number() if sf.get_spacegroup_number() \
                else -1
            sgsym = sf.get_spacegroup_symbol() if sf.get_spacegroup_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 = unicode(sf.get_point_group(), errors="ignore")

            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!")
Ejemplo n.º 2
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 = SymmetryFinder(spstruc, SPACEGROUP_TOLERANCE)
            sf.get_spacegroup()
            sgnum = sf.get_spacegroup_number() if sf.get_spacegroup_number() \
                else -1
            sgsym = sf.get_spacegroup_symbol() if sf.get_spacegroup_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 = unicode(sf.get_point_group(), errors="ignore")

            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!")
Ejemplo n.º 3
0
def _generate_entry(structure, params, name, energy, pressure):
    comp = structure.composition
    entry = {"structure": structure.to_dict, "name": name, "energy": energy, "energy_per_site": energy / comp.num_atoms,
             "pressure": pressure, "potential": {"name": "lennard_jones", "params": params.to_dict}}

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

    # Figure out the symmetry group
    sg = SymmetryFinder(structure, normalised_symmetry_precision(structure), -1)
    entry["spacegroup"] = {"symbol": unicode(sg.get_spacegroup_symbol(), errors="ignore"),
                           "number": sg.get_spacegroup_number(),
                           "point_group": unicode(sg.get_point_group(), errors="ignore"),
                           "source": "spglib",
                           "crystal_system": sg.get_crystal_system(),
                           "hall": sg.get_hall()}

    return entry
Ejemplo n.º 4
0
    def process_res(cls, resfile):
        fullpath = os.path.abspath(resfile)
        res = Res.from_file(resfile)
        d = res.to_dict
        d["file_name"] = fullpath

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

        # Figure out the symmetry group
        sg = SymmetryFinder(s, util.normalised_symmetry_precision(s), -1)
        d["spacegroup"] = {"symbol": unicode(sg.get_spacegroup_symbol(),
                                             errors="ignore"),
                           "number": sg.get_spacegroup_number(),
                           "point_group": unicode(sg.get_point_group(),
                                                  errors="ignore"),
                           "source": "spglib",
                           "crystal_system": sg.get_crystal_system(),
                           "hall": sg.get_hall()}

        return d
    def complete_ordering(self, structure, num_remove_dict):
        self.logger.debug("Performing complete ordering...")
        all_structures = []
        from pymatgen.symmetry.finder import SymmetryFinder
        symprec = 0.2
        s = SymmetryFinder(structure, symprec=symprec)
        self.logger.debug("Symmetry of structure is determined to be {}."
                          .format(s.get_spacegroup_symbol()))
        sg = s.get_spacegroup()
        tested_sites = []
        starttime = time.time()
        self.logger.debug("Performing initial ewald sum...")
        ewaldsum = EwaldSummation(structure)
        self.logger.debug("Ewald sum took {} seconds."
                          .format(time.time() - starttime))
        starttime = time.time()

        allcombis = []
        for ind, num in num_remove_dict.items():
            allcombis.append(itertools.combinations(ind, num))

        count = 0
        for allindices in itertools.product(*allcombis):
            sites_to_remove = []
            indices_list = []
            for indices in allindices:
                sites_to_remove.extend([structure[i] for i in indices])
                indices_list.extend(indices)

            mod = StructureEditor(structure)
            mod.delete_sites(indices_list)
            s_new = mod.modified_structure
            energy = ewaldsum.compute_partial_energy(indices_list)
            already_tested = False
            for i, tsites in enumerate(tested_sites):
                tenergy = all_structures[i]["energy"]
                if abs((energy - tenergy) / len(s_new)) < 1e-5 and \
                        sg.are_symmetrically_equivalent(sites_to_remove, tsites,
                                                        symm_prec=symprec):
                    already_tested = True

            if not already_tested:
                tested_sites.append(sites_to_remove)
                all_structures.append({"structure": s_new, "energy": energy})

            count += 1
            if count % 10 == 0:
                timenow = time.time()
                self.logger.debug("{} structures, {:.2f} seconds."
                                  .format(count, timenow - starttime))
                self.logger.debug("Average time per combi = {} seconds"
                                  .format((timenow - starttime) / count))
                self.logger.debug("{} symmetrically distinct structures found."
                                  .format(len(all_structures)))

        self.logger.debug("Total symmetrically distinct structures found = {}"
                          .format(len(all_structures)))
        all_structures = sorted(all_structures, key=lambda s: s["energy"])
        return all_structures
Ejemplo n.º 6
0
    def add_snl(self, snl, force_new=False, snlgroup_guess=None):
        snl_id = self._get_next_snl_id()
        sf = SymmetryFinder(snl.structure, SPACEGROUP_TOLERANCE)
        sf.get_spacegroup()
        sgnum = sf.get_spacegroup_number() if sf.get_spacegroup_number() \
            else -1
        sgsym = sf.get_spacegroup_symbol() if sf.get_spacegroup_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 = unicode(sf.get_point_group(), errors="ignore")

        mpsnl = MPStructureNL.from_snl(snl, snl_id, sgnum, sgsym, sghall,
                                       sgxtal, sglatt, sgpoint)
        snlgroup, add_new = self.add_mpsnl(mpsnl, force_new, snlgroup_guess)
        return mpsnl, snlgroup.snlgroup_id
Ejemplo n.º 7
0
 def add_snl(self, snl):
     snl_id = self._get_next_snl_id()
     sf = SymmetryFinder(snl.structure, SPACEGROUP_TOLERANCE)
     sf.get_spacegroup()
     mpsnl = MPStructureNL.from_snl(snl, snl_id, sf.get_spacegroup_number(),
                                    sf.get_spacegroup_symbol(), sf.get_hall(),
                                    sf.get_crystal_system(), sf.get_lattice_type())
     snlgroup, add_new = self.add_mpsnl(mpsnl)
     return mpsnl, snlgroup.snlgroup_id
Ejemplo n.º 8
0
    def add_snl(self, snl, force_new=False, snlgroup_guess=None):
        snl_id = self._get_next_snl_id()
        sf = SymmetryFinder(snl.structure, SPACEGROUP_TOLERANCE)
        sf.get_spacegroup()
        sgnum = sf.get_spacegroup_number() if sf.get_spacegroup_number() \
            else -1
        sgsym = sf.get_spacegroup_symbol() if sf.get_spacegroup_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 = unicode(sf.get_point_group(), errors="ignore")

        mpsnl = MPStructureNL.from_snl(snl, snl_id, sgnum, sgsym, sghall,
                                       sgxtal, sglatt, sgpoint)
        snlgroup, add_new = self.add_mpsnl(mpsnl, force_new, snlgroup_guess)
        return mpsnl, snlgroup.snlgroup_id
Ejemplo n.º 9
0
 def _make_struc_file(self, file_name):
     sym = SymmetryFinder(self._bs._structure, symprec=0.01)
     with open(file_name, "w") as f:
         f.write(self._bs._structure.composition.formula + " " + str(sym.get_spacegroup_symbol()) + "\n")
         for i in range(3):
             line = ""
             for j in range(3):
                 line += "%12.5f" % (Length(self._bs._structure.lattice.matrix[i][j], "ang").to("bohr"))
             f.write(line + "\n")
         ops = sym.get_symmetry_dataset()["rotations"]
         f.write(str(len(ops)) + "\n")
         for c in ops:
             f.write("\n".join([" ".join([str(int(i)) for i in row]) for row in c]))
             f.write("\n")
Ejemplo n.º 10
0
def get_symetry(lines, output):
    latt_tmp = [[float(x) for x in y.split()] for y in lines[0:3]]
    trans = [[float(x) for x in y.split()] for y in lines[3:6]]
    sites = [[float(x) for x in y.split()[0:3]] for y in lines[6:]]
    elements = [x.split()[3] for x in lines[6:]]
    latt = np.dot(np.array(trans),np.array(latt_tmp))
    latt_obj = mg.Lattice(latt)
    structure = mg.Structure(latt, elements, sites)
    finder = SymmetryFinder(structure)
    out = finder.get_spacegroup_symbol() + "\n"
    #structure = finder.find_primitive()
    #structure = finder.get_primitive_standard_structure()
    poscar = Poscar(structure)
    #cif = CifWriter(structure)
    out += poscar.__str__()
    #print(cif)
    return out
Ejemplo n.º 11
0
 def _make_struc_file(self, file_name):
     sym = SymmetryFinder(self._bs._structure, symprec=0.01)
     with open(file_name, 'w') as f:
         f.write(self._bs._structure.composition.formula+" " +
                 str(sym.get_spacegroup_symbol())+"\n")
         for i in range(3):
             line = ''
             for j in range(3):
                 line += "%12.5f" % (
                     Length(self._bs._structure.lattice.matrix[i][j],
                            "ang").to("bohr"))
             f.write(line+'\n')
         ops = sym.get_symmetry_dataset()['rotations']
         f.write(str(len(ops))+"\n")
         for c in ops:
             f.write('\n'.join([' '.join([str(int(i)) for i in row])
                                for row in c]))
             f.write('\n')
Ejemplo n.º 12
0
    def get_structure_hash(self, structure):
        """
        Hash for structure.

        Args:
            structure: A structure

        Returns:
            Reduced formula for the structure is used as a hash for the
            SpeciesComparator.
        """
        if not hasattr(structure, 'spacegroup'):
            sg = SymmetryFinder(structure, splpy.util.normalised_symmetry_precision(structure), -1)
            structure.spacegroup = {"symbol": unicode(sg.get_spacegroup_symbol(), errors="ignore"),
                                    "number": sg.get_spacegroup_number(),
                                    "point_group": unicode(sg.get_point_group(), errors="ignore"),
                                    "crystal_system": sg.get_crystal_system(),
                                    "hall": sg.get_hall()}

        return "{} {}".format(structure.spacegroup['number'], self._parent.get_structure_hash(structure))
Ejemplo n.º 13
0
def produce(irreps):
    os.makedirs('irrep')
    for i, irrep in enumerate(irreps):
        poscar = Poscar(irrep)
        symbols = poscar.site_symbols
        natoms = poscar.natoms
        name_dict = {'Al': 'A', 'Ti': 'B'}
        tmp = ["{0}{1}".format(name_dict[x], y)
               for x, y in zip(symbols, natoms)]
        finder = SymmetryFinder(irrep)
        spg_num = finder.get_spacegroup_number()
        spg = "_".join(finder.get_spacegroup_symbol().split('/'))
        dirname = "No." + "{0:03d}".format(i) + "_" + spg + "_" + "".join(tmp)
        poscar.comment += "    (#" + str(spg_num) + ": " + spg + ")"

        standard = finder.get_conventional_standard_structure()
        stand_pos = Poscar(standard)
        stand_pos.comment += "    (#" + str(spg_num) + ": " + spg + ")"

        os.makedirs(os.path.join('irrep', dirname))
        poscar.write_file(os.path.join('irrep', dirname, 'POSCAR.prim'))
        stand_pos.write_file(os.path.join('irrep', dirname, 'POSCAR.std'))
Ejemplo n.º 14
0
    def _gen_input_file(self, working_dir):
        """
        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 = SymmetryFinder(self.structure, self.symm_prec)
        symmetrized_structure = fitter.get_symmetrized_structure()
        logger.debug("Spacegroup {} ({}) with {} distinct sites".format(
            fitter.get_spacegroup_symbol(),
            fitter.get_spacegroup_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 = []

        #Let"s group and sort the sites by symmetry.
        site_symmetries = []
        for sites in symmetrized_structure.equivalent_sites:
            finder = SymmetryFinder(Structure.from_sites(sites),
                                    self.symm_prec)
            sgnum = finder.get_spacegroup_number()
            site_symmetries.append((sites, sgnum))

        site_symmetries = sorted(site_symmetries, key=lambda s: s[1])

        #Stores the ordered sites, which are not enumerated.
        min_sg_num = site_symmetries[0][1]
        ordered_sites = []
        disordered_sites = []
        coord_str = []
        min_disordered_sg = 300
        for (sites, sgnum) in site_symmetries:
            if sites[0].is_ordered:
                ordered_sites.append(sites)
            else:
                min_disordered_sg = min(min_disordered_sg, sgnum)
                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)

        #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.
        if min_disordered_sg > min_sg_num:
            logger.debug("Ordered sites have lower symmetry than disordered.")
            sites = ordered_sites.pop(0)
            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)

        self.ordered_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("{}".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")
        #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 * 100 - round(conc * 100)) < 1e-5:
                output.append("{} {} {}".format(int(round(conc * 100)),
                                                int(round(conc * 100)), 100))
            else:
                min_conc = int(math.floor(conc * 100))
                output.append("{} {} {}".format(min_conc - 1, min_conc + 1,
                                                100))
        output.append("")
        logger.debug("Generated input file:\n{}".format("\n".join(output)))
        with open(os.path.join(working_dir, "struct_enum.in"), "w") as f:
            f.write("\n".join(output))
Ejemplo n.º 15
0
    def generate_doc(cls, dir_name, vasprun_files, parse_dos,
                     additional_fields):
        """Process aflow style and NEB runs."""
        print "TTM DEBUG: In generate_doc for NEB task drone."
        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 additional_fields.items()} \
                if additional_fields else {}
            d["dir_name"] = fullpath
            print "TTM DEBUG: fullpath: ", fullpath
            d["schema_version"] = NEBToDbTaskDrone.__version__
            d["calculations"] = [
                cls.process_vasprun(dir_name, taskname, filename, parse_dos)
                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"]))
            d["input"] = {"crystal": d1["input"]["crystal"]}
            vals = sorted(d2["reduced_cell_formula"].values())
            d["anonymous_formula"] = {string.ascii_uppercase[i]: float(vals[i])
                                      for i in xrange(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"
            d["pseudo_potential"] = {"functional": "pbe", "pot_type": "paw",
                                     "labels": d2["input"]["potcar"]}

            if len(d["calculations"]) == 2 or \
                    vasprun_files.keys()[0] != "relax1":
                d["state"] = "successful" if d2["has_vasp_completed"] \
                    else "unsuccessful"
            else:
                d["state"] = "stopped"

            s = Structure.from_dict(d2["output"]["crystal"])
            if not s.is_valid():
                d["state"] = "errored_bad_structure"

            d["analysis"] = get_basic_analysis_and_error_checks(d)

            sg = SymmetryFinder(Structure.from_dict(d["output"]["crystal"]),
                                0.1)
            d["spacegroup"] = {"symbol": sg.get_spacegroup_symbol(),
                               "number": sg.get_spacegroup_number(),
                               "point_group": unicode(sg.get_point_group(),
                                                      errors="ignore"),
                               "source": "spglib",
                               "crystal_system": sg.get_crystal_system(),
                               "hall": sg.get_hall()}
            d["last_updated"] = datetime.datetime.today()

            # Process NEB runs. The energy and magnetic moments for each image are listed.
            # Some useful values are calculated.

            # Number of NEB images
            print "TTM DEBUG: At NEB processing stage."
            image_list = []
            for i in xrange(0,9):
                append = "0"+str(i)
                newpath = os.path.join(fullpath,append)
                if os.path.exists(newpath):
                    image_list.append(newpath)
            d["num_images"] = len(image_list)
            print "TTM DEBUG: Image list:", image_list
            # Image energies and magnetic moments for specific folders
            list_image_energies = []
            list_image_mags = []
            for i in xrange(0,len(image_list)):
                append = "0"+str(i)
                oszicar = os.path.join(fullpath,append,"OSZICAR")
                if not os.path.isfile(oszicar):
                    return None
                val_energy = util2.getEnergy(oszicar)
                val_mag = util2.getMag(oszicar)
                d["E_"+append]= val_energy
                d["mag_"+append]= val_mag
                list_image_energies.append(val_energy)
                list_image_mags.append(val_mag)
            print "TTM DEBUG: first occurrence list_image_mags", list_image_mags
            # List of image energies and magnetic moments in order 
            image_energies = ' '.join(map(str,list_image_energies))
            d["image_energies"] = image_energies

            # An simple way to visualize relative image energies and magnetic moments
            energy_contour = "-x-"
            if len(image_list)==0:
                return None
            for i in xrange(1,len(image_list)):
                if(list_image_energies[i]>list_image_energies[i-1]):
                    energy_contour += "/-x-"
                elif list_image_energies[i]<list_image_energies[i-1]:
                    energy_contour += "\\-x-"
                else:
                    energy_contour += "=-x-"
            d["energy_contour"] = energy_contour
            print "TTM DEBUG: energy contour:", energy_contour

            # Difference between the first and maximum energies and magnetic moments
            deltaE_firstmax = max(list_image_energies) - list_image_energies[0] 
            d["deltaE_firstmax"] = deltaE_firstmax
            # Difference between the last and maximum energies and magnetic moments
            deltaE_lastmax = max(list_image_energies) - list_image_energies[-1]
            d["deltaE_lastmax"] = deltaE_lastmax

            # Difference between the endpoint energies and magnetic moments
            deltaE_endpoints = list_image_energies[-1] - list_image_energies[0]
            d["deltaE_endpoints"] = deltaE_endpoints

            # Difference between the minimum and maximum energies and magnetic moments
            deltaE_maxmin = max(list_image_energies) - min(list_image_energies)
            d["deltaE_maxmin"] = deltaE_maxmin            
        
#INDENT THE NEXT LINES:
            if not (list_image_mags[0] == None): #if ISPIN not 2, no mag info
                image_mags = ' '.join(map(str,list_image_mags))
                d["image_mags"] = image_mags
                mag_contour = "-o-"
                if len(image_list)==0:
                    return None
                for i in xrange(1,len(image_list)):
                    if(list_image_mags[i]>list_image_mags[i-1]):
                        mag_contour += "/-o-"
                    elif list_image_mags[i]<list_image_mags[i-1]:
                        mag_contour += "\\-o-"
                    else:
                        mag_contour += "=-o-"
                d["mag_contour"] = mag_contour
                deltaM_firstmax = max(list_image_mags) - list_image_mags[0]
                d["deltaM_firstmax"] = deltaM_firstmax
                deltaM_lastmax = max(list_image_mags) - list_image_mags[-1]
                d["deltaM_lastmax"] = deltaM_lastmax
                deltaM_endpoints = list_image_mags[-1] - list_image_mags[0]
                d["deltaM_endpoints"] = deltaM_endpoints
                deltaM_maxmin = max(list_image_mags) - min(list_image_mags)
                d["deltaM_maxmin"] = deltaM_maxmin


            d["type"] = "NEB"

            return d

        except Exception as ex:
            logger.error("Error in " + os.path.abspath(dir_name) +
                         ".\nError msg: " + str(ex))
            return None
Ejemplo n.º 16
0
    def _gen_input_file(self, working_dir):
        """
        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 = SymmetryFinder(self.structure, self.symm_prec)
        symmetrized_structure = fitter.get_symmetrized_structure()
        logger.debug("Spacegroup {} ({}) with {} distinct sites".format(
            fitter.get_spacegroup_symbol(), fitter.get_spacegroup_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 = []

        #Let"s group and sort the sites by symmetry.
        site_symmetries = []
        for sites in symmetrized_structure.equivalent_sites:
            finder = SymmetryFinder(Structure.from_sites(sites),
                                    self.symm_prec)
            sgnum = finder.get_spacegroup_number()
            site_symmetries.append((sites, sgnum))

        site_symmetries = sorted(site_symmetries, key=lambda s: s[1])

        #Stores the ordered sites, which are not enumerated.
        min_sg_num = site_symmetries[0][1]
        ordered_sites = []
        disordered_sites = []
        coord_str = []
        min_disordered_sg = 300
        for (sites, sgnum) in site_symmetries:
            if sites[0].is_ordered:
                ordered_sites.append(sites)
            else:
                min_disordered_sg = min(min_disordered_sg, sgnum)
                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)

        #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.
        if min_disordered_sg > min_sg_num:
            logger.debug("Ordered sites have lower symmetry than disordered.")
            sites = ordered_sites.pop(0)
            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)

        self.ordered_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("{}".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")
        #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 * 100 - round(conc * 100)) < 1e-5:
                output.append("{} {} {}".format(int(round(conc * 100)),
                                                int(round(conc * 100)), 100))
            else:
                min_conc = int(math.floor(conc * 100))
                output.append("{} {} {}".format(min_conc - 1, min_conc + 1,
                                                100))
        output.append("")
        logger.debug("Generated input file:\n{}".format("\n".join(output)))
        with open(os.path.join(working_dir, "struct_enum.in"), "w") as f:
            f.write("\n".join(output))
Ejemplo n.º 17
0
i = 0
out_str = []
for lines, boo in zip(strs[:-1], judge):
    if boo:
        i += 1
        lines = lines.split('\n')
        latt_tmp = [[float(x) for x in y.split()] for y in lines[0:3]]
        trans = [[float(x) for x in y.split()] for y in lines[3:6]]
        sites = [[float(x) for x in y.split()[0:3]] for y in lines[6:]]
        elements = [x.split()[3] for x in lines[6:]]
        latt = np.dot(np.array(trans), np.array(latt_tmp))
        latt_obj = mg.Lattice(latt)
        structure = mg.Structure(latt, elements, sites)
        finder = SymmetryFinder(structure)
        print(i)
        print(finder.get_spacegroup_symbol())
        structure = finder.get_primitive_standard_structure()
        out_str.append(Poscar(structure).__str__())
        print((Poscar(structure)))

#final_str = list(set(out_str))
final_str = out_str
print(len(final_str))

i = 0
for structure in final_str:
    i += 1
    posc = structure.split('\n')
    site_line = [" ".join(x.split()[0:3]) for x in posc[8:]]
    posc[8:] = site_line
    os.makedirs('str{0}'.format(i))
Ejemplo n.º 18
0
class HighSymmKpath(object):
    """
    This class looks for path along high symmetry lines in
    the Brillouin Zone.
    It is based on Setyawan, W., & Curtarolo, S. (2010).
    High-throughput electronic band structure calculations:
    Challenges and tools. Computational Materials Science,
    49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010
    The symmetry is determined by spglib through the
    SymmetryFinder class
    """

    def __init__(self, structure, symprec=0.01, angle_tolerance=5):
        """
        Args:
            structure:
                Structure object
            symprec:
                Tolerance for symmetry finding
            angle_tolerance:
                Angle tolerance for symmetry finding.
        """
        self._structure = structure
        self._sym = SymmetryFinder(structure, symprec=symprec,
                                   angle_tolerance=angle_tolerance)
        self._prim = self._sym\
            .get_primitive_standard_structure()
        self._conv = self._sym.get_conventional_standard_structure()
        self._prim_rec = self._prim.lattice.reciprocal_lattice
        self._kpath = None

        lattice_type = self._sym.get_lattice_type() 
        spg_symbol = self._sym.get_spacegroup_symbol()

        if lattice_type == "cubic":
            if "P" in spg_symbol:
                self._kpath = self.cubic()
            elif "F" in spg_symbol:
                self._kpath = self.fcc()
            elif "I" in spg_symbol:
                self._kpath = self.bcc()
            else:
                warn("Unexpected value for spg_symbol: %s" % spg_symbol)

        elif lattice_type == "tetragonal":
            if "P" in spg_symbol:
                self._kpath = self.tet()
            elif "I" in spg_symbol:
                a = self._conv.lattice.abc[0]
                c = self._conv.lattice.abc[2]
                if c < a:
                    self._kpath = self.bctet1(c, a)
                else:
                    self._kpath = self.bctet2(c, a)
            else:
                warn("Unexpected value for spg_symbol: %s" % spg_symbol)

        elif lattice_type == "orthorhombic":
            a = self._conv.lattice.abc[0]
            b = self._conv.lattice.abc[1]
            c = self._conv.lattice.abc[2]

            if "P" in spg_symbol:
                self._kpath = self.orc()

            elif "F" in spg_symbol:
                if 1 / a ** 2 > 1 / b ** 2 + 1 / c ** 2:
                    self._kpath = self.orcf1(a, b, c)
                elif 1 / a ** 2 < 1 / b ** 2 + 1 / c ** 2:
                    self._kpath = self.orcf2(a, b, c)
                else:
                    self._kpath = self.orcf3(a, b, c)

            elif "I" in spg_symbol:
                self._kpath = self.orci(a, b, c)

            elif "C" in spg_symbol:
                self._kpath = self.orcc(a, b, c)
            else:
                warn("Unexpected value for spg_symbol: %s" % spg_symbol)

        elif lattice_type == "hexagonal":
            self._kpath = self.hex()

        elif lattice_type == "rhombohedral":
            alpha = self._prim.lattice.lengths_and_angles[1][0]
            if alpha < 90:
                self._kpath = self.rhl1(alpha * pi / 180)
            else:
                self._kpath = self.rhl2(alpha * pi / 180)

        elif lattice_type == "monoclinic":
            a, b, c = self._conv.lattice.abc
            alpha = self._conv.lattice.lengths_and_angles[1][0]

            if "P" in spg_symbol:
                self._kpath = self.mcl(b, c, alpha * pi / 180)

            elif "C" in spg_symbol:
                kgamma = self._prim_rec.lengths_and_angles[1][2]
                if kgamma > 90:
                    self._kpath = self.mclc1(a, b, c, alpha * pi / 180)
                if kgamma == 90:
                    self._kpath = self.mclc2(a, b, c, alpha * pi / 180)
                if kgamma < 90:
                    if b * cos(alpha * pi / 180) / c\
                            + b ** 2 * sin(alpha) ** 2 / a ** 2 < 1:
                        self._kpath = self.mclc3(a, b, c, alpha * pi / 180)
                    if b * cos(alpha * pi / 180) / c \
                            + b ** 2 * sin(alpha) ** 2 / a ** 2 == 1:
                        self._kpath = self.mclc4(a, b, c, alpha * pi / 180)
                    if b * cos(alpha * pi / 180) / c \
                            + b ** 2 * sin(alpha) ** 2 / a ** 2 > 1:
                        self._kpath = self.mclc5(a, b, c, alpha * pi / 180)
            else:
                warn("Unexpected value for spg_symbol: %s" % spg_symbol)

        elif lattice_type == "triclinic":
            kalpha = self._prim_rec.lengths_and_angles[1][0]
            kbeta = self._prim_rec.lengths_and_angles[1][1]
            kgamma = self._prim_rec.lengths_and_angles[1][2]
            if kalpha > 90 and kbeta > 90 and kgamma > 90:
                self._kpath = self.tria()
            if kalpha < 90 and kbeta < 90 and kgamma < 90:
                self._kpath = self.trib()
            if kalpha > 90 and kbeta > 90 and kgamma == 90:
                self._kpath = self.tria()
            if kalpha < 90 and kbeta < 90 and kgamma == 90:
                self._kpath = self.trib()

        else:
            warn("Unknown lattice type %s" % lattice_type)

    @property
    def structure(self):
        """
        Returns:
            The standardized primitive structure
        """
        return self._prim

    @property
    def kpath(self):
        """
        Returns:
            The symmetry line path in reciprocal space
        """
        return self._kpath

    def get_kpoints(self, line_density=20):
        """
            Returns:
                the kpoints along the paths in cartesian coordinates
                together with the labels for symmetry points -Wei
        """
        list_k_points = []
        sym_point_labels = []
        for b in self.kpath['path']:
            for i in range(1, len(b)):
                start = np.array(self.kpath['kpoints'][b[i - 1]])
                end = np.array(self.kpath['kpoints'][b[i]])
                distance = np.linalg.norm(
                    self._prim_rec.get_cartesian_coords(start) -
                    self._prim_rec.get_cartesian_coords(end))
                nb = int(ceil(distance * line_density))
                sym_point_labels.extend([b[i - 1]] + [''] * (nb - 1) + [b[i]])
                list_k_points.extend(
                    [self._prim_rec.get_cartesian_coords(start)
                     + float(i) / float(nb) *
                     (self._prim_rec.get_cartesian_coords(end)
                      - self._prim_rec.get_cartesian_coords(start))
                     for i in range(0, nb + 1)])
        return list_k_points, sym_point_labels

    def get_kpath_plot(self, **kwargs):
        """
        Gives the plot (as a matplotlib object) of the symmetry line path in
        the Brillouin Zone.

        Returns:
            `matplotlib` figure.
                                                                                         
        ================  ==============================================================
        kwargs            Meaning
        ================  ==============================================================
        show              True to show the figure (Default).
        savefig           'abc.png' or 'abc.eps'* to save the figure to a file.
        ================  ==============================================================
        """
        import itertools
        import matplotlib.pyplot as plt
        from mpl_toolkits.mplot3d import axes3d

        def _plot_shape_skeleton(bz, style):
            for iface in range(len(bz)):
                for line in itertools.combinations(bz[iface], 2):
                    for jface in range(len(bz)):
                        if iface < jface and line[0] in bz[jface]\
                                and line[1] in bz[jface]:
                            ax.plot([line[0][0], line[1][0]],
                                    [line[0][1], line[1][1]],
                                    [line[0][2], line[1][2]], style)

        def _plot_lattice(lattice):
            vertex1 = lattice.get_cartesian_coords([0.0, 0.0, 0.0])
            vertex2 = lattice.get_cartesian_coords([1.0, 0.0, 0.0])
            ax.plot([vertex1[0], vertex2[0]], [vertex1[1], vertex2[1]],
                    [vertex1[2], vertex2[2]], color='g', linewidth=3)
            vertex2 = lattice.get_cartesian_coords([0.0, 1.0, 0.0])
            ax.plot([vertex1[0], vertex2[0]], [vertex1[1], vertex2[1]],
                    [vertex1[2], vertex2[2]], color='g', linewidth=3)
            vertex2 = lattice.get_cartesian_coords([0.0, 0.0, 1.0])
            ax.plot([vertex1[0], vertex2[0]], [vertex1[1], vertex2[1]],
                    [vertex1[2], vertex2[2]], color='g', linewidth=3)

        def _plot_kpath(kpath, lattice):
            for line in kpath['path']:
                for k in range(len(line) - 1):
                    vertex1 = lattice.get_cartesian_coords(kpath['kpoints']
                                                           [line[k]])
                    vertex2 = lattice.get_cartesian_coords(kpath['kpoints']
                                                           [line[k + 1]])
                    ax.plot([vertex1[0], vertex2[0]], [vertex1[1], vertex2[1]],
                            [vertex1[2], vertex2[2]], color='r', linewidth=3)

        def _plot_labels(kpath, lattice):
            for k in kpath['kpoints']:
                label = k
                if k.startswith("\\") or k.find("_") != -1:
                    label = "$" + k + "$"
                off = 0.01
                ax.text(lattice.get_cartesian_coords(kpath['kpoints'][k])[0]
                        + off,
                        lattice.get_cartesian_coords(kpath['kpoints'][k])[1]
                        + off,
                        lattice.get_cartesian_coords(kpath['kpoints'][k])[2]
                        + off,
                        label, color='b', size='25')
                ax.scatter([lattice.get_cartesian_coords(
                            kpath['kpoints'][k])[0]],
                           [lattice.get_cartesian_coords(
                            kpath['kpoints'][k])[1]],
                           [lattice.get_cartesian_coords(
                            kpath['kpoints'][k])[2]], color='b')
        fig = plt.figure()
        ax = axes3d.Axes3D(fig)
        _plot_lattice(self._prim_rec)
        _plot_shape_skeleton(self._prim_rec.get_wigner_seitz_cell(), '-k')
        _plot_kpath(self.kpath, self._prim_rec)
        _plot_labels(self.kpath, self._prim_rec)
        ax.axis("off")

        show = kwargs.pop("show", True)
        if show:
            plt.show()

        savefig = kwargs.pop("savefig", None)
        if savefig:
            fig.savefig(savefig)

        return fig

    def cubic(self):
        self.name = "CUB"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'X': np.array([0.0, 0.5, 0.0]),
                   'R': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.5, 0.0])}
        path = [["\Gamma", "X", "M", "\Gamma", "R", "X"], ["M", "R"]]
        return {'kpoints': kpoints, 'path': path}

    def fcc(self):
        self.name = "FCC"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'K': np.array([3.0 / 8.0, 3.0 / 8.0, 3.0 / 4.0]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'U': np.array([5.0 / 8.0, 1.0 / 4.0, 5.0 / 8.0]),
                   'W': np.array([0.5, 1.0 / 4.0, 3.0 / 4.0]),
                   'X': np.array([0.5, 0.0, 0.5])}
        path = [["\Gamma", "X", "W", "K",
                 "\Gamma", "L", "U", "W", "L", "K"], ["U", "X"]]
        return {'kpoints': kpoints, 'path': path}

    def bcc(self):
        self.name = "BCC"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'H': np.array([0.5, -0.5, 0.5]),
                   'P': np.array([0.25, 0.25, 0.25]),
                   'N': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "H", "N", "\Gamma", "P", "H"], ["P", "N"]]
        return {'kpoints': kpoints, 'path': path}

    def tet(self):
        self.name = "TET"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.5, 0.0]),
                   'R': np.array([0.0, 0.5, 0.5]),
                   'X': np.array([0.0, 0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "X", "M", "\Gamma", "Z", "R", "A", "Z"], ["X", "R"],
                ["M", "A"]]
        return {'kpoints': kpoints, 'path': path}

    def bctet1(self, c, a):
        self.name = "BCT1"
        eta = (1 + c ** 2 / a ** 2) / 4.0
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'M': np.array([-0.5, 0.5, 0.5]),
                   'N': np.array([0.0, 0.5, 0.0]),
                   'P': np.array([0.25, 0.25, 0.25]),
                   'X': np.array([0.0, 0.0, 0.5]),
                   'Z': np.array([eta, eta, -eta]),
                   'Z_1': np.array([-eta, 1 - eta, eta])}
        path = [["\Gamma", "X", "M", "\Gamma", "Z", "P", "N", "Z_1", "M"],
                ["X", "P"]]
        return {'kpoints': kpoints, 'path': path}

    def bctet2(self, c, a):
        self.name = "BCT2"
        eta = (1 + a ** 2 / c ** 2) / 4.0
        zeta = a ** 2 / (2 * c ** 2)
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'N': np.array([0.0, 0.5, 0.0]),
                   'P': np.array([0.25, 0.25, 0.25]),
                   '\Sigma': np.array([-eta, eta, eta]),
                   '\Sigma_1': np.array([eta, 1 - eta, -eta]),
                   'X': np.array([0.0, 0.0, 0.5]),
                   'Y': np.array([-zeta, zeta, 0.5]),
                   'Y_1': np.array([0.5, 0.5, -zeta]),
                   'Z': np.array([0.5, 0.5, -0.5])}
        path = [["\Gamma", "X", "Y", "\Sigma", "\Gamma", "Z",
                 "\Sigma_1", "N", "P", "Y_1", "Z"], ["X", "P"]]
        return {'kpoints': kpoints, 'path': path}

    def orc(self):
        self.name = "ORC"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'R': np.array([0.5, 0.5, 0.5]),
                   'S': np.array([0.5, 0.5, 0.0]),
                   'T': np.array([0.0, 0.5, 0.5]),
                   'U': np.array([0.5, 0.0, 0.5]),
                   'X': np.array([0.5, 0.0, 0.0]),
                   'Y': np.array([0.0, 0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "X", "S", "Y", "\Gamma",
                 "Z", "U", "R", "T", "Z"], ["Y", "T"], ["U", "X"], ["S", "R"]]
        return {'kpoints': kpoints, 'path': path}

    def orcf1(self, a, b, c):
        self.name = "ORCF1"
        zeta = (1 + a ** 2 / b ** 2 - a ** 2 / c ** 2) / 4
        eta = (1 + a ** 2 / b ** 2 + a ** 2 / c ** 2) / 4

        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.5, 0.5 + zeta, zeta]),
                   'A_1': np.array([0.5, 0.5 - zeta, 1 - zeta]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'T': np.array([1, 0.5, 0.5]),
                   'X': np.array([0.0, eta, eta]),
                   'X_1': np.array([1, 1 - eta, 1 - eta]),
                   'Y': np.array([0.5, 0.0, 0.5]),
                   'Z': np.array([0.5, 0.5, 0.0])}
        path = [["\Gamma", "Y", "T", "Z", "\Gamma", "X", "A_1", "Y"],
                ["T", "X_1"], ["X", "A", "Z"], ["L", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def orcf2(self, a, b, c):
        self.name = "ORCF2"
        phi = (1 + c ** 2 / b ** 2 - c ** 2 / a ** 2) / 4
        eta = (1 + a ** 2 / b ** 2 - a ** 2 / c ** 2) / 4
        delta = (1 + b ** 2 / a ** 2 - b ** 2 / c ** 2) / 4
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'C': np.array([0.5, 0.5 - eta, 1 - eta]),
                   'C_1': np.array([0.5, 0.5 + eta, eta]),
                   'D': np.array([0.5 - delta, 0.5, 1 - delta]),
                   'D_1': np.array([0.5 + delta, 0.5, delta]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'H': np.array([1 - phi, 0.5 - phi, 0.5]),
                   'H_1': np.array([phi, 0.5 + phi, 0.5]),
                   'X': np.array([0.0, 0.5, 0.5]),
                   'Y': np.array([0.5, 0.0, 0.5]),
                   'Z': np.array([0.5, 0.5, 0.0])}
        path = [["\Gamma", "Y", "C", "D", "X", "\Gamma",
                 "Z", "D_1", "H", "C"], ["C_1", "Z"], ["X", "H_1"], ["H", "Y"],
                ["L", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def orcf3(self, a, b, c):
        self.name = "ORCF3"
        zeta = (1 + a ** 2 / b ** 2 - a ** 2 / c ** 2) / 4
        eta = (1 + a ** 2 / b ** 2 + a ** 2 / c ** 2) / 4
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.5, 0.5 + zeta, zeta]),
                   'A_1': np.array([0.5, 0.5 - zeta, 1 - zeta]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'T': np.array([1, 0.5, 0.5]),
                   'X': np.array([0.0, eta, eta]),
                   'X_1': np.array([1, 1 - eta, 1 - eta]),
                   'Y': np.array([0.5, 0.0, 0.5]),
                   'Z': np.array([0.5, 0.5, 0.0])}
        path = [["\Gamma", "Y", "T", "Z", "\Gamma", "X", "A_1", "Y"],
                ["X", "A", "Z"], ["L", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def orci(self, a, b, c):
        self.name = "ORCI"
        zeta = (1 + a ** 2 / c ** 2) / 4
        eta = (1 + b ** 2 / c ** 2) / 4
        delta = (b ** 2 - a ** 2) / (4 * c ** 2)
        mu = (a ** 2 + b ** 2) / (4 * c ** 2)
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'L': np.array([-mu, mu, 0.5 - delta]),
                   'L_1': np.array([mu, -mu, 0.5 + delta]),
                   'L_2': np.array([0.5 - delta, 0.5 + delta, -mu]),
                   'R': np.array([0.0, 0.5, 0.0]),
                   'S': np.array([0.5, 0.0, 0.0]),
                   'T': np.array([0.0, 0.0, 0.5]),
                   'W': np.array([0.25, 0.25, 0.25]),
                   'X': np.array([-zeta, zeta, zeta]),
                   'X_1': np.array([zeta, 1 - zeta, -zeta]),
                   'Y': np.array([eta, -eta, eta]),
                   'Y_1': np.array([1 - eta, eta, -eta]),
                   'Z': np.array([0.5, 0.5, -0.5])}
        path = [["\Gamma", "X", "L", "T", "W", "R", "X_1", "Z",
                 "\Gamma", "Y", "S", "W"], ["L_1", "Y"], ["Y_1", "Z"]]
        return {'kpoints': kpoints, 'path': path}

    def orcc(self, a, b, c):
        self.name = "ORCC"
        zeta = (1 + a ** 2 / b ** 2) / 4
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([zeta, zeta, 0.5]),
                   'A_1': np.array([-zeta, 1 - zeta, 0.5]),
                   'R': np.array([0.0, 0.5, 0.5]),
                   'S': np.array([0.0, 0.5, 0.0]),
                   'T': np.array([-0.5, 0.5, 0.5]),
                   'X': np.array([zeta, zeta, 0.0]),
                   'X_1': np.array([-zeta, 1 - zeta, 0.0]),
                   'Y': np.array([-0.5, 0.5, 0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "X", "S", "R", "A", "Z",
                 "\Gamma", "Y", "X_1", "A_1", "T", "Y"], ["Z", "T"]]
        return {'kpoints': kpoints, 'path': path}

    def hex(self):
        self.name = "HEX"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.0, 0.0, 0.5]),
                   'H': np.array([1.0 / 3.0, 1.0 / 3.0, 0.5]),
                   'K': np.array([1.0 / 3.0, 1.0 / 3.0, 0.0]),
                   'L': np.array([0.5, 0.0, 0.5]),
                   'M': np.array([0.5, 0.0, 0.0])}
        path = [["\Gamma", "M", "K", "\Gamma", "A", "L", "H", "A"], ["L", "M"],
                ["K", "H"]]
        return {'kpoints': kpoints, 'path': path}

    def rhl1(self, alpha):
        self.name = "RHL1"
        eta = (1 + 4 * cos(alpha)) / (2 + 4 * cos(alpha))
        nu = 3.0 / 4.0 - eta / 2.0
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'B': np.array([eta, 0.5, 1.0 - eta]),
                   'B_1': np.array([1.0 / 2.0, 1.0 - eta, eta - 1.0]),
                   'F': np.array([0.5, 0.5, 0.0]),
                   'L': np.array([0.5, 0.0, 0.0]),
                   'L_1': np.array([0.0, 0.0, -0.5]),
                   'P': np.array([eta, nu, nu]),
                   'P_1': np.array([1.0 - nu, 1.0 - nu, 1.0 - eta]),
                   'P_2': np.array([nu, nu, eta - 1.0]),
                   'Q': np.array([1.0 - nu, nu, 0.0]),
                   'X': np.array([nu, 0.0, -nu]),
                   'Z': np.array([0.5, 0.5, 0.5])}
        path = [["\Gamma", "L", "B_1"], ["B", "Z", "\Gamma", "X"],
                ["Q", "F", "P_1", "Z"], ["L", "P"]]
        return {'kpoints': kpoints, 'path': path}

    def rhl2(self, alpha):
        self.name = "RHL2"
        eta = 1 / (2 * tan(alpha / 2.0) ** 2)
        nu = 3.0 / 4.0 - eta / 2.0
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'F': np.array([0.5, -0.5, 0.0]),
                   'L': np.array([0.5, 0.0, 0.0]),
                   'P': np.array([1 - nu, -nu, 1 - nu]),
                   'P_1': np.array([nu, nu - 1.0, nu - 1.0]),
                   'Q': np.array([eta, eta, eta]),
                   'Q_1': np.array([1.0 - eta, -eta, -eta]),
                   'Z': np.array([0.5, -0.5, 0.5])}
        path = [["\Gamma", "P", "Z", "Q", "\Gamma",
                 "F", "P_1", "Q_1", "L", "Z"]]
        return {'kpoints': kpoints, 'path': path}

    def mcl(self, b, c, alpha):
        self.name = "MCL"
        eta = (1 - b * cos(alpha) / c) / (2 * sin(alpha) ** 2)
        nu = 0.5 - eta * c * cos(alpha) / b
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.5, 0.5, 0.0]),
                   'C': np.array([0.0, 0.5, 0.5]),
                   'D': np.array([0.5, 0.0, 0.5]),
                   'D_1': np.array([0.5, 0.5, -0.5]),
                   'E': np.array([0.5, 0.5, 0.5]),
                   'H': np.array([0.0, eta, 1.0 - nu]),
                   'H_1': np.array([0.0, 1.0 - eta, nu]),
                   'H_2': np.array([0.0, eta, -nu]),
                   'M': np.array([0.5, eta, 1.0 - nu]),
                   'M_1': np.array([0.5, 1 - eta, nu]),
                   'M_2': np.array([0.5, 1 - eta, nu]),
                   'X': np.array([0.0, 0.5, 0.0]),
                   'Y': np.array([0.0, 0.0, 0.5]),
                   'Y_1': np.array([0.0, 0.0, -0.5]),
                   'Z': np.array([0.5, 0.0, 0.0])}
        path = [["\Gamma", "Y", "H", "C", "E", "M_1", "A", "X", "H_1"],
                ["M", "D", "Z"], ["Y", "D"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc1(self, a, b, c, alpha):
        self.name = "MCLC1"
        zeta = (2 - b * cos(alpha) / c) / (4 * sin(alpha) ** 2)
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        psi = 0.75 - a ** 2 / (4 * b ** 2 * sin(alpha) ** 2)
        phi = psi + (0.75 - psi) * b * cos(alpha) / c
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'F': np.array([1 - zeta, 1 - zeta, 1 - eta]),
                   'F_1': np.array([zeta, zeta, eta]),
                   'F_2': np.array([-zeta, -zeta, 1 - eta]),
                   #'F_3': np.array([1 - zeta, -zeta, 1 - eta]),
                   'I': np.array([phi, 1 - phi, 0.5]),
                   'I_1': np.array([1 - phi, phi - 1, 0.5]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'X': np.array([1 - psi, psi - 1, 0.0]),
                   'X_1': np.array([psi, 1 - psi, 0.0]),
                   'X_2': np.array([psi - 1, -psi, 0.0]),
                   'Y': np.array([0.5, 0.5, 0.0]),
                   'Y_1': np.array([-0.5, -0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "L", "I"], ["I_1", "Z", "F_1"],
                ["Y", "X_1"], ["X", "\Gamma", "N"], ["M", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc2(self, a, b, c, alpha):
        self.name = "MCLC2"
        zeta = (2 - b * cos(alpha) / c) / (4 * sin(alpha) ** 2)
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        psi = 0.75 - a ** 2 / (4 * b ** 2 * sin(alpha) ** 2)
        phi = psi + (0.75 - psi) * b * cos(alpha) / c
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'F': np.array([1 - zeta, 1 - zeta, 1 - eta]),
                   'F_1': np.array([zeta, zeta, eta]),
                   'F_2': np.array([-zeta, -zeta, 1 - eta]),
                   'F_3': np.array([1 - zeta, -zeta, 1 - eta]),
                   'I': np.array([phi, 1 - phi, 0.5]),
                   'I_1': np.array([1 - phi, phi - 1, 0.5]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'X': np.array([1 - psi, psi - 1, 0.0]),
                   'X_1': np.array([psi, 1 - psi, 0.0]),
                   'X_2': np.array([psi - 1, -psi, 0.0]),
                   'Y': np.array([0.5, 0.5, 0.0]),
                   'Y_1': np.array([-0.5, -0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "L", "I"], ["I_1", "Z", "F_1"],
                ["N", "\Gamma", "M"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc3(self, a, b, c, alpha):
        self.name = "MCLC3"
        mu = (1 + b ** 2 / a ** 2) / 4.0
        delta = b * c * cos(alpha) / (2 * a ** 2)
        zeta = mu - 0.25 + (1 - b * cos(alpha) / c)\
            / (4 * sin(alpha) ** 2)
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        phi = 1 + zeta - 2 * mu
        psi = eta - 2 * delta
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'F': np.array([1 - phi, 1 - phi, 1 - psi]),
                   'F_1': np.array([phi, phi - 1, psi]),
                   'F_2': np.array([1 - phi, -phi, 1 - psi]),
                   'H': np.array([zeta, zeta, eta]),
                   'H_1': np.array([1 - zeta, -zeta, 1 - eta]),
                   'H_2': np.array([-zeta, -zeta, 1 - eta]),
                   'I': np.array([0.5, -0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'X': np.array([0.5, -0.5, 0.0]),
                   'Y': np.array([mu, mu, delta]),
                   'Y_1': np.array([1 - mu, -mu, -delta]),
                   'Y_2': np.array([-mu, -mu, -delta]),
                   'Y_3': np.array([mu, mu - 1, delta]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "H", "Z", "I", "F_1"],
                ["H_1", "Y_1", "X", "\Gamma", "N"], ["M", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc4(self, a, b, c, alpha):
        self.name = "MCLC4"
        mu = (1 + b ** 2 / a ** 2) / 4.0
        delta = b * c * cos(alpha) / (2 * a ** 2)
        zeta = mu - 0.25 + (1 - b * cos(alpha) / c)\
            / (4 * sin(alpha) ** 2)
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        phi = 1 + zeta - 2 * mu
        psi = eta - 2 * delta
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'F': np.array([1 - phi, 1 - phi, 1 - psi]),
                   'F_1': np.array([phi, phi - 1, psi]),
                   'F_2': np.array([1 - phi, -phi, 1 - psi]),
                   'H': np.array([zeta, zeta, eta]),
                   'H_1': np.array([1 - zeta, -zeta, 1 - eta]),
                   'H_2': np.array([-zeta, -zeta, 1 - eta]),
                   'I': np.array([0.5, -0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'X': np.array([0.5, -0.5, 0.0]),
                   'Y': np.array([mu, mu, delta]),
                   'Y_1': np.array([1 - mu, -mu, -delta]),
                   'Y_2': np.array([-mu, -mu, -delta]),
                   'Y_3': np.array([mu, mu - 1, delta]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "H", "Z", "I"],
                ["H_1", "Y_1", "X", "\Gamma", "N"], ["M", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc5(self, a, b, c, alpha):
        self.name = "MCLC5"
        zeta = (b ** 2 / a ** 2 + (1 - b * cos(alpha) / c)
                / sin(alpha) ** 2) / 4
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        mu = eta / 2 + b ** 2 / (4 * a ** 2) \
            - b * c * cos(alpha) / (2 * a ** 2)
        nu = 2 * mu - zeta
        rho = 1 - zeta * a ** 2 / b ** 2
        omega = (4 * nu - 1 - b ** 2 * sin(alpha) ** 2 / a ** 2)\
            * c / (2 * b * cos(alpha))
        delta = zeta * c * cos(alpha) / b + omega / 2 - 0.25
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'F': np.array([nu, nu, omega]),
                   'F_1': np.array([1 - nu, 1 - nu, 1 - omega]),
                   'F_2': np.array([nu, nu - 1, omega]),
                   'H': np.array([zeta, zeta, eta]),
                   'H_1': np.array([1 - zeta, -zeta, 1 - eta]),
                   'H_2': np.array([-zeta, -zeta, 1 - eta]),
                   'I': np.array([rho, 1 - rho, 0.5]),
                   'I_1': np.array([1 - rho, rho - 1, 0.5]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'X': np.array([0.5, -0.5, 0.0]),
                   'Y': np.array([mu, mu, delta]),
                   'Y_1': np.array([1 - mu, -mu, -delta]),
                   'Y_2': np.array([-mu, -mu, -delta]),
                   'Y_3': np.array([mu, mu - 1, delta]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "L", "I"], ["I_1", "Z", "H", "F_1"],
                ["H_1", "Y_1", "X", "\Gamma", "N"], ["M", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def tria(self):
        self.name = "TRI1a"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'L': np.array([0.5, 0.5, 0.0]),
                   'M': np.array([0.0, 0.5, 0.5]),
                   'N': np.array([0.5, 0.0, 0.5]),
                   'R': np.array([0.5, 0.5, 0.5]),
                   'X': np.array([0.5, 0.0, 0.0]),
                   'Y': np.array([0.0, 0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["X", "\Gamma", "Y"], ["L", "\Gamma", "Z"],
                ["N", "\Gamma", "M"], ["R", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def trib(self):
        self.name = "TRI1b"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'L': np.array([0.5, -0.5, 0.0]),
                   'M': np.array([0.0, 0.0, 0.5]),
                   'N': np.array([-0.5, -0.5, 0.5]),
                   'R': np.array([0.0, -0.5, 0.5]),
                   'X': np.array([0.0, -0.5, 0.0]),
                   'Y': np.array([0.5, 0.0, 0.0]),
                   'Z': np.array([-0.5, 0.0, 0.5])}
        path = [["X", "\Gamma", "Y"], ["L", "\Gamma", "Z"],
                ["N", "\Gamma", "M"], ["R", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}
Ejemplo n.º 19
0
    def generate_doc(cls, dir_name, vasprun_files, parse_dos,
                     additional_fields):
        """Process aflow style and NEB runs."""
        print "TTM DEBUG: In generate_doc for NEB task drone."
        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 additional_fields.items()} \
                if additional_fields else {}
            d["dir_name"] = fullpath
            print "TTM DEBUG: fullpath: ", fullpath
            d["schema_version"] = NEBToDbTaskDrone.__version__
            d["calculations"] = [
                cls.process_vasprun(dir_name, taskname, filename, parse_dos)
                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"]))
            d["input"] = {"crystal": d1["input"]["crystal"]}
            vals = sorted(d2["reduced_cell_formula"].values())
            d["anonymous_formula"] = {
                string.ascii_uppercase[i]: float(vals[i])
                for i in xrange(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"
            d["pseudo_potential"] = {
                "functional": "pbe",
                "pot_type": "paw",
                "labels": d2["input"]["potcar"]
            }

            if len(d["calculations"]) == 2 or \
                    vasprun_files.keys()[0] != "relax1":
                d["state"] = "successful" if d2["has_vasp_completed"] \
                    else "unsuccessful"
            else:
                d["state"] = "stopped"

            s = Structure.from_dict(d2["output"]["crystal"])
            if not s.is_valid():
                d["state"] = "errored_bad_structure"

            d["analysis"] = get_basic_analysis_and_error_checks(d)

            sg = SymmetryFinder(Structure.from_dict(d["output"]["crystal"]),
                                0.1)
            d["spacegroup"] = {
                "symbol": sg.get_spacegroup_symbol(),
                "number": sg.get_spacegroup_number(),
                "point_group": unicode(sg.get_point_group(), errors="ignore"),
                "source": "spglib",
                "crystal_system": sg.get_crystal_system(),
                "hall": sg.get_hall()
            }
            d["last_updated"] = datetime.datetime.today()

            # Process NEB runs. The energy and magnetic moments for each image are listed.
            # Some useful values are calculated.

            # Number of NEB images
            print "TTM DEBUG: At NEB processing stage."
            image_list = []
            for i in xrange(0, 9):
                append = "0" + str(i)
                newpath = os.path.join(fullpath, append)
                if os.path.exists(newpath):
                    image_list.append(newpath)
            d["num_images"] = len(image_list)
            print "TTM DEBUG: Image list:", image_list
            # Image energies and magnetic moments for specific folders
            list_image_energies = []
            list_image_mags = []
            for i in xrange(0, len(image_list)):
                append = "0" + str(i)
                oszicar = os.path.join(fullpath, append, "OSZICAR")
                if not os.path.isfile(oszicar):
                    return None
                val_energy = util2.getEnergy(oszicar)
                val_mag = util2.getMag(oszicar)
                d["E_" + append] = val_energy
                d["mag_" + append] = val_mag
                list_image_energies.append(val_energy)
                list_image_mags.append(val_mag)
            print "TTM DEBUG: first occurrence list_image_mags", list_image_mags
            # List of image energies and magnetic moments in order
            image_energies = ' '.join(map(str, list_image_energies))
            d["image_energies"] = image_energies

            # An simple way to visualize relative image energies and magnetic moments
            energy_contour = "-x-"
            if len(image_list) == 0:
                return None
            for i in xrange(1, len(image_list)):
                if (list_image_energies[i] > list_image_energies[i - 1]):
                    energy_contour += "/-x-"
                elif list_image_energies[i] < list_image_energies[i - 1]:
                    energy_contour += "\\-x-"
                else:
                    energy_contour += "=-x-"
            d["energy_contour"] = energy_contour
            print "TTM DEBUG: energy contour:", energy_contour

            # Difference between the first and maximum energies and magnetic moments
            deltaE_firstmax = max(list_image_energies) - list_image_energies[0]
            d["deltaE_firstmax"] = deltaE_firstmax
            # Difference between the last and maximum energies and magnetic moments
            deltaE_lastmax = max(list_image_energies) - list_image_energies[-1]
            d["deltaE_lastmax"] = deltaE_lastmax

            # Difference between the endpoint energies and magnetic moments
            deltaE_endpoints = list_image_energies[-1] - list_image_energies[0]
            d["deltaE_endpoints"] = deltaE_endpoints

            # Difference between the minimum and maximum energies and magnetic moments
            deltaE_maxmin = max(list_image_energies) - min(list_image_energies)
            d["deltaE_maxmin"] = deltaE_maxmin

            #INDENT THE NEXT LINES:
            if not (list_image_mags[0] == None):  #if ISPIN not 2, no mag info
                image_mags = ' '.join(map(str, list_image_mags))
                d["image_mags"] = image_mags
                mag_contour = "-o-"
                if len(image_list) == 0:
                    return None
                for i in xrange(1, len(image_list)):
                    if (list_image_mags[i] > list_image_mags[i - 1]):
                        mag_contour += "/-o-"
                    elif list_image_mags[i] < list_image_mags[i - 1]:
                        mag_contour += "\\-o-"
                    else:
                        mag_contour += "=-o-"
                d["mag_contour"] = mag_contour
                deltaM_firstmax = max(list_image_mags) - list_image_mags[0]
                d["deltaM_firstmax"] = deltaM_firstmax
                deltaM_lastmax = max(list_image_mags) - list_image_mags[-1]
                d["deltaM_lastmax"] = deltaM_lastmax
                deltaM_endpoints = list_image_mags[-1] - list_image_mags[0]
                d["deltaM_endpoints"] = deltaM_endpoints
                deltaM_maxmin = max(list_image_mags) - min(list_image_mags)
                d["deltaM_maxmin"] = deltaM_maxmin

            d["type"] = "NEB"

            return d

        except Exception as ex:
            logger.error("Error in " + os.path.abspath(dir_name) +
                         ".\nError msg: " + str(ex))
            return None
Ejemplo n.º 20
0
    def generate_doc(cls, dir_name, vasprun_files, parse_dos,
                     additional_fields):
        """
        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 additional_fields.items()} \
                if additional_fields else {}
            d["dir_name"] = fullpath
            d["schema_version"] = VaspToDbTaskDrone.__version__
            d["calculations"] = [
                cls.process_vasprun(dir_name, taskname, filename, parse_dos)
                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"]))
            d["input"] = {"crystal": d1["input"]["crystal"]}
            vals = sorted(d2["reduced_cell_formula"].values())
            d["anonymous_formula"] = {
                string.ascii_uppercase[i]: float(vals[i])
                for i in xrange(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"
            d["pseudo_potential"] = {
                "functional": "pbe",
                "pot_type": "paw",
                "labels": d2["input"]["potcar"]
            }

            if len(d["calculations"]) == 2 or \
                    vasprun_files.keys()[0] != "relax1":
                d["state"] = "successful" if d2["has_vasp_completed"] \
                    else "unsuccessful"
            else:
                d["state"] = "stopped"

            s = Structure.from_dict(d2["output"]["crystal"])
            if not s.is_valid():
                d["state"] = "errored_bad_structure"

            d["analysis"] = get_basic_analysis_and_error_checks(d)

            sg = SymmetryFinder(Structure.from_dict(d["output"]["crystal"]),
                                0.1)
            d["spacegroup"] = {
                "symbol": sg.get_spacegroup_symbol(),
                "number": sg.get_spacegroup_number(),
                "point_group": unicode(sg.get_point_group(), errors="ignore"),
                "source": "spglib",
                "crystal_system": sg.get_crystal_system(),
                "hall": sg.get_hall()
            }
            d["last_updated"] = datetime.datetime.today()
            d["type"] = "VASP"  #PS

            return d
        except Exception as ex:
            logger.error("Error in " + os.path.abspath(dir_name) +
                         ".\nError msg: " + str(ex))
            return None
Ejemplo n.º 21
0
    def __init__(self, struct, find_spacegroup=False):
        block = CifFile.CifBlock()
        latt = struct.lattice
        comp = struct.composition
        no_oxi_comp = Composition(comp.formula)
        spacegroup = ("P 1", 1)
        if find_spacegroup:
            sf = SymmetryFinder(struct, 0.001)
            spacegroup = (sf.get_spacegroup_symbol(),
                          sf.get_spacegroup_number())
        block["_symmetry_space_group_name_H-M"] = spacegroup[0]
        for cell_attr in ['a', 'b', 'c']:
            block["_cell_length_" + cell_attr] = str(getattr(latt, cell_attr))
        for cell_attr in ['alpha', 'beta', 'gamma']:
            block["_cell_angle_" + cell_attr] = float(getattr(latt, cell_attr))
        block["_chemical_name_systematic"] = "Generated by pymatgen"
        block["_symmetry_Int_Tables_number"] = spacegroup[1]
        block["_chemical_formula_structural"] = str(
            no_oxi_comp.reduced_formula)
        block["_chemical_formula_sum"] = str(no_oxi_comp.formula)
        block["_cell_volume"] = str(latt.volume)

        reduced_comp = Composition.from_formula(no_oxi_comp.reduced_formula)
        el = no_oxi_comp.elements[0]
        amt = comp[el]
        fu = int(amt / reduced_comp[Element(el.symbol)])

        block["_cell_formula_units_Z"] = str(fu)
        block.AddCifItem(
            ([["_symmetry_equiv_pos_site_id",
               "_symmetry_equiv_pos_as_xyz"]], [[["1"], ["x, y, z"]]]))

        contains_oxidation = True
        try:
            symbol_to_oxinum = {
                str(el): float(el.oxi_state)
                for el in comp.elements
            }
        except AttributeError:
            symbol_to_oxinum = {el.symbol: 0 for el in comp.elements}
            contains_oxidation = False
        if contains_oxidation:
            block.AddCifItem(
                ([["_atom_type_symbol", "_atom_type_oxidation_number"]],
                 [[symbol_to_oxinum.keys(),
                   symbol_to_oxinum.values()]]))

        atom_site_type_symbol = []
        atom_site_symmetry_multiplicity = []
        atom_site_fract_x = []
        atom_site_fract_y = []
        atom_site_fract_z = []
        atom_site_attached_hydrogens = []
        atom_site_B_iso_or_equiv = []
        atom_site_label = []
        atom_site_occupancy = []
        count = 1
        for site in struct:
            for sp, occu in site.species_and_occu.items():
                atom_site_type_symbol.append(str(sp))
                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_attached_hydrogens.append("0")
                atom_site_B_iso_or_equiv.append(".")
                atom_site_label.append("{}{}".format(sp.symbol, count))
                atom_site_occupancy.append(str(occu))
                count += 1

        block["_atom_site_type_symbol"] = atom_site_type_symbol
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_label": atom_site_label})
        block.AddToLoop("_atom_site_type_symbol", {
            "_atom_site_symmetry_multiplicity":
            atom_site_symmetry_multiplicity
        })
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_x": atom_site_fract_x})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_y": atom_site_fract_y})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_z": atom_site_fract_z})
        block.AddToLoop(
            "_atom_site_type_symbol",
            {"_atom_site_attached_hydrogens": atom_site_attached_hydrogens})
        block.AddToLoop(
            "_atom_site_type_symbol",
            {"_atom_site_B_iso_or_equiv": atom_site_B_iso_or_equiv})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_occupancy": atom_site_occupancy})

        self._cf = CifFile.CifFile()
        # AJ says: CIF Block names cannot be more than 75 characters or you
        # get an Exception
        self._cf[comp.reduced_formula[0:74]] = block
Ejemplo n.º 22
0
    def __init__(self, struct, find_spacegroup=False):
        block = CifFile.CifBlock()
        latt = struct.lattice
        comp = struct.composition
        no_oxi_comp = Composition(comp.formula)
        spacegroup = ("P 1", 1)
        if find_spacegroup:
            sf = SymmetryFinder(struct, 0.001)
            spacegroup = (sf.get_spacegroup_symbol(), sf.get_spacegroup_number())
        block["_symmetry_space_group_name_H-M"] = spacegroup[0]
        for cell_attr in ['a', 'b', 'c']:
            block["_cell_length_" + cell_attr] = str(getattr(latt, cell_attr))
        for cell_attr in ['alpha', 'beta', 'gamma']:
            block["_cell_angle_" + cell_attr] = float(getattr(latt, cell_attr))
        block["_chemical_name_systematic"] = "Generated by pymatgen"
        block["_symmetry_Int_Tables_number"] = spacegroup[1]
        block["_chemical_formula_structural"] = str(no_oxi_comp
                                                    .reduced_formula)
        block["_chemical_formula_sum"] = str(no_oxi_comp.formula)
        block["_cell_volume"] = str(latt.volume)

        reduced_comp = Composition.from_formula(no_oxi_comp.reduced_formula)
        el = no_oxi_comp.elements[0]
        amt = comp[el]
        fu = int(amt / reduced_comp[Element(el.symbol)])

        block["_cell_formula_units_Z"] = str(fu)
        block.AddCifItem(([["_symmetry_equiv_pos_site_id",
                            "_symmetry_equiv_pos_as_xyz"]],
                          [[["1"], ["x, y, z"]]]))

        contains_oxidation = True
        try:
            symbol_to_oxinum = {str(el): float(el.oxi_state)
                                for el in comp.elements}
        except AttributeError:
            symbol_to_oxinum = {el.symbol: 0 for el in comp.elements}
            contains_oxidation = False
        if contains_oxidation:
            block.AddCifItem(([["_atom_type_symbol",
                                "_atom_type_oxidation_number"]],
                              [[symbol_to_oxinum.keys(),
                                symbol_to_oxinum.values()]]))

        atom_site_type_symbol = []
        atom_site_symmetry_multiplicity = []
        atom_site_fract_x = []
        atom_site_fract_y = []
        atom_site_fract_z = []
        atom_site_attached_hydrogens = []
        atom_site_B_iso_or_equiv = []
        atom_site_label = []
        atom_site_occupancy = []
        count = 1
        for site in struct:
            for sp, occu in site.species_and_occu.items():
                atom_site_type_symbol.append(str(sp))
                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_attached_hydrogens.append("0")
                atom_site_B_iso_or_equiv.append(".")
                atom_site_label.append("{}{}".format(sp.symbol, count))
                atom_site_occupancy.append(str(occu))
                count += 1

        block["_atom_site_type_symbol"] = atom_site_type_symbol
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_label": atom_site_label})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_symmetry_multiplicity":
                         atom_site_symmetry_multiplicity})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_x": atom_site_fract_x})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_y": atom_site_fract_y})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_z": atom_site_fract_z})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_attached_hydrogens":
                         atom_site_attached_hydrogens})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_B_iso_or_equiv":
                         atom_site_B_iso_or_equiv})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_occupancy": atom_site_occupancy})

        self._cf = CifFile.CifFile()
        # AJ says: CIF Block names cannot be more than 75 characters or you
        # get an Exception
        self._cf[comp.reduced_formula[0:74]] = block
Ejemplo n.º 23
0
    def complete_ordering(self, structure, num_remove_dict):
        self.logger.debug("Performing complete ordering...")
        all_structures = []
        from pymatgen.symmetry.finder import SymmetryFinder
        symprec = 0.2
        s = SymmetryFinder(structure, symprec=symprec)
        self.logger.debug(
            "Symmetry of structure is determined to be {}.".format(
                s.get_spacegroup_symbol()))
        sg = s.get_spacegroup()
        tested_sites = []
        starttime = time.time()
        self.logger.debug("Performing initial ewald sum...")
        ewaldsum = EwaldSummation(structure)
        self.logger.debug("Ewald sum took {} seconds.".format(time.time() -
                                                              starttime))
        starttime = time.time()

        allcombis = []
        for ind, num in num_remove_dict.items():
            allcombis.append(itertools.combinations(ind, num))

        count = 0
        for allindices in itertools.product(*allcombis):
            sites_to_remove = []
            indices_list = []
            for indices in allindices:
                sites_to_remove.extend([structure[i] for i in indices])
                indices_list.extend(indices)
            s_new = Structure.from_sites(structure.sites)
            s_new.remove_sites(indices_list)
            energy = ewaldsum.compute_partial_energy(indices_list)
            already_tested = False
            for i, tsites in enumerate(tested_sites):
                tenergy = all_structures[i]["energy"]
                if abs((energy - tenergy) / len(s_new)) < 1e-5 and \
                        sg.are_symmetrically_equivalent(sites_to_remove,
                                                        tsites,
                                                        symm_prec=symprec):
                    already_tested = True

            if not already_tested:
                tested_sites.append(sites_to_remove)
                all_structures.append({"structure": s_new, "energy": energy})

            count += 1
            if count % 10 == 0:
                timenow = time.time()
                self.logger.debug("{} structures, {:.2f} seconds.".format(
                    count, timenow - starttime))
                self.logger.debug("Average time per combi = {} seconds".format(
                    (timenow - starttime) / count))
                self.logger.debug(
                    "{} symmetrically distinct structures found.".format(
                        len(all_structures)))

        self.logger.debug(
            "Total symmetrically distinct structures found = {}".format(
                len(all_structures)))
        all_structures = sorted(all_structures, key=lambda s: s["energy"])
        return all_structures
Ejemplo n.º 24
0
    def generate_doc(cls, dir_name, vasprun_files, parse_dos, additional_fields):
        """
        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 additional_fields.items()} if additional_fields else {}
            d["dir_name"] = fullpath
            d["schema_version"] = VaspToDbTaskDrone.__version__
            d["calculations"] = [
                cls.process_vasprun(dir_name, taskname, filename, parse_dos)
                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"]))
            d["input"] = {"crystal": d1["input"]["crystal"]}
            vals = sorted(d2["reduced_cell_formula"].values())
            d["anonymous_formula"] = {string.ascii_uppercase[i]: float(vals[i]) for i in xrange(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"
            d["pseudo_potential"] = {"functional": "pbe", "pot_type": "paw", "labels": d2["input"]["potcar"]}

            if len(d["calculations"]) == 2 or vasprun_files.keys()[0] != "relax1":
                d["state"] = "successful" if d2["has_vasp_completed"] else "unsuccessful"
            else:
                d["state"] = "stopped"

            s = Structure.from_dict(d2["output"]["crystal"])
            if not s.is_valid():
                d["state"] = "errored_bad_structure"

            d["analysis"] = get_basic_analysis_and_error_checks(d)

            sg = SymmetryFinder(Structure.from_dict(d["output"]["crystal"]), 0.1)
            d["spacegroup"] = {
                "symbol": sg.get_spacegroup_symbol(),
                "number": sg.get_spacegroup_number(),
                "point_group": unicode(sg.get_point_group(), errors="ignore"),
                "source": "spglib",
                "crystal_system": sg.get_crystal_system(),
                "hall": sg.get_hall(),
            }
            d["last_updated"] = datetime.datetime.today()
            return d
        except Exception as ex:
            logger.error("Error in " + os.path.abspath(dir_name) + ".\nError msg: " + str(ex))
            return None
Ejemplo n.º 25
0
class SymmetryFinderTest(unittest.TestCase):
    def setUp(self):
        p = Poscar.from_file(os.path.join(test_dir, 'POSCAR'))
        self.structure = p.structure
        self.sg = SymmetryFinder(self.structure, 0.001)
        parser = CifParser(os.path.join(test_dir, 'Li10GeP2S12.cif'))
        self.disordered_structure = parser.get_structures()[0]
        self.disordered_sg = SymmetryFinder(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 = SymmetryFinder(s, 0.001)
        parser = CifParser(os.path.join(test_dir, 'Graphite.cif'))
        graphite = parser.get_structures()[0]
        graphite.add_site_property("magmom", [0.1] * len(graphite))
        self.sg4 = SymmetryFinder(graphite, 0.001)

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

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

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

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

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

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

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

    def test_get_refined_structure(self):
        for a in self.sg.get_refined_structure().lattice.angles:
            self.assertEqual(a, 90)
        refined = self.disordered_sg.get_refined_structure()
        for a in refined.lattice.angles:
            self.assertEqual(a, 90)
        self.assertEqual(refined.lattice.a, refined.lattice.b)
        parser = CifParser(os.path.join(test_dir, 'Li2O.cif'))
        s = parser.get_structures()[0]
        sg = SymmetryFinder(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(map(len, symm_struct.equivalent_sites),
                         [16, 4, 8, 4, 2, 8, 8, 8])
        s1 = symm_struct.equivalent_sites[1][1]
        s2 = symm_struct[symm_struct.equivalent_indices[1][1]]
        self.assertEqual(s1, s2)
        self.assertEqual(self.sg4.get_symmetrized_structure()[0].magmom, 0.1)

    def test_find_primitive(self):
        """
        F m -3 m Li2O testing of converting to primitive cell
        """
        parser = CifParser(os.path.join(test_dir, 'Li2O.cif'))
        structure = parser.get_structures(False)[0]
        s = SymmetryFinder(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.assertEquals(len(grid), 216)
        self.assertAlmostEquals(grid[1][0][0], 0.1)
        self.assertAlmostEquals(grid[1][0][1], 0.0)
        self.assertAlmostEquals(grid[1][0][2], 0.0)
        self.assertEquals(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 117.53832420192903)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 14.033435583000625)
        self.assertAlmostEqual(conv.lattice.b, 3.96052850731)
        self.assertAlmostEqual(conv.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'rhomb_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 63.579155761999999)
        self.assertAlmostEqual(prim.lattice.beta, 116.42084423747779)
        self.assertAlmostEqual(prim.lattice.gamma, 148.47965136208569)
        self.assertAlmostEqual(prim.lattice.a, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.b, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'rhomb_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SymmetryFinder(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)
Ejemplo n.º 26
0
            ndiv = int(sys.argv[sys.argv.index("-d") + 1])
        except ValueError, IndexError:
            print("-d must be followed by an integer")
            exit(1)

# read structure
if os.path.exists(fstruct):
    struct = mg.read_structure(fstruct)
else:
    print("File %s does not exist" % fstruct)
    exit(1)

# symmetry information
struct_sym = SymmetryFinder(struct)
print("lattice type : {0}".format(struct_sym.get_lattice_type()))
print("space group  : {0} ({1})".format(struct_sym.get_spacegroup_symbol(),
                                     struct_sym.get_spacegroup_number()))

# Compute first brillouin zone
ibz = HighSymmKpath(struct)
ibz.get_kpath_plot(savefig="path.png")
print("ibz type     : {0}".format(ibz.name))

# print specific kpoints in the first brillouin zone
for key, val in ibz.kpath["kpoints"].items():
    print("%8s %s" % (key, str(val)))
 
# suggested path for the band structure
print("paths in first brillouin zone :")
for path in ibz.kpath["path"]:
    print(path)
Ejemplo n.º 27
0
    def calc_shiftk(self, symprec=0.01, angle_tolerance=5):
        """
        Find the values of shiftk and nshiftk appropriate for the sampling of the Brillouin zone.

        Returns
            Suggested value of shiftk

        .. note:

            When the primitive vectors of the lattice do NOT form a FCC or a BCC lattice, 
            the usual (shifted) Monkhorst-Pack grids are formed by using nshiftk=1 and shiftk 0.5 0.5 0.5 . 
            This is often the preferred k point sampling. For a non-shifted Monkhorst-Pack grid, 
            use nshiftk=1 and shiftk 0.0 0.0 0.0 , but there is little reason to do that.

            2) When the primitive vectors of the lattice form a FCC lattice, with rprim

                    0.0 0.5 0.5
                    0.5 0.0 0.5
                    0.5 0.5 0.0

            the (very efficient) usual Monkhorst-Pack sampling will be generated by using nshiftk= 4 and shiftk

                    0.5 0.5 0.5
                    0.5 0.0 0.0
                    0.0 0.5 0.0
                    0.0 0.0 0.5

            3) When the primitive vectors of the lattice form a BCC lattice, with rprim

                   -0.5  0.5  0.5
                    0.5 -0.5  0.5
                    0.5  0.5 -0.5

            the usual Monkhorst-Pack sampling will be generated by using nshiftk= 2 and shiftk

                    0.25  0.25  0.25
                   -0.25 -0.25 -0.25

            However, the simple sampling nshiftk=1 and shiftk 0.5 0.5 0.5 is excellent.

            4) For hexagonal lattices with hexagonal axes, e.g. rprim

                    1.0  0.0       0.0
                   -0.5  sqrt(3)/2 0.0
                    0.0  0.0       1.0

            one can use nshiftk= 1 and shiftk 0.0 0.0 0.5

            In rhombohedral axes, e.g. using angdeg 3*60., this corresponds to shiftk 0.5 0.5 0.5, 
            to keep the shift along the symmetry axis. 
        """
        # Find lattice type.
        from pymatgen.symmetry.finder import SymmetryFinder
        sym = SymmetryFinder(self, symprec=symprec, angle_tolerance=angle_tolerance)
        lattice_type = sym.get_lattice_type() 
        spg_symbol = sym.get_spacegroup_symbol()

        # Generate the appropriate set of shifts.
        shiftk = None

        if lattice_type == "cubic":
            if "F" in spg_symbol:  
                # FCC
                shiftk = [0.5, 0.5, 0.5,
                          0.5, 0.0, 0.0,
                          0.0, 0.5, 0.0,
                          0.0, 0.0, 0.5]

            elif "I" in spg_symbol:  
                # BCC
                shiftk = [0.25,  0.25,  0.25,
                         -0.25, -0.25, -0.25]

                #shiftk = [0.5, 0.5, 05])

        elif lattice_type == "hexagonal":
            # Find the hexagonal axis and set the shift along it.
            for i, angle in enumerate(self.lattice.angles):
                if abs(angle - 120) < 1.0:
                    j = (i + 1) % 3
                    k = (i + 2) % 3
                    hex_ax = [ax for ax in range(3) if ax not in [j,k]][0] 
                    break
            else:
                raise ValueError("Cannot find hexagonal axis")

            shiftk = [0.0, 0.0, 0.0]
            shiftk[hex_ax] = 0.5 

        if shiftk is None:
            # Use default value.
            shiftk = [0.5, 0.5, 0.5]

        return np.reshape(shiftk, (-1,3))
Ejemplo n.º 28
0
class HighSymmKpath(object):
    """
    This class looks for path along high symmetry lines in
    the Brillouin Zone.
    It is based on Setyawan, W., & Curtarolo, S. (2010).
    High-throughput electronic band structure calculations:
    Challenges and tools. Computational Materials Science,
    49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010
    The symmetry is determined by spglib through the
    SymmetryFinder class

    Args:
        structure (Structure): Structure object
        symprec (float): Tolerance for symmetry finding
        angle_tolerance (float): Angle tolerance for symmetry finding.
    """

    def __init__(self, structure, symprec=0.01, angle_tolerance=5):
        self._structure = structure
        self._sym = SymmetryFinder(structure, symprec=symprec,
                                   angle_tolerance=angle_tolerance)
        self._prim = self._sym\
            .get_primitive_standard_structure(international_monoclinic=False)
        self._conv = self._sym.get_conventional_standard_structure(international_monoclinic=False)
        self._prim_rec = self._prim.lattice.reciprocal_lattice
        self._kpath = None

        lattice_type = self._sym.get_lattice_type()
        spg_symbol = self._sym.get_spacegroup_symbol()

        if lattice_type == "cubic":
            if "P" in spg_symbol:
                self._kpath = self.cubic()
            elif "F" in spg_symbol:
                self._kpath = self.fcc()
            elif "I" in spg_symbol:
                self._kpath = self.bcc()
            else:
                warn("Unexpected value for spg_symbol: %s" % spg_symbol)

        elif lattice_type == "tetragonal":
            if "P" in spg_symbol:
                self._kpath = self.tet()
            elif "I" in spg_symbol:
                a = self._conv.lattice.abc[0]
                c = self._conv.lattice.abc[2]
                if c < a:
                    self._kpath = self.bctet1(c, a)
                else:
                    self._kpath = self.bctet2(c, a)
            else:
                warn("Unexpected value for spg_symbol: %s" % spg_symbol)

        elif lattice_type == "orthorhombic":
            a = self._conv.lattice.abc[0]
            b = self._conv.lattice.abc[1]
            c = self._conv.lattice.abc[2]

            if "P" in spg_symbol:
                self._kpath = self.orc()

            elif "F" in spg_symbol:
                if 1 / a ** 2 > 1 / b ** 2 + 1 / c ** 2:
                    self._kpath = self.orcf1(a, b, c)
                elif 1 / a ** 2 < 1 / b ** 2 + 1 / c ** 2:
                    self._kpath = self.orcf2(a, b, c)
                else:
                    self._kpath = self.orcf3(a, b, c)

            elif "I" in spg_symbol:
                self._kpath = self.orci(a, b, c)

            elif "C" in spg_symbol:
                self._kpath = self.orcc(a, b, c)
            else:
                warn("Unexpected value for spg_symbol: %s" % spg_symbol)

        elif lattice_type == "hexagonal":
            self._kpath = self.hex()

        elif lattice_type == "rhombohedral":
            alpha = self._prim.lattice.lengths_and_angles[1][0]
            if alpha < 90:
                self._kpath = self.rhl1(alpha * pi / 180)
            else:
                self._kpath = self.rhl2(alpha * pi / 180)

        elif lattice_type == "monoclinic":
            a, b, c = self._conv.lattice.abc
            alpha = self._conv.lattice.lengths_and_angles[1][0]
            #beta = self._conv.lattice.lengths_and_angles[1][1]

            if "P" in spg_symbol:
                self._kpath = self.mcl(b, c, alpha * pi / 180)

            elif "C" in spg_symbol:
                kgamma = self._prim_rec.lengths_and_angles[1][2]
                if kgamma > 90:
                    self._kpath = self.mclc1(a, b, c, alpha * pi / 180)
                if kgamma == 90:
                    self._kpath = self.mclc2(a, b, c, alpha * pi / 180)
                if kgamma < 90:
                    if b * cos(alpha * pi / 180) / c\
                            + b ** 2 * sin(alpha) ** 2 / a ** 2 < 1:
                        self._kpath = self.mclc3(a, b, c, alpha * pi / 180)
                    if b * cos(alpha * pi / 180) / c \
                            + b ** 2 * sin(alpha) ** 2 / a ** 2 == 1:
                        self._kpath = self.mclc4(a, b, c, alpha * pi / 180)
                    if b * cos(alpha * pi / 180) / c \
                            + b ** 2 * sin(alpha) ** 2 / a ** 2 > 1:
                        self._kpath = self.mclc5(a, b, c, alpha * pi / 180)
            else:
                warn("Unexpected value for spg_symbol: %s" % spg_symbol)

        elif lattice_type == "triclinic":
            kalpha = self._prim_rec.lengths_and_angles[1][0]
            kbeta = self._prim_rec.lengths_and_angles[1][1]
            kgamma = self._prim_rec.lengths_and_angles[1][2]
            if kalpha > 90 and kbeta > 90 and kgamma > 90:
                self._kpath = self.tria()
            if kalpha < 90 and kbeta < 90 and kgamma < 90:
                self._kpath = self.trib()
            if kalpha > 90 and kbeta > 90 and kgamma == 90:
                self._kpath = self.tria()
            if kalpha < 90 and kbeta < 90 and kgamma == 90:
                self._kpath = self.trib()

        else:
            warn("Unknown lattice type %s" % lattice_type)

    @property
    def structure(self):
        """
        Returns:
            The standardized primitive structure
        """
        return self._prim

    @property
    def kpath(self):
        """
        Returns:
            The symmetry line path in reciprocal space
        """
        return self._kpath

    def get_kpoints(self, line_density=20):
        """
        Returns:
            the kpoints along the paths in cartesian coordinates
            together with the labels for symmetry points -Wei
        """
        list_k_points = []
        sym_point_labels = []
        for b in self.kpath['path']:
            for i in range(1, len(b)):
                start = np.array(self.kpath['kpoints'][b[i - 1]])
                end = np.array(self.kpath['kpoints'][b[i]])
                distance = np.linalg.norm(
                    self._prim_rec.get_cartesian_coords(start) -
                    self._prim_rec.get_cartesian_coords(end))
                nb = int(ceil(distance * line_density))
                sym_point_labels.extend([b[i - 1]] + [''] * (nb - 1) + [b[i]])
                list_k_points.extend(
                    [self._prim_rec.get_cartesian_coords(start)
                     + float(i) / float(nb) *
                     (self._prim_rec.get_cartesian_coords(end)
                      - self._prim_rec.get_cartesian_coords(start))
                     for i in range(0, nb + 1)])
        return list_k_points, sym_point_labels

    def get_kpath_plot(self, **kwargs):
        """
        Gives the plot (as a matplotlib object) of the symmetry line path in
        the Brillouin Zone.

        Returns:
            `matplotlib` figure.

        ================  ==============================================================
        kwargs            Meaning
        ================  ==============================================================
        show              True to show the figure (Default).
        savefig           'abc.png' or 'abc.eps'* to save the figure to a file.
        ================  ==============================================================
        """
        import itertools
        import matplotlib.pyplot as plt
        from mpl_toolkits.mplot3d import axes3d

        def _plot_shape_skeleton(bz, style):
            for iface in range(len(bz)):
                for line in itertools.combinations(bz[iface], 2):
                    for jface in range(len(bz)):
                        if iface < jface and line[0] in bz[jface]\
                                and line[1] in bz[jface]:
                            ax.plot([line[0][0], line[1][0]],
                                    [line[0][1], line[1][1]],
                                    [line[0][2], line[1][2]], style)

        def _plot_lattice(lattice):
            vertex1 = lattice.get_cartesian_coords([0.0, 0.0, 0.0])
            vertex2 = lattice.get_cartesian_coords([1.0, 0.0, 0.0])
            ax.plot([vertex1[0], vertex2[0]], [vertex1[1], vertex2[1]],
                    [vertex1[2], vertex2[2]], color='g', linewidth=3)
            vertex2 = lattice.get_cartesian_coords([0.0, 1.0, 0.0])
            ax.plot([vertex1[0], vertex2[0]], [vertex1[1], vertex2[1]],
                    [vertex1[2], vertex2[2]], color='g', linewidth=3)
            vertex2 = lattice.get_cartesian_coords([0.0, 0.0, 1.0])
            ax.plot([vertex1[0], vertex2[0]], [vertex1[1], vertex2[1]],
                    [vertex1[2], vertex2[2]], color='g', linewidth=3)

        def _plot_kpath(kpath, lattice):
            for line in kpath['path']:
                for k in range(len(line) - 1):
                    vertex1 = lattice.get_cartesian_coords(kpath['kpoints']
                                                           [line[k]])
                    vertex2 = lattice.get_cartesian_coords(kpath['kpoints']
                                                           [line[k + 1]])
                    ax.plot([vertex1[0], vertex2[0]], [vertex1[1], vertex2[1]],
                            [vertex1[2], vertex2[2]], color='r', linewidth=3)

        def _plot_labels(kpath, lattice):
            for k in kpath['kpoints']:
                label = k
                if k.startswith("\\") or k.find("_") != -1:
                    label = "$" + k + "$"
                off = 0.01
                ax.text(lattice.get_cartesian_coords(kpath['kpoints'][k])[0]
                        + off,
                        lattice.get_cartesian_coords(kpath['kpoints'][k])[1]
                        + off,
                        lattice.get_cartesian_coords(kpath['kpoints'][k])[2]
                        + off,
                        label, color='b', size='25')
                ax.scatter([lattice.get_cartesian_coords(
                            kpath['kpoints'][k])[0]],
                           [lattice.get_cartesian_coords(
                            kpath['kpoints'][k])[1]],
                           [lattice.get_cartesian_coords(
                            kpath['kpoints'][k])[2]], color='b')
        fig = plt.figure()
        ax = axes3d.Axes3D(fig)
        _plot_lattice(self._prim_rec)
        _plot_shape_skeleton(self._prim_rec.get_wigner_seitz_cell(), '-k')
        _plot_kpath(self.kpath, self._prim_rec)
        _plot_labels(self.kpath, self._prim_rec)
        ax.axis("off")

        show = kwargs.pop("show", True)
        if show:
            plt.show()

        savefig = kwargs.pop("savefig", None)
        if savefig:
            fig.savefig(savefig)

        return fig

    def cubic(self):
        self.name = "CUB"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'X': np.array([0.0, 0.5, 0.0]),
                   'R': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.5, 0.0])}
        path = [["\Gamma", "X", "M", "\Gamma", "R", "X"], ["M", "R"]]
        return {'kpoints': kpoints, 'path': path}

    def fcc(self):
        self.name = "FCC"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'K': np.array([3.0 / 8.0, 3.0 / 8.0, 3.0 / 4.0]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'U': np.array([5.0 / 8.0, 1.0 / 4.0, 5.0 / 8.0]),
                   'W': np.array([0.5, 1.0 / 4.0, 3.0 / 4.0]),
                   'X': np.array([0.5, 0.0, 0.5])}
        path = [["\Gamma", "X", "W", "K",
                 "\Gamma", "L", "U", "W", "L", "K"], ["U", "X"]]
        return {'kpoints': kpoints, 'path': path}

    def bcc(self):
        self.name = "BCC"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'H': np.array([0.5, -0.5, 0.5]),
                   'P': np.array([0.25, 0.25, 0.25]),
                   'N': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "H", "N", "\Gamma", "P", "H"], ["P", "N"]]
        return {'kpoints': kpoints, 'path': path}

    def tet(self):
        self.name = "TET"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.5, 0.0]),
                   'R': np.array([0.0, 0.5, 0.5]),
                   'X': np.array([0.0, 0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "X", "M", "\Gamma", "Z", "R", "A", "Z"], ["X", "R"],
                ["M", "A"]]
        return {'kpoints': kpoints, 'path': path}

    def bctet1(self, c, a):
        self.name = "BCT1"
        eta = (1 + c ** 2 / a ** 2) / 4.0
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'M': np.array([-0.5, 0.5, 0.5]),
                   'N': np.array([0.0, 0.5, 0.0]),
                   'P': np.array([0.25, 0.25, 0.25]),
                   'X': np.array([0.0, 0.0, 0.5]),
                   'Z': np.array([eta, eta, -eta]),
                   'Z_1': np.array([-eta, 1 - eta, eta])}
        path = [["\Gamma", "X", "M", "\Gamma", "Z", "P", "N", "Z_1", "M"],
                ["X", "P"]]
        return {'kpoints': kpoints, 'path': path}

    def bctet2(self, c, a):
        self.name = "BCT2"
        eta = (1 + a ** 2 / c ** 2) / 4.0
        zeta = a ** 2 / (2 * c ** 2)
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'N': np.array([0.0, 0.5, 0.0]),
                   'P': np.array([0.25, 0.25, 0.25]),
                   '\Sigma': np.array([-eta, eta, eta]),
                   '\Sigma_1': np.array([eta, 1 - eta, -eta]),
                   'X': np.array([0.0, 0.0, 0.5]),
                   'Y': np.array([-zeta, zeta, 0.5]),
                   'Y_1': np.array([0.5, 0.5, -zeta]),
                   'Z': np.array([0.5, 0.5, -0.5])}
        path = [["\Gamma", "X", "Y", "\Sigma", "\Gamma", "Z",
                 "\Sigma_1", "N", "P", "Y_1", "Z"], ["X", "P"]]
        return {'kpoints': kpoints, 'path': path}

    def orc(self):
        self.name = "ORC"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'R': np.array([0.5, 0.5, 0.5]),
                   'S': np.array([0.5, 0.5, 0.0]),
                   'T': np.array([0.0, 0.5, 0.5]),
                   'U': np.array([0.5, 0.0, 0.5]),
                   'X': np.array([0.5, 0.0, 0.0]),
                   'Y': np.array([0.0, 0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "X", "S", "Y", "\Gamma",
                 "Z", "U", "R", "T", "Z"], ["Y", "T"], ["U", "X"], ["S", "R"]]
        return {'kpoints': kpoints, 'path': path}

    def orcf1(self, a, b, c):
        self.name = "ORCF1"
        zeta = (1 + a ** 2 / b ** 2 - a ** 2 / c ** 2) / 4
        eta = (1 + a ** 2 / b ** 2 + a ** 2 / c ** 2) / 4

        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.5, 0.5 + zeta, zeta]),
                   'A_1': np.array([0.5, 0.5 - zeta, 1 - zeta]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'T': np.array([1, 0.5, 0.5]),
                   'X': np.array([0.0, eta, eta]),
                   'X_1': np.array([1, 1 - eta, 1 - eta]),
                   'Y': np.array([0.5, 0.0, 0.5]),
                   'Z': np.array([0.5, 0.5, 0.0])}
        path = [["\Gamma", "Y", "T", "Z", "\Gamma", "X", "A_1", "Y"],
                ["T", "X_1"], ["X", "A", "Z"], ["L", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def orcf2(self, a, b, c):
        self.name = "ORCF2"
        phi = (1 + c ** 2 / b ** 2 - c ** 2 / a ** 2) / 4
        eta = (1 + a ** 2 / b ** 2 - a ** 2 / c ** 2) / 4
        delta = (1 + b ** 2 / a ** 2 - b ** 2 / c ** 2) / 4
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'C': np.array([0.5, 0.5 - eta, 1 - eta]),
                   'C_1': np.array([0.5, 0.5 + eta, eta]),
                   'D': np.array([0.5 - delta, 0.5, 1 - delta]),
                   'D_1': np.array([0.5 + delta, 0.5, delta]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'H': np.array([1 - phi, 0.5 - phi, 0.5]),
                   'H_1': np.array([phi, 0.5 + phi, 0.5]),
                   'X': np.array([0.0, 0.5, 0.5]),
                   'Y': np.array([0.5, 0.0, 0.5]),
                   'Z': np.array([0.5, 0.5, 0.0])}
        path = [["\Gamma", "Y", "C", "D", "X", "\Gamma",
                 "Z", "D_1", "H", "C"], ["C_1", "Z"], ["X", "H_1"], ["H", "Y"],
                ["L", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def orcf3(self, a, b, c):
        self.name = "ORCF3"
        zeta = (1 + a ** 2 / b ** 2 - a ** 2 / c ** 2) / 4
        eta = (1 + a ** 2 / b ** 2 + a ** 2 / c ** 2) / 4
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.5, 0.5 + zeta, zeta]),
                   'A_1': np.array([0.5, 0.5 - zeta, 1 - zeta]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'T': np.array([1, 0.5, 0.5]),
                   'X': np.array([0.0, eta, eta]),
                   'X_1': np.array([1, 1 - eta, 1 - eta]),
                   'Y': np.array([0.5, 0.0, 0.5]),
                   'Z': np.array([0.5, 0.5, 0.0])}
        path = [["\Gamma", "Y", "T", "Z", "\Gamma", "X", "A_1", "Y"],
                ["X", "A", "Z"], ["L", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def orci(self, a, b, c):
        self.name = "ORCI"
        zeta = (1 + a ** 2 / c ** 2) / 4
        eta = (1 + b ** 2 / c ** 2) / 4
        delta = (b ** 2 - a ** 2) / (4 * c ** 2)
        mu = (a ** 2 + b ** 2) / (4 * c ** 2)
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'L': np.array([-mu, mu, 0.5 - delta]),
                   'L_1': np.array([mu, -mu, 0.5 + delta]),
                   'L_2': np.array([0.5 - delta, 0.5 + delta, -mu]),
                   'R': np.array([0.0, 0.5, 0.0]),
                   'S': np.array([0.5, 0.0, 0.0]),
                   'T': np.array([0.0, 0.0, 0.5]),
                   'W': np.array([0.25, 0.25, 0.25]),
                   'X': np.array([-zeta, zeta, zeta]),
                   'X_1': np.array([zeta, 1 - zeta, -zeta]),
                   'Y': np.array([eta, -eta, eta]),
                   'Y_1': np.array([1 - eta, eta, -eta]),
                   'Z': np.array([0.5, 0.5, -0.5])}
        path = [["\Gamma", "X", "L", "T", "W", "R", "X_1", "Z",
                 "\Gamma", "Y", "S", "W"], ["L_1", "Y"], ["Y_1", "Z"]]
        return {'kpoints': kpoints, 'path': path}

    def orcc(self, a, b, c):
        self.name = "ORCC"
        zeta = (1 + a ** 2 / b ** 2) / 4
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([zeta, zeta, 0.5]),
                   'A_1': np.array([-zeta, 1 - zeta, 0.5]),
                   'R': np.array([0.0, 0.5, 0.5]),
                   'S': np.array([0.0, 0.5, 0.0]),
                   'T': np.array([-0.5, 0.5, 0.5]),
                   'X': np.array([zeta, zeta, 0.0]),
                   'X_1': np.array([-zeta, 1 - zeta, 0.0]),
                   'Y': np.array([-0.5, 0.5, 0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "X", "S", "R", "A", "Z",
                 "\Gamma", "Y", "X_1", "A_1", "T", "Y"], ["Z", "T"]]
        return {'kpoints': kpoints, 'path': path}

    def hex(self):
        self.name = "HEX"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.0, 0.0, 0.5]),
                   'H': np.array([1.0 / 3.0, 1.0 / 3.0, 0.5]),
                   'K': np.array([1.0 / 3.0, 1.0 / 3.0, 0.0]),
                   'L': np.array([0.5, 0.0, 0.5]),
                   'M': np.array([0.5, 0.0, 0.0])}
        path = [["\Gamma", "M", "K", "\Gamma", "A", "L", "H", "A"], ["L", "M"],
                ["K", "H"]]
        return {'kpoints': kpoints, 'path': path}

    def rhl1(self, alpha):
        self.name = "RHL1"
        eta = (1 + 4 * cos(alpha)) / (2 + 4 * cos(alpha))
        nu = 3.0 / 4.0 - eta / 2.0
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'B': np.array([eta, 0.5, 1.0 - eta]),
                   'B_1': np.array([1.0 / 2.0, 1.0 - eta, eta - 1.0]),
                   'F': np.array([0.5, 0.5, 0.0]),
                   'L': np.array([0.5, 0.0, 0.0]),
                   'L_1': np.array([0.0, 0.0, -0.5]),
                   'P': np.array([eta, nu, nu]),
                   'P_1': np.array([1.0 - nu, 1.0 - nu, 1.0 - eta]),
                   'P_2': np.array([nu, nu, eta - 1.0]),
                   'Q': np.array([1.0 - nu, nu, 0.0]),
                   'X': np.array([nu, 0.0, -nu]),
                   'Z': np.array([0.5, 0.5, 0.5])}
        path = [["\Gamma", "L", "B_1"], ["B", "Z", "\Gamma", "X"],
                ["Q", "F", "P_1", "Z"], ["L", "P"]]
        return {'kpoints': kpoints, 'path': path}

    def rhl2(self, alpha):
        self.name = "RHL2"
        eta = 1 / (2 * tan(alpha / 2.0) ** 2)
        nu = 3.0 / 4.0 - eta / 2.0
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'F': np.array([0.5, -0.5, 0.0]),
                   'L': np.array([0.5, 0.0, 0.0]),
                   'P': np.array([1 - nu, -nu, 1 - nu]),
                   'P_1': np.array([nu, nu - 1.0, nu - 1.0]),
                   'Q': np.array([eta, eta, eta]),
                   'Q_1': np.array([1.0 - eta, -eta, -eta]),
                   'Z': np.array([0.5, -0.5, 0.5])}
        path = [["\Gamma", "P", "Z", "Q", "\Gamma",
                 "F", "P_1", "Q_1", "L", "Z"]]
        return {'kpoints': kpoints, 'path': path}

    def mcl(self, b, c, beta):
        self.name = "MCL"
        eta = (1 - b * cos(beta) / c) / (2 * sin(beta) ** 2)
        nu = 0.5 - eta * c * cos(beta) / b
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'A': np.array([0.5, 0.5, 0.0]),
                   'C': np.array([0.0, 0.5, 0.5]),
                   'D': np.array([0.5, 0.0, 0.5]),
                   'D_1': np.array([0.5, 0.5, -0.5]),
                   'E': np.array([0.5, 0.5, 0.5]),
                   'H': np.array([0.0, eta, 1.0 - nu]),
                   'H_1': np.array([0.0, 1.0 - eta, nu]),
                   'H_2': np.array([0.0, eta, -nu]),
                   'M': np.array([0.5, eta, 1.0 - nu]),
                   'M_1': np.array([0.5, 1 - eta, nu]),
                   'M_2': np.array([0.5, 1 - eta, nu]),
                   'X': np.array([0.0, 0.5, 0.0]),
                   'Y': np.array([0.0, 0.0, 0.5]),
                   'Y_1': np.array([0.0, 0.0, -0.5]),
                   'Z': np.array([0.5, 0.0, 0.0])}
        path = [["\Gamma", "Y", "H", "C", "E", "M_1", "A", "X", "H_1"],
                ["M", "D", "Z"], ["Y", "D"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc1(self, a, b, c, alpha):
        self.name = "MCLC1"
        zeta = (2 - b * cos(alpha) / c) / (4 * sin(alpha) ** 2)
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        psi = 0.75 - a ** 2 / (4 * b ** 2 * sin(alpha) ** 2)
        phi = psi + (0.75 - psi) * b * cos(alpha) / c
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'F': np.array([1 - zeta, 1 - zeta, 1 - eta]),
                   'F_1': np.array([zeta, zeta, eta]),
                   'F_2': np.array([-zeta, -zeta, 1 - eta]),
                   #'F_3': np.array([1 - zeta, -zeta, 1 - eta]),
                   'I': np.array([phi, 1 - phi, 0.5]),
                   'I_1': np.array([1 - phi, phi - 1, 0.5]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'X': np.array([1 - psi, psi - 1, 0.0]),
                   'X_1': np.array([psi, 1 - psi, 0.0]),
                   'X_2': np.array([psi - 1, -psi, 0.0]),
                   'Y': np.array([0.5, 0.5, 0.0]),
                   'Y_1': np.array([-0.5, -0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "L", "I"], ["I_1", "Z", "F_1"],
                ["Y", "X_1"], ["X", "\Gamma", "N"], ["M", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc2(self, a, b, c, alpha):
        self.name = "MCLC2"
        zeta = (2 - b * cos(alpha) / c) / (4 * sin(alpha) ** 2)
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        psi = 0.75 - a ** 2 / (4 * b ** 2 * sin(alpha) ** 2)
        phi = psi + (0.75 - psi) * b * cos(alpha) / c
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'F': np.array([1 - zeta, 1 - zeta, 1 - eta]),
                   'F_1': np.array([zeta, zeta, eta]),
                   'F_2': np.array([-zeta, -zeta, 1 - eta]),
                   'F_3': np.array([1 - zeta, -zeta, 1 - eta]),
                   'I': np.array([phi, 1 - phi, 0.5]),
                   'I_1': np.array([1 - phi, phi - 1, 0.5]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'X': np.array([1 - psi, psi - 1, 0.0]),
                   'X_1': np.array([psi, 1 - psi, 0.0]),
                   'X_2': np.array([psi - 1, -psi, 0.0]),
                   'Y': np.array([0.5, 0.5, 0.0]),
                   'Y_1': np.array([-0.5, -0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "L", "I"], ["I_1", "Z", "F_1"],
                ["N", "\Gamma", "M"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc3(self, a, b, c, alpha):
        self.name = "MCLC3"
        mu = (1 + b ** 2 / a ** 2) / 4.0
        delta = b * c * cos(alpha) / (2 * a ** 2)
        zeta = mu - 0.25 + (1 - b * cos(alpha) / c)\
            / (4 * sin(alpha) ** 2)
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        phi = 1 + zeta - 2 * mu
        psi = eta - 2 * delta
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'F': np.array([1 - phi, 1 - phi, 1 - psi]),
                   'F_1': np.array([phi, phi - 1, psi]),
                   'F_2': np.array([1 - phi, -phi, 1 - psi]),
                   'H': np.array([zeta, zeta, eta]),
                   'H_1': np.array([1 - zeta, -zeta, 1 - eta]),
                   'H_2': np.array([-zeta, -zeta, 1 - eta]),
                   'I': np.array([0.5, -0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'X': np.array([0.5, -0.5, 0.0]),
                   'Y': np.array([mu, mu, delta]),
                   'Y_1': np.array([1 - mu, -mu, -delta]),
                   'Y_2': np.array([-mu, -mu, -delta]),
                   'Y_3': np.array([mu, mu - 1, delta]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "H", "Z", "I", "F_1"],
                ["H_1", "Y_1", "X", "\Gamma", "N"], ["M", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc4(self, a, b, c, alpha):
        self.name = "MCLC4"
        mu = (1 + b ** 2 / a ** 2) / 4.0
        delta = b * c * cos(alpha) / (2 * a ** 2)
        zeta = mu - 0.25 + (1 - b * cos(alpha) / c)\
            / (4 * sin(alpha) ** 2)
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        phi = 1 + zeta - 2 * mu
        psi = eta - 2 * delta
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'F': np.array([1 - phi, 1 - phi, 1 - psi]),
                   'F_1': np.array([phi, phi - 1, psi]),
                   'F_2': np.array([1 - phi, -phi, 1 - psi]),
                   'H': np.array([zeta, zeta, eta]),
                   'H_1': np.array([1 - zeta, -zeta, 1 - eta]),
                   'H_2': np.array([-zeta, -zeta, 1 - eta]),
                   'I': np.array([0.5, -0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'X': np.array([0.5, -0.5, 0.0]),
                   'Y': np.array([mu, mu, delta]),
                   'Y_1': np.array([1 - mu, -mu, -delta]),
                   'Y_2': np.array([-mu, -mu, -delta]),
                   'Y_3': np.array([mu, mu - 1, delta]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "H", "Z", "I"],
                ["H_1", "Y_1", "X", "\Gamma", "N"], ["M", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def mclc5(self, a, b, c, alpha):
        self.name = "MCLC5"
        zeta = (b ** 2 / a ** 2 + (1 - b * cos(alpha) / c)
                / sin(alpha) ** 2) / 4
        eta = 0.5 + 2 * zeta * c * cos(alpha) / b
        mu = eta / 2 + b ** 2 / (4 * a ** 2) \
            - b * c * cos(alpha) / (2 * a ** 2)
        nu = 2 * mu - zeta
        rho = 1 - zeta * a ** 2 / b ** 2
        omega = (4 * nu - 1 - b ** 2 * sin(alpha) ** 2 / a ** 2)\
            * c / (2 * b * cos(alpha))
        delta = zeta * c * cos(alpha) / b + omega / 2 - 0.25
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'F': np.array([nu, nu, omega]),
                   'F_1': np.array([1 - nu, 1 - nu, 1 - omega]),
                   'F_2': np.array([nu, nu - 1, omega]),
                   'H': np.array([zeta, zeta, eta]),
                   'H_1': np.array([1 - zeta, -zeta, 1 - eta]),
                   'H_2': np.array([-zeta, -zeta, 1 - eta]),
                   'I': np.array([rho, 1 - rho, 0.5]),
                   'I_1': np.array([1 - rho, rho - 1, 0.5]),
                   'L': np.array([0.5, 0.5, 0.5]),
                   'M': np.array([0.5, 0.0, 0.5]),
                   'N': np.array([0.5, 0.0, 0.0]),
                   'N_1': np.array([0.0, -0.5, 0.0]),
                   'X': np.array([0.5, -0.5, 0.0]),
                   'Y': np.array([mu, mu, delta]),
                   'Y_1': np.array([1 - mu, -mu, -delta]),
                   'Y_2': np.array([-mu, -mu, -delta]),
                   'Y_3': np.array([mu, mu - 1, delta]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["\Gamma", "Y", "F", "L", "I"], ["I_1", "Z", "H", "F_1"],
                ["H_1", "Y_1", "X", "\Gamma", "N"], ["M", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def tria(self):
        self.name = "TRI1a"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'L': np.array([0.5, 0.5, 0.0]),
                   'M': np.array([0.0, 0.5, 0.5]),
                   'N': np.array([0.5, 0.0, 0.5]),
                   'R': np.array([0.5, 0.5, 0.5]),
                   'X': np.array([0.5, 0.0, 0.0]),
                   'Y': np.array([0.0, 0.5, 0.0]),
                   'Z': np.array([0.0, 0.0, 0.5])}
        path = [["X", "\Gamma", "Y"], ["L", "\Gamma", "Z"],
                ["N", "\Gamma", "M"], ["R", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}

    def trib(self):
        self.name = "TRI1b"
        kpoints = {'\Gamma': np.array([0.0, 0.0, 0.0]),
                   'L': np.array([0.5, -0.5, 0.0]),
                   'M': np.array([0.0, 0.0, 0.5]),
                   'N': np.array([-0.5, -0.5, 0.5]),
                   'R': np.array([0.0, -0.5, 0.5]),
                   'X': np.array([0.0, -0.5, 0.0]),
                   'Y': np.array([0.5, 0.0, 0.0]),
                   'Z': np.array([-0.5, 0.0, 0.5])}
        path = [["X", "\Gamma", "Y"], ["L", "\Gamma", "Z"],
                ["N", "\Gamma", "M"], ["R", "\Gamma"]]
        return {'kpoints': kpoints, 'path': path}
Ejemplo n.º 29
0
class SymmetryFinderTest(unittest.TestCase):

    def setUp(self):
        p = Poscar.from_file(os.path.join(test_dir, 'POSCAR'))
        self.structure = p.structure
        self.sg = SymmetryFinder(self.structure, 0.001)
        parser = CifParser(os.path.join(test_dir, 'Li10GeP2S12.cif'))
        self.disordered_structure = parser.get_structures()[0]
        self.disordered_sg = SymmetryFinder(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 = SymmetryFinder(s, 0.001)
        parser = CifParser(os.path.join(test_dir, 'Graphite.cif'))
        graphite = parser.get_structures()[0]
        graphite.add_site_property("magmom", [0.1] * len(graphite))
        self.sg4 = SymmetryFinder(graphite, 0.001)

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

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

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

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

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

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

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

    def test_get_refined_structure(self):
        for a in self.sg.get_refined_structure().lattice.angles:
            self.assertEqual(a, 90)
        refined = self.disordered_sg.get_refined_structure()
        for a in refined.lattice.angles:
            self.assertEqual(a, 90)
        self.assertEqual(refined.lattice.a, refined.lattice.b)
        parser = CifParser(os.path.join(test_dir, 'Li2O.cif'))
        s = parser.get_structures()[0]
        sg = SymmetryFinder(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(map(len, symm_struct.equivalent_sites), [16,4,8,4,2,8,8,8])
        s1 = symm_struct.equivalent_sites[1][1]
        s2 = symm_struct[symm_struct.equivalent_indices[1][1]]
        self.assertEqual(s1, s2)
        self.assertEqual(self.sg4.get_symmetrized_structure()[0].magmom, 0.1)

    def test_find_primitive(self):
        """
        F m -3 m Li2O testing of converting to primitive cell
        """
        parser = CifParser(os.path.join(test_dir, 'Li2O.cif'))
        structure = parser.get_structures(False)[0]
        s = SymmetryFinder(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.assertEquals(len(grid), 216)
        self.assertAlmostEquals(grid[1][0][0], 0.1)
        self.assertAlmostEquals(grid[1][0][1], 0.0)
        self.assertAlmostEquals(grid[1][0][2], 0.0)
        self.assertEquals(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(structure, symprec=1e-2)
        conv = s.get_conventional_standard_structure()
        self.assertAlmostEqual(conv.lattice.alpha, 90)
        self.assertAlmostEqual(conv.lattice.beta, 117.53832420192903)
        self.assertAlmostEqual(conv.lattice.gamma, 90)
        self.assertAlmostEqual(conv.lattice.a, 14.033435583000625)
        self.assertAlmostEqual(conv.lattice.b, 3.96052850731)
        self.assertAlmostEqual(conv.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'rhomb_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(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 = SymmetryFinder(structure, symprec=1e-2)
        prim = s.get_primitive_standard_structure()
        self.assertAlmostEqual(prim.lattice.alpha, 63.579155761999999)
        self.assertAlmostEqual(prim.lattice.beta, 116.42084423747779)
        self.assertAlmostEqual(prim.lattice.gamma, 148.47965136208569)
        self.assertAlmostEqual(prim.lattice.a, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.b, 7.2908007159612325)
        self.assertAlmostEqual(prim.lattice.c, 6.8743926325200002)

        parser = CifParser(os.path.join(test_dir, 'rhomb_1170.cif'))
        structure = parser.get_structures(False)[0]
        s = SymmetryFinder(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)