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!")
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!")
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
def test_apply_transformation(self): trans = MagOrderingTransformation({"Fe": 5}) p = Poscar.from_file(os.path.join(test_dir, 'POSCAR.LiFePO4'), check_for_POTCAR=False) s = p.structure alls = trans.apply_transformation(s, 10) self.assertEqual(len(alls), 3) f = SymmetryFinder(alls[0]["structure"], 0.1) self.assertEqual(f.get_spacegroup_number(), 31) model = IsingModel(5, 5) trans = MagOrderingTransformation({"Fe": 5}, energy_model=model) alls2 = trans.apply_transformation(s, 10) #Ising model with +J penalizes similar neighbor magmom. self.assertNotEqual(alls[0]["structure"], alls2[0]["structure"]) self.assertEqual(alls[0]["structure"], alls2[2]["structure"]) from pymatgen.io.smartio import read_structure s = read_structure(os.path.join(test_dir, 'Li2O.cif')) #Li2O doesn't have magnetism of course, but this is to test the # enumeration. trans = MagOrderingTransformation({"Li+": 1}, max_cell_size=3) alls = trans.apply_transformation(s, 100) self.assertEqual(len(alls), 10)
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 __init__(self, structures, spacegroup, symm_prec=0.1): """ Args: structures: Sequence of structures to test. spacegroup: A spacegroup to test the structures. symm_prec: The symmetry precision to test with. """ structure_symm = {} self.symm_prec = symm_prec self.spacegroup = spacegroup logger.debug("Computing spacegroups...") for i, s in enumerate(structures): finder = SymmetryFinder(s, symm_prec) structure_symm[s] = finder.get_spacegroup_number() logger.debug("Structure {} has spacegroup {}" .format(i, structure_symm[s])) sorted_structures = sorted(structures, key=lambda s: -structure_symm[s]) unique_groups = [] for i, group in itertools.groupby(sorted_structures, key=lambda s: structure_symm[s]): logger.debug("Processing group of structures with sg number {}" .format(i)) subgroups = self._fit_group(group) unique_groups.extend(subgroups) self.unique_groups = unique_groups
def get_primitive(fname): poscar = Poscar.from_file(fname) finder = SymmetryFinder(poscar.structure) spg_num = finder.get_spacegroup_number() primitive = finder.get_primitive_standard_structure() return spg_num, primitive
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
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
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. """ f = SymmetryFinder(structure, 0.1) return "{} {}".format(f.get_spacegroup_number(), structure.composition.reduced_formula)
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))
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'))
precision = 0.01 same = 0 different = 0 for doc in structures.find({"prototype_id": {"$exists": True}, "spacegroup.number": {"$gt": 100}}, fields={"prototype_id": 1, "structure": 1}): proto_doc = prototypes.find({"_id": doc["prototype_id"]}, fields={"structure": 1, "wyckoff_sites": 1})[0] proto_pretidy = Structure.from_dict(proto_doc["structure"]) sg = SymmetryFinder(proto_pretidy, precision, -1) proto = structure_tidy.structure_tidy(sg.get_primitive_standard_structure()) sg_proto = SymmetryFinder(proto, precision, -1) proto_wyckoff = prototype.get_wyckoff_sites(sg_proto) str_pretidy = prototype.create_prototype(Structure.from_dict(doc["structure"])) sg = SymmetryFinder(str_pretidy, precision, -1) str = structure_tidy.structure_tidy(sg.get_primitive_standard_structure()) sg_str = SymmetryFinder(str, precision, -1) str_wyckoff = prototype.get_wyckoff_sites(sg_str) # if str_wyckoff != proto_wyckoff: # print("Wyckoff sites not equal!") # print("proto: {}".format(proto_wyckoff)) # print("structure: {}".format(str_wyckoff)) # splpy.util.write_structures([proto, str], ['proto', 'str']) if str_wyckoff != proto_wyckoff: different += 1 print("{} {}".format(str_wyckoff == proto_wyckoff, sg_str.get_spacegroup_number())) else: same += 1 print("Same: {}, Different: {}, Percent: {}".format(same, different, float(different)/float(same+different)))
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))
def get_sg_info(ss): finder = SymmetryFinder(Structure.from_sites(ss), self.symm_prec) sgnum = finder.get_spacegroup_number() return sgnum
def inter_descript_gen(cif_file, collection, prune_args): """ Generates the interstitial descriptor values for the structures in input cif directory and store them into the database supplied Args: cif_file: cif File collection: Mongo database collection prune_ars: List of keywords to prune the interstitials a) anion: Only the interstitial sites that can be occupied by the anion are kept a) cation: Only the interstitial sites that can be occupied by the smallest cation are kept c) [El, oxi_state]: Only the interstitial sites that can be occupied by the input ion are kept Ex: ['Li', 1] """ # Use the number as struct identifier # Store the remaining string as formula print cif_file dir, filen = os.path.split(cif_file) print filen name = os.path.splitext(filen)[0] item = name.split('--') key = item[0] inter_descript_dict = {'key': key, 'formula': ''.join(item[1].split())} FAIL = 0 SUCC = 1 #read the file to pymatgen struct try: struct = CifParser(cif_file).get_structures(False)[0] except: print 'reading ', cif_file, ' failed' return FAIL symm_finder = SymmetryFinder(struct) inter_descript_dict['structure'] = struct inter_descript_dict['crystal_system'] = symm_finder.get_crystal_system() inter_descript_dict['spacegroup_no'] = symm_finder.get_spacegroup_number() no_symmops = len(symm_finder.get_symmetry_operations()) inter_descript_dict['no_symmops'] = no_symmops try: struct_val_rad = StructWithValenceIonicRadius(struct) valences = struct_val_rad.valences.values() valences.sort() anion_cation_charge_ratio = abs(valences[-1] / valences[0]) radii = struct_val_rad.radii.values() radii.sort() anion_cation_radii_ratio = radii[-1] / radii[0] except: print inter_descript_dict['formula'] print "Unable to identify radii and valences" return FAIL inter_descript_dict['charge_ratio'] = anion_cation_charge_ratio inter_descript_dict['radius_ratio'] = anion_cation_radii_ratio try: inter = Interstitial(struct_val_rad) except: print inter_descript_dict['formula'] print 'interstitial not generated' return FAIL if prune_args[0] == "cation": inter.radius_prune_defectsites( radii[0]) #smallest element in the structure elif prune_args[0] == "anion": inter.radius_prune_defectsites( radii[-1]) #largest element in the structure else: el = prune_args[0] oxi_state = prune_args[1] inter.prune_defectsites(el, oxi_state) inter.prune_close_defectsites() if inter.defectsite_count() > 10: inter.reduce_defectsites() no_inter = inter.defectsite_count() inter_descript_dict['no_inter'] = no_inter #print >>sys.stderr, inter_descript_dict[key]['formula'], "No. of inter", no_inter #Create a list storing a dictionary of properties for each interstitial inter_list = [] for i in range(no_inter): inter_dict = {} inter_dict['coord_no'] = inter.get_defectsite_coordination_number(i) inter_dict['coord_el'] = list(inter.get_coordinated_elements(i)) inter_dict['radius'] = inter.get_radius(i) inter_dict['coord_chrg_sum'] = inter.get_coordsites_charge_sum(i) inter_list.append(inter_dict) inter_descript_dict['interstitials'] = inter_list descriptor_id = collection.insert(inter_descript_dict) return descriptor_id
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
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))
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
def get_energy(self, structure): f = SymmetryFinder(structure, symprec=self.symprec, angle_tolerance=self.angle_tolerance) return -f.get_spacegroup_number()
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
def get_sg(s): finder = SymmetryFinder(s, symprec=self._symprec) return finder.get_spacegroup_number()
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
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
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)
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)
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)
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
def inter_descript_gen(cif_file, prune_args): # Use the number as struct identifier # Store the remaining string as formula print cif_file dir, filen = os.path.split(cif_file) print filen name = os.path.splitext(filen)[0] item = name.split('--') key = item[0] inter_descript_dict = {'formula': ''.join(item[1].split())} #read the file to pymatgen struct try: struct = CifParser(cif_file).get_structures(False)[0] except: print 'reading ', cif_file, ' failed' return None, filen symm_finder = SymmetryFinder(struct, symprec=1e-1) inter_descript_dict['crystal_system'] = symm_finder.get_crystal_system() inter_descript_dict['spacegroup_no'] = symm_finder.get_spacegroup_number() no_symmops = len(symm_finder.get_symmetry_operations()) inter_descript_dict['no_symmops'] = no_symmops try: struct_val_rad = StructWithValenceIonicRadius(struct) except: print inter_descript_dict['formula'] print "Unable to identify radii and valences" return None, filen try: inter = Interstitial(struct_val_rad) except: print inter_descript_dict['formula'] print 'interstitial not generated' return None, filen valences = inter.struct_valences.values() valences.sort() try: anion_cation_charge_ratio = abs(valences[-1] / valences[0]) except: #BVAnalyzer fails sometimes and valences are set to 0 print inter_descript_dict['formula'] print valences anion_cation_charge_ratio = 0 inter_descript_dict['charge_ratio'] = anion_cation_charge_ratio radii = inter.struct_radii.values() radii.sort() try: anion_cation_radii_ratio = radii[-1] / radii[0] except: anion_cation_radii_ratio = 0 inter_descript_dict['radius_ratio'] = anion_cation_radii_ratio if prune_args[0] == "cation": inter.radius_prune_defectsites( radii[0]) #smallest element in the structure elif prune_args[0] == "anion": inter.radius_prune_defectsites( radii[-1]) #largest element in the structure else: el = prune_args[0] oxi_state = prune_args[1] print el, oxi_state inter.prune_defectsites(el, oxi_state) inter.prune_close_defectsites() if inter.defectsite_count() > 10: # Something wrong with the symmetry reduction of defects. # Ignoring the outlier return None, filen inter.reduce_defectsites() no_inter = inter.defectsite_count() if no_inter > 5: print "Tag:", key, inter_descript_dict['formula'], no_inter inter_descript_dict['no_inter'] = no_inter #print >>sys.stderr, inter_descript_dict[key]['formula'], "No. of inter", no_inter #ife = InterstitialFormationEnergy(inter) #Create a list storing a dictionary of properties for each interstitial inter_list = [] for i in range(no_inter): inter_dict = {} inter_dict['coords'] = inter.get_defectsite(i).coords inter_dict['coord_no'] = inter.get_defectsite_coordination_number(i) inter_dict['coord_el'] = list(inter.get_coordinated_elements(i)) inter_dict['radius'] = inter.get_radius(i) inter_dict['coord_chrg_sum'] = inter.get_coordsites_charge_sum(i) inter_list.append(inter_dict) inter_descript_dict['interstitials'] = inter_list return key, inter_descript_dict