def interpolate_poscar(self, fw_spec): # make folder for poscar interpolation start and end structure files. interpolate_folder = 'interpolate' if not os.path.exists(os.path.join(os.getcwd(), interpolate_folder)): os.makedirs(os.path.join(os.getcwd(), interpolate_folder)) # use method of GrabFilesFromCalcLoc to grab files from previous locations. CopyFilesFromCalcLoc(calc_dir=None, calc_loc=self["start"], filenames=["CONTCAR"], name_prepend=interpolate_folder + os.sep, name_append="_0").run_task(fw_spec=fw_spec) CopyFilesFromCalcLoc(calc_dir=None, calc_loc=self["end"], filenames=["CONTCAR"], name_prepend=interpolate_folder + os.sep, name_append="_1").run_task(fw_spec=fw_spec) # assuming first calc_dir is polar structure for ferroelectric search s1 = Structure.from_file(os.path.join(interpolate_folder, "CONTCAR_0")) s2 = Structure.from_file(os.path.join(interpolate_folder, "CONTCAR_1")) structs = s1.interpolate(s2, self["nimages"], interpolate_lattices=True, autosort_tol=self.get("autosort_tol", 0.0)) # save only the interpolation needed for this run i = self.get("this_image") return structs[i]
def test_to_from_file_string(self): for fmt in ["cif", "json", "poscar", "cssr"]: s = self.struct.to(fmt=fmt) self.assertIsNotNone(s) ss = IStructure.from_str(s, fmt=fmt) self.assertArrayAlmostEqual( ss.lattice.lengths_and_angles, self.struct.lattice.lengths_and_angles, decimal=5) self.assertArrayAlmostEqual(ss.frac_coords, self.struct.frac_coords) self.assertIsInstance(ss, IStructure) self.struct.to(filename="POSCAR.testing") self.assertTrue(os.path.exists("POSCAR.testing")) os.remove("POSCAR.testing") self.struct.to(filename="Si_testing.yaml") self.assertTrue(os.path.exists("Si_testing.yaml")) s = Structure.from_file("Si_testing.yaml") self.assertEqual(s, self.struct) os.remove("Si_testing.yaml") self.struct.to(filename="POSCAR.testing.gz") s = Structure.from_file("POSCAR.testing.gz") self.assertEqual(s, self.struct) os.remove("POSCAR.testing.gz")
def relax(dim=2, submit=True, force_overwrite=False): """ Writes input files and (optionally) submits a self-consistent relaxation. Should be run before pretty much anything else, in order to get the right energy and structure of the material. Args: dim (int): 2 for relaxing a 2D material, 3 for a 3D material. submit (bool): Whether or not to submit the job. force_overwrite (bool): Whether or not to overwrite files if an already converged vasprun.xml exists in the directory. """ if force_overwrite or not utl.is_converged(os.getcwd()): directory = os.getcwd().split('/')[-1] # vdw_kernel.bindat file required for VDW calculations. if VDW_KERNEL: os.system('cp {} .'.format(VDW_KERNEL)) # KPOINTS Kpoints.automatic_density(Structure.from_file('POSCAR'), 1000).write_file('KPOINTS') # INCAR INCAR_DICT.update( {'MAGMOM': utl.get_magmom_string(Structure.from_file('POSCAR'))} ) Incar.from_dict(INCAR_DICT).write_file('INCAR') # POTCAR utl.write_potcar() # Special tasks only performed for 2D materials. if dim == 2: # Ensure 20A interlayer vacuum utl.ensure_vacuum(Structure.from_file('POSCAR'), 20) # Remove all z k-points. kpts_lines = open('KPOINTS').readlines() with open('KPOINTS', 'w') as kpts: for line in kpts_lines[:3]: kpts.write(line) kpts.write(kpts_lines[3].split()[0] + ' ' + kpts_lines[3].split()[1] + ' 1') # Submission script if dim == 2: binary = VASP_TWOD_BIN elif dim == 3: binary = VASP_STD_BIN if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob(directory, 1, 16, '800mb', '6:00:00', binary) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob(directory, 16, '800mb', '6:00:00', binary) submission_command = 'sbatch runjob' if submit: os.system(submission_command)
def setUp(self): """Loading structures before tests""" #print "TestConnectivityMethods:setUp_" print "Loading structures from file" self.fe_structure = Structure.from_file('Fe.cif', True, True) self.caf2_structure = Structure.from_file('CaF2.cif', True, True) self.licoo2_structure = Structure.from_file('LiCoO2.cif', True, True) print "Structures from file loaded"
def test_getinterpolatedposcar(self): nimages = 5 this_image = 1 autosort_tol = 0.5 fw1 = Firework([CopyVaspOutputs(calc_dir=self.static_outdir, contcar_to_poscar=False, additional_files=["CONTCAR"]), PassCalcLocs(name="fw1")], name="fw1") fw2 = Firework([CopyVaspOutputs(calc_dir=self.opt_outdir, contcar_to_poscar=False, additional_files=["CONTCAR"]), PassCalcLocs(name="fw2")], name="fw2") fw3 = Firework([GetInterpolatedPOSCAR(start="fw1", end="fw2", this_image=this_image, nimages=nimages, autosort_tol=autosort_tol), PassCalcLocs(name="fw3")], name="fw3", parents=[fw1, fw2]) fw4 = Firework([PassCalcLocs(name="fw4")], name="fw4", parents=fw3) wf = Workflow([fw1, fw2, fw3, fw4]) self.lp.add_wf(wf) rapidfire(self.lp) fw4 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw4"})[0]) calc_locs = fw4.spec["calc_locs"] self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR")) self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_0")) self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_1")) struct_start = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_0") struct_end = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_1") struct_inter = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR") structs = struct_start.interpolate(struct_end, nimages, interpolate_lattices=True, autosort_tol=autosort_tol) # Check x of 1st site. self.assertAlmostEqual(structs[this_image][1].coords[0], struct_inter[1].coords[0]) # Check c lattice parameter self.assertAlmostEqual(structs[this_image].lattice.abc[0], struct_inter.lattice.abc[0])
def setUp(self): self.cscl = self.get_structure("CsCl") self.lifepo4 = self.get_structure("LiFePO4") self.tei = Structure.from_file(get_path("icsd_TeI.cif"), primitive=False) self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50), ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]])
def setUp(self): """Loading structures before tests""" print "Loading structures from file" self.fe_structure = Structure.from_file('Fe.cif', True, True) self.caf2_structure = Structure.from_file('CaF2.cif', True, True) self.licoo2_structure = Structure.from_file('LiCoO2.cif', True, True) self.fe_finder = econ.EffectiveCoordFinder(self.fe_structure) self.caf2_finder = econ.EffectiveCoordFinder(self.caf2_structure) self.licoo2_finder = econ.EffectiveCoordFinder(self.licoo2_structure) print "Structures from file loaded"
def setUp(self): self.cscl = Structure.from_spacegroup( "Pm-3m", Lattice.cubic(4.2), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.lifepo4 = self.get_structure("LiFePO4") self.tei = Structure.from_file(get_path("icsd_TeI.cif"), primitive=False) self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50), ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]]) self.graphite = self.get_structure("Graphite")
def get_competing_phases(): """ Collect the species to which the material might decompose to. Returns: A list of phases as tuples formatted as [(formula_1, Materials_Project_ID_1), (formula_2, Materials_Project_ID_2), ...] """ composition = Structure.from_file('POSCAR').composition try: energy = Vasprun('vasprun.xml').final_energy except: energy = 100 # The function can work without a vasprun.xml entries = MPR.get_entries_in_chemsys([elt.symbol for elt in composition]) my_entry = ComputedEntry(composition, energy) entries.append(my_entry) #pda = PDAnalyzer(PhaseDiagram(entries)) pda = PhaseDiagram(entries) decomp = pda.get_decomp_and_e_above_hull(my_entry, allow_negative=True) competing_phases = [(entry.composition.reduced_formula, entry.entry_id) for entry in decomp[0]] return competing_phases
def test_substitute(self): structure = Structure.from_file(os.path.join(os.path.dirname(__file__), "..", "..", "..", "test_files", "Li2O.cif")) molecule = FunctionalGroups["methyl"] structure_copy = copy.deepcopy(structure) structure_copy_graph = copy.deepcopy(structure) sg = StructureGraph.with_local_env_strategy(structure, MinimumDistanceNN()) sg_copy = copy.deepcopy(sg) # Ensure that strings and molecules lead to equivalent substitutions sg.substitute_group(1, molecule, MinimumDistanceNN) sg_copy.substitute_group(1, "methyl", MinimumDistanceNN) self.assertEqual(sg, sg_copy) # Ensure that the underlying structure has been modified as expected structure_copy.substitute(1, "methyl") self.assertEqual(structure_copy, sg.structure) # Test inclusion of graph dictionary graph_dict = {(0, 1): {"weight": 0.5}, (0, 2): {"weight": 0.5}, (0, 3): {"weight": 0.5}, } sg_with_graph = StructureGraph.with_local_env_strategy(structure_copy_graph, MinimumDistanceNN()) sg_with_graph.substitute_group(1, "methyl", MinimumDistanceNN, graph_dict=graph_dict) edge = sg_with_graph.graph.get_edge_data(11, 13)[0] self.assertEqual(edge["weight"], 0.5)
def __init__(self, custom_interpreter=None, custom_test_structures=None): p = os.path.join(module_dir, "..", "test_structures", "human_interpreter.yaml") t = os.path.join(module_dir, "..", "test_structures") interpreter = custom_interpreter if custom_interpreter else p test_structures = custom_test_structures if custom_test_structures else t with open(interpreter) as f: hi = yaml.load(f) for k in hi.keys(): hi[k].append(len(hi[k])) if custom_test_structures: find_structure = glob.glob(os.path.join(test_structures, k + "*")) else: find_structure = glob.glob(os.path.join(test_structures, "*", k+"*")) if len(find_structure)==0: continue s = Structure.from_file(find_structure[0]) s.remove_oxidation_states() hi[k].append(s) super(HumanInterpreter, self).__init__(params=hi)
def test_rocksalt(self): """Testing coordination and connectivity matrix for rock salt structure NaCl""" rocksalt_structure = Structure.from_file("test_structures/rocksalt.cif", True, True) cn_finder = EffectiveCoordFinder(rocksalt_structure) cns = cn_finder.get_avg_cn(radius=3.0, anions=["Cl"]) for cation in cns: self.assertTrue(cation == "Na", "Na should be the only ions in rocksalt NaCl structure") if cation == "Na": self.assertEqual(round(cns[cation]), 6, "Na should be 6-fold coordinated") central_species = ["Na"] peripheral_species = ["Cl"] connectivity_matrix, connectivity_polyhedra = get_connectivity_matrix( rocksalt_structure, False, 3.0, peripheral_species, central_species ) self.assertIn("Na", connectivity_matrix.keys(), "Na polyhedra not found in NaCl matrix") self.assertEqual(connectivity_matrix["Na"]["Na"]["point"], 6, "Na should not be point-sharing") self.assertEqual(connectivity_matrix["Na"]["Na"]["edge"], 12, "Na should be edge-sharing") self.assertEqual(connectivity_matrix["Na"]["Na"]["face"], 0, "Na should not be face-sharing") for poly in connectivity_polyhedra: self.assertIsInstance(poly, Polyhedra, "List of polyhedra includes a non-polyhedra element")
def test_fluorite(self): """Testing coordination and connectivity matrix for fluorite structure CaF2""" caf2_structure = Structure.from_file('test_structures/fluorite.cif', True, True) cn_finder = EffectiveCoordFinder(caf2_structure) cns = cn_finder.get_avg_CN(radius=2.6, anions=['F']) for cation in cns: self.assertEqual(cation, "Ca", "Ca should be the only ions in CaF2 fluorite") if cation == 'Ca': self.assertEqual(round(cns[cation]), 8, "Ca should be 8-fold coordinated") central_species = ['Ca'] peripheral_species = ['F'] connectivity_matrix, connectivity_polyhedra = \ get_connectivity_matrix(caf2_structure, False, 2.6, peripheral_species, central_species) self.assertIn('Ca', connectivity_matrix.keys(), "Ca polyhedra not found in CaF2 fluorite matrix") self.assertEqual(connectivity_matrix['Ca']['Ca']['point'], 0, "Ca should not be point-sharing") self.assertEqual(connectivity_matrix['Ca']['Ca']['edge'], 12, "Ca should be edge-sharing") self.assertEqual(connectivity_matrix['Ca']['Ca']['face'], 0, "Ca should not be face-sharing") for poly in connectivity_polyhedra: self.assertIsInstance(poly, Polyhedra, "List of polyhedra includes a non-polyhedra element")
def test_kpath_generation(self): triclinic = [1, 2] monoclinic = range(3, 16) orthorhombic = range(16, 75) tetragonal = range(75, 143) rhombohedral = range(143, 168) hexagonal = range(168, 195) cubic = range(195, 231) species = ['K', 'La', 'Ti'] coords = [[.345, 5, .77298], [.1345, 5.1, .77298], [.7, .8, .9]] for i in range(230): sg_num = i + 1 if sg_num in triclinic: lattice = Lattice([[3.0233057319441246,0,0], [0,7.9850357844548681,0], [0,0,8.1136762279561818]]) elif sg_num in monoclinic: lattice = Lattice.monoclinic(2, 9, 1, 99) elif sg_num in orthorhombic: lattice = Lattice.orthorhombic(2, 9, 1) elif sg_num in tetragonal: lattice = Lattice.tetragonal(2, 9) elif sg_num in rhombohedral: lattice = Lattice.hexagonal(2, 95) elif sg_num in hexagonal: lattice = Lattice.hexagonal(2, 9) elif sg_num in cubic: lattice = Lattice.cubic(2) struct = Structure.from_spacegroup(sg_num, lattice, species, coords) kpath = HighSymmKpath(struct) #Throws error if something doesn't work, causing test to fail. struct_file_path = os.path.join(test_dir_structs, 'ICSD_170.cif') struct = Structure.from_file(struct_file_path) hkp = HighSymmKpath(struct) self.assertEqual(hkp.name, 'MCLC5')
def test_get_conversion_factor(self): filepath = os.path.join(test_dir, 'LiFePO4.cif') s = Structure.from_file(filepath) # large tolerance because scipy constants changed between 0.16.1 and 0.17 self.assertAlmostEqual(41370704.343540139, get_conversion_factor(s, "Li", 600), delta=20)
def test_get_slabs(self): gen = SlabGenerator(self.get_structure("CsCl"), [0, 0, 1], 10, 10) #Test orthogonality of some internal variables. a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) self.assertEqual(len(gen.get_slabs()), 1) s = self.get_structure("LiFePO4") gen = SlabGenerator(s, [0, 0, 1], 10, 10) self.assertEqual(len(gen.get_slabs()), 5) self.assertEqual(len(gen.get_slabs(bonds={("P", "O"): 3})), 2) # There are no slabs in LFP that does not break either P-O or Fe-O # bonds for a miller index of [0, 0, 1]. self.assertEqual(len(gen.get_slabs( bonds={("P", "O"): 3, ("Fe", "O"): 3})), 0) #If we allow some broken bonds, there are a few slabs. self.assertEqual(len(gen.get_slabs( bonds={("P", "O"): 3, ("Fe", "O"): 3}, max_broken_bonds=2)), 2) # At this threshold, only the origin and center Li results in # clustering. All other sites are non-clustered. So the of # slabs is of sites in LiFePO4 unit cell - 2 + 1. self.assertEqual(len(gen.get_slabs(tol=1e-4)), 15) LiCoO2=Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) gen = SlabGenerator(LiCoO2, [0, 0, 1], 10, 10) lco = gen.get_slabs(bonds={("Co", "O"): 3}) self.assertEqual(len(lco), 1) a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) scc = Structure.from_spacegroup("Pm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) gen = SlabGenerator(scc, [0, 0, 1], 10, 10) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1) gen = SlabGenerator(scc, [1, 1, 1], 10, 10, max_normal_search=1) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1) # Test whether using units of hkl planes instead of Angstroms for # min_slab_size and min_vac_size will give us the same number of atoms natoms = [] for a in [1, 1.4, 2.5, 3.6]: s = Structure.from_spacegroup("Im-3m", Lattice.cubic(a), ["Fe"], [[0,0,0]]) slabgen = SlabGenerator(s, (1,1,1), 10, 10, in_unit_planes=True, max_normal_search=2) natoms.append(len(slabgen.get_slab())) n = natoms[0] for i in natoms: self.assertEqual(n, i)
def setUp(self): zno1 = Structure.from_file(get_path("ZnO-wz.cif"), primitive=False) zno55 = SlabGenerator(zno1, [1, 0, 0], 5, 5, lll_reduce=False, center_slab=False).get_slab() Ti = Structure(Lattice.hexagonal(4.6, 2.82), ["Ti", "Ti", "Ti"], [[0.000000, 0.000000, 0.000000], [0.333333, 0.666667, 0.500000], [0.666667, 0.333333, 0.500000]]) Ag_fcc = Structure(Lattice.cubic(4.06), ["Ag", "Ag", "Ag", "Ag"], [[0.000000, 0.000000, 0.000000], [0.000000, 0.500000, 0.500000], [0.500000, 0.000000, 0.500000], [0.500000, 0.500000, 0.000000]]) laue_groups = ["-1", "2/m", "mmm", "4/m", "4/mmm", "-3", "-3m", "6/m", "6/mmm", "m-3", "m-3m"] self.ti = Ti self.agfcc = Ag_fcc self.zno1 = zno1 self.zno55 = zno55 self.h = Structure(Lattice.cubic(3), ["H"], [[0, 0, 0]]) self.libcc = Structure(Lattice.cubic(3.51004), ["Li", "Li"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.laue_groups = laue_groups
def asabistructure(obj): """ Convert obj into an AbiStructure object. Accepts: - AbiStructure instance - Subinstances of pymatgen. - File paths """ if isinstance(obj, AbiStructure): return obj if isinstance(obj, Structure): # Promote return AbiStructure(obj) if is_string(obj): # Handle file paths. if os.path.isfile(obj): if obj.endswith(".nc"): structure = structure_from_etsf_file(obj) else: structure = Structure.from_file(obj) # Promote return AbiStructure(structure) raise ValueError("Don't know how to convert object %s to an AbiStructure structure" % str(obj))
def test_previous_reconstructions(self): # Test to see if we generated all reconstruction # types correctly and nothing changes m = StructureMatcher() for n in self.rec_archive.keys(): if "base_reconstruction" in self.rec_archive[n].keys(): arch = self.rec_archive[ self.rec_archive[n]["base_reconstruction"]] sg = arch["spacegroup"]["symbol"] else: sg = self.rec_archive[n]["spacegroup"]["symbol"] if sg == "Fm-3m": rec = ReconstructionGenerator(self.Ni, 20, 20, n) el = self.Ni[0].species_string elif sg == "Im-3m": rec = ReconstructionGenerator(self.Fe, 20, 20, n) el = self.Fe[0].species_string elif sg == "Fd-3m": rec = ReconstructionGenerator(self.Si, 20, 20, n) el = self.Si[0].species_string slabs = rec.build_slabs() s = Structure.from_file(get_path(os.path.join("reconstructions", el + "_" + n + ".cif"))) self.assertTrue(any( [len(m.group_structures([s, slab])) == 1 for slab in slabs]))
def test_sio2(self): """Testing coordination and connectivity matrix for SiO2 structure""" sio2_structure = Structure.from_file("test_structures/SiO2.cif", True, True) cn_finder = EffectiveCoordFinder(sio2_structure) cns = cn_finder.get_avg_cn(radius=2.6, anions=["O"]) for cation in cns: self.assertTrue(cation == "Si", "Si should be the only ions in SiO2 structure") if cation == "Si": self.assertEqual(round(cns[cation]), 4, "Si should be 6-fold coordinated") central_species = ["Si"] peripheral_species = ["O"] connectivity_matrix, connectivity_polyhedra = get_connectivity_matrix( sio2_structure, False, 2.6, peripheral_species, central_species ) self.assertIn("Si", connectivity_matrix.keys(), "Si polyhedra not found in SiO2 matrix") self.assertEqual(connectivity_matrix["Si"]["Si"]["point"], 4, "Si should not be point-sharing") self.assertEqual(connectivity_matrix["Si"]["Si"]["edge"], 0, "Si should be edge-sharing") self.assertEqual(connectivity_matrix["Si"]["Si"]["face"], 0, "Si should not be face-sharing") for poly in connectivity_polyhedra: self.assertIsInstance(poly, Polyhedra, "List of polyhedra includes a non-polyhedra element")
def get_convergence_data(jfile, params = ['ENCUT','KPOINTS']): """ returns data dict in the following format {'Al': {'ENCUT': [ [500,1.232], [600,0.8798] ], 'KPOINTS':[ [], [] ] }, 'W': ... } Note: processes only INCAR parmaters and KPOINTS """ cutoff_jobs = jobs_from_file(jfile) data = {} for j in cutoff_jobs: jdir = os.path.join(j.parent_job_dir, j.job_dir) poscar_file = os.path.join(jdir, 'POSCAR') struct_m = Structure.from_file(poscar_file) species = ''.join([tos.symbol for tos in struct_m.types_of_specie]) if data.get(species): for p in params: if j.vis.incar.get(p): data[species][p].append( [ j.vis.incar[p], j.final_energy/len(struct_m) ] ) elif p == 'KPOINTS': data[species]['KPOINTS'].append( [ j.vis.kpoints.kpts, j.final_energy/len(struct_m) ] ) else: logger.warn('dont know how to parse the parameter {}'.format(p)) else: data[species] = {} for p in params: data[species][p] = [] data[species][p] = [] return data
def test_corundum(self): """Testing coordination and connectivity matrix for corundum structure Cr2O3""" corundum_structure = Structure.from_file('test_structures/corundum.cif', True, True) cn_finder = EffectiveCoordFinder(corundum_structure) cns = cn_finder.get_avg_CN(radius=2.6, anions=['O']) for cation in cns: self.assertTrue(cation == "Cr", "Cr should be the only ions in corundum Cr2O3") if cation == 'Cr': self.assertEqual(round(cns[cation]), 6, "Cr should be 6-fold coordinated") central_species = ['Cr'] peripheral_species = ['O'] connectivity_matrix, connectivity_polyhedra = \ get_connectivity_matrix(corundum_structure, False, 2.6, peripheral_species, central_species) self.assertIn('Cr', connectivity_matrix.keys(), "Cr polyhedra not found in corundum Cr2O3 matrix") self.assertEqual(connectivity_matrix['Cr']['Cr']['point'], 9, "Cr should be point-sharing") self.assertEqual(connectivity_matrix['Cr']['Cr']['edge'], 3, "Cr should be edge-sharing") self.assertEqual(connectivity_matrix['Cr']['Cr']['face'], 1, "Cr should be face-sharing") for poly in connectivity_polyhedra: self.assertIsInstance(poly, Polyhedra, "List of polyhedra includes a non-polyhedra element")
def get_spacing(filename='POSCAR', cut=0.9): """ Returns the interlayer spacing for a 2D material. Args: filename (str): 'CONTCAR' or 'POSCAR', whichever file to check. cut (float): a fractional z-coordinate that must be within the vacuum region. Returns: float. Spacing in Angstroms. """ structure = Structure.from_file('POSCAR') lines = open(filename).readlines() c_axis = lines[4].split() lattice_parameter = lines[1].split() split_coords = [line.split() for line in lines[8:8+structure.num_sites]] z_coords = list() for coord in split_coords: z_coord = float(coord[2]) if z_coord > cut: z_coord -= 1 z_coords.append(z_coord) max_height = max([z_height for z_height in z_coords]) min_height = min([z_height for z_height in z_coords]) spacing = ((1.0 + min_height) - max_height) * abs(float(c_axis[2]))\ * float(lattice_parameter[0]) return spacing
def get_convergence_data(jfile): """ returns data dict in the following format {'Al': {'ENCUT': [ [500,1.232], [600,0.8798] ], 'KPOINTS':[ [], [] ] }, 'W': ... } Note: only ENCUT and KPOINTS """ cutoff_jobs = jobs_from_file(jfile) data = {} for j in cutoff_jobs: jdir = os.path.join(j.parent_job_dir, j.job_dir) poscar_file = os.path.join(jdir, 'POSCAR') struct_m = Structure.from_file(poscar_file) species = ''.join([tos.symbol for tos in struct_m.types_of_specie]) # energy / atom if data.get(species): data[species]['ENCUT'].append([j.vis.incar['ENCUT'],j.final_energy/len(struct_m)]) data[species]['KPOINTS'].append([j.vis.kpoints.kpts,j.final_energy/len(struct_m)]) else: data[species] = {} data[species]['ENCUT'] = [] data[species]['KPOINTS'] = [] return data
def get_hull_distance(competing_phase_directory='../competing_phases'): """ Calculate the material's distance to the thermodynamic hull, based on species in the Materials Project database. Args: competing_phase_directory (str): absolute or relative path to the location where your competing phases have been relaxed. The default expectation is that they are stored in a directory named 'competing_phases' at the same level as your material's relaxation directory. Returns: float. distance (eV/atom) between the material and the hull. """ finished_competitors = {} original_directory = os.getcwd() # Determine which competing phases have been relaxed in the current # framework and store them in a dictionary ({formula: entry}). if os.path.isdir(competing_phase_directory): os.chdir(competing_phase_directory) for comp_dir in [ dir for dir in os.listdir(os.getcwd()) if os.path.isdir(dir) and is_converged(dir) ]: vasprun = Vasprun('{}/vasprun.xml'.format(comp_dir)) composition = vasprun.final_structure.composition energy = vasprun.final_energy finished_competitors[comp_dir] = ComputedEntry(composition, energy) os.chdir(original_directory) else: raise ValueError('Competing phase directory does not exist.') composition = Structure.from_file('POSCAR').composition try: energy = Vasprun('vasprun.xml').final_energy except: raise ValueError('This directory does not have a converged vasprun.xml') my_entry = ComputedEntry(composition, energy) # 2D material entries = MPR.get_entries_in_chemsys( [elt.symbol for elt in composition] ) # If the energies of competing phases have been calculated in # the current framework, put them in the phase diagram instead # of the MP energies. for i in range(len(entries)): formula = entries[i].composition.reduced_formula if formula in finished_competitors: entries[i] = finished_competitors[formula] else: entries[i] = ComputedEntry(entries[i].composition, 100) entries.append(my_entry) # 2D material pda = PDAnalyzer(PhaseDiagram(entries)) decomp = pda.get_decomp_and_e_above_hull(my_entry, allow_negative=True) return decomp[1]
def find_structure(self, filename_or_structure): """ Finds matching structures on the Materials Project site. Args: filename_or_structure: filename or Structure object Returns: A list of matching structures. Raises: MPRestError """ try: if isinstance(filename_or_structure, string_types): s = Structure.from_file(filename_or_structure) elif isinstance(filename_or_structure, Structure): s = filename_or_structure else: raise MPRestError("Provide filename or Structure object.") payload = {'structure': json.dumps(s.as_dict(), cls=MontyEncoder)} response = self.session.post( '{}/find_structure'.format(self.preamble), data=payload ) if response.status_code in [200, 400]: resp = json.loads(response.text, cls=MontyDecoder) if resp['valid_response']: return resp['response'] else: raise MPRestError(resp["error"]) raise MPRestError("REST error with status code {} and error {}" .format(response.status_code, response.text)) except Exception as ex: raise MPRestError(str(ex))
def plot_local_potential(axis=2, ylim=(-20, 0), fmt='pdf'): """ Plot data from the LOCPOT file along any of the 3 primary axes. Useful for determining surface dipole moments and electric potentials on the interior of the material. Args: axis (int): 0 = x, 1 = y, 2 = z ylim (tuple): minimum and maximum potentials for the plot's y-axis. fmt (str): matplotlib format style. Check the matplotlib docs for options. """ ax = plt.figure(figsize=(16, 10)).gca() locpot = Locpot.from_file('LOCPOT') structure = Structure.from_file('CONTCAR') vd = VolumetricData(structure, locpot.data) abs_potentials = vd.get_average_along_axis(axis) vacuum_level = max(abs_potentials) vasprun = Vasprun('vasprun.xml') bs = vasprun.get_band_structure() if not bs.is_metal(): cbm = bs.get_cbm()['energy'] - vacuum_level vbm = bs.get_vbm()['energy'] - vacuum_level potentials = [potential - vacuum_level for potential in abs_potentials] axis_length = structure.lattice._lengths[axis] positions = np.arange(0, axis_length, axis_length / len(potentials)) ax.plot(positions, potentials, linewidth=2, color='k') ax.set_xlim(0, axis_length) ax.set_ylim(ylim[0], ylim[1]) ax.set_xticklabels( [r'$\mathrm{%s}$' % tick for tick in ax.get_xticks()], size=20) ax.set_yticklabels( [r'$\mathrm{%s}$' % tick for tick in ax.get_yticks()], size=20) ax.set_xlabel(r'$\mathrm{\AA}$', size=24) ax.set_ylabel(r'$\mathrm{V\/(eV)}$', size=24) if not bs.is_metal(): ax.text(ax.get_xlim()[1], cbm, r'$\mathrm{CBM}$', horizontalalignment='right', verticalalignment='bottom', size=20) ax.text(ax.get_xlim()[1], vbm, r'$\mathrm{VBM}$', horizontalalignment='right', verticalalignment='top', size=20) ax.fill_between(ax.get_xlim(), cbm, ax.get_ylim()[1], facecolor=plt.cm.jet(0.3), zorder=0, linewidth=0) ax.fill_between(ax.get_xlim(), ax.get_ylim()[0], vbm, facecolor=plt.cm.jet(0.7), zorder=0, linewidth=0) if fmt == "None": return ax else: plt.savefig('locpot.{}'.format(fmt)) plt.close()
def setUp(self): # This is a CHGCAR_sum file with reduced grid size chgcar_path = os.path.join(test_dir, "CHGCAR.FePO4") chg_FePO4 = Chgcar.from_file(chgcar_path) self.chgcar_path = chgcar_path self.chg_FePO4 = chg_FePO4 self.ca_FePO4 = ChargeDensityAnalyzer(chg_FePO4) self.s_LiFePO4 = Structure.from_file(os.path.join(test_dir, "LiFePO4.cif"))
def test_calculate_vol(self): s = Structure.from_file(os.path.join(test_dir, "LiFePO4.cif")) a = TopographyAnalyzer(s, framework_ions=["O"], cations=["P", "Fe"], check_volume=False) coords = [s[i].coords for i in [20, 23, 25, 17, 24, 19]] vol = calculate_vol(coords=coords) vol_expected = 12.8884 # LiO6 volume calculated by VESTA self.assertAlmostEqual(vol, vol_expected, 4)
def test_get_orthogonal_c_slab(self): TeI = Structure.from_file(get_path("icsd_TeI.cif"), primitive=False) trclnc_TeI = SlabGenerator(TeI, (0, 0, 1), 10, 10) TeI_slabs = trclnc_TeI.get_slabs() slab = TeI_slabs[0] norm_slab = slab.get_orthogonal_c_slab() self.assertAlmostEqual(norm_slab.lattice.angles[0], 90) self.assertAlmostEqual(norm_slab.lattice.angles[1], 90)
def callback_update_structure(contents, filename, last_modified): if not contents: raise PreventUpdate # assume we only want the first input for now content_type, content_string = contents.split(",") decoded_contents = b64decode(content_string) error = None struct_or_mol = None # necessary to write to file so pymatgen's filetype detection can work with NamedTemporaryFile(suffix=filename) as tmp: tmp.write(decoded_contents) tmp.flush() try: struct_or_mol = Structure.from_file(tmp.name) except: try: struct_or_mol = Molecule.from_file(tmp.name) except: try: struct_or_mol = Chgcar.from_file(tmp.name) except: # TODO: fix these horrible try/excepts, loadfn may be dangerous try: struct_or_mol = loadfn(tmp.name) except: error = ( "Could not parse uploaded file. " "If this seems like a bug, please report it. " "Crystal Toolkit understands all crystal " "structure file types and molecule file types " "supported by pymatgen.") return {"data": struct_or_mol, "error": error}
def __getitem__(self, idx): cif_id, target = self.id_prop_data[idx] crystal = Structure.from_file( os.path.join(self.root_dir, cif_id + ".cif")) atom_fea = np.vstack([ self.ari.get_atom_fea(crystal[i].specie.number) for i in range(len(crystal)) ]) atom_fea = torch.Tensor(atom_fea) all_nbrs = crystal.get_all_neighbors(self.radius, include_index=True) all_nbrs = [sorted(nbrs, key=lambda x: x[1]) for nbrs in all_nbrs] nbr_fea_idx, nbr_fea = [], [] for nbr in all_nbrs: if len(nbr) < self.max_num_nbr: warnings.warn("{} not find enough neighbors to build graph. " "If it happens frequently, consider increase " "radius.".format(cif_id)) nbr_fea_idx.append( list(map(lambda x: x[2], nbr)) + [0] * (self.max_num_nbr - len(nbr))) nbr_fea.append( list(map(lambda x: x[1], nbr)) + [self.radius + 1.0] * (self.max_num_nbr - len(nbr))) if self.store_bad_indices: self.bad_indices.add(idx) else: nbr_fea_idx.append( list(map(lambda x: x[2], nbr[:self.max_num_nbr]))) nbr_fea.append( list(map(lambda x: x[1], nbr[:self.max_num_nbr]))) nbr_fea_idx, nbr_fea = np.array(nbr_fea_idx), np.array(nbr_fea) nbr_fea = self.gdf.expand(nbr_fea) atom_fea = torch.Tensor(atom_fea) nbr_fea = torch.Tensor(nbr_fea) nbr_fea_idx = torch.LongTensor(nbr_fea_idx) target = torch.Tensor([float(target)]) return (atom_fea, nbr_fea, nbr_fea_idx), target, cif_id
def def_energy(vac=[]): """ Calculation of vacancy formation energies Args: vac: list of Poscar vacancy structure objects Returns: def_list: list of defect energies def_header_list: list of defect names """ def_list=[] header_list=[] fi=str('DEF.INFO') f=open(fi,'w') for v in vac: enp,contc=smart_converge(mat=v) #enp,contc=run_job(mat=v,incar=incar,kpoints=kpoints,jobname=str(v.comment)) strt=Structure.from_file(contc) comm=str(v.comment) print ("running def_energy for =",comm) header_list.append(comm) if comm.split('@')[0]=='bulk': gs_energy=float(enp)*float(strt.composition.num_atoms) print ("in def_energy gs_energy for",comm, gs_energy) else: chem_pot=sum_chem_pot(strt) if comm.startswith("intl"): chem_pot=0.0-float(chem_pot) def_en=(float(enp)*float(strt.composition.num_atoms))-float(gs_energy)+chem_pot print ("in def_energy def_en for",comm, def_en,"chem_pot",chem_pot) def_list.append(def_en) print (v.comment,'=',def_en) line= str(v.comment)+str('=')+str(def_en)+'\n' f.write(line) f.close() return def_list,header_list
def __getitem__(self, idx): data_row = self.id_prop_data[idx] cif_id = str(int(float(data_row.pop(0)))) # At this point we have a list of strings each with some decimal value of a property or None. # To represent None in float datatype while converting we use float("inf") targets = [float(x) if x else float("inf") for x in data_row] crystal = Structure.from_file(os.path.join(self.root_dir, cif_id+'.cif')) atom_fea = np.vstack([self.ari.get_atom_fea(crystal[i].specie.number) for i in range(len(crystal))]) atom_fea = torch.Tensor(atom_fea) all_nbrs = crystal.get_all_neighbors(self.radius, include_index=True) all_nbrs = [sorted(nbrs, key=lambda x: x[1]) for nbrs in all_nbrs] nbr_fea_idx, nbr_fea = [], [] for nbr in all_nbrs: if len(nbr) < self.max_num_nbr: warnings.warn('{} not find enough neighbors to build graph. ' 'If it happens frequently, consider increase ' 'radius.'.format(cif_id)) nbr_fea_idx.append(list(map(lambda x: x[2], nbr)) + [0] * (self.max_num_nbr - len(nbr))) nbr_fea.append(list(map(lambda x: x[1], nbr)) + [self.radius + 1.] * (self.max_num_nbr - len(nbr))) else: nbr_fea_idx.append(list(map(lambda x: x[2], nbr[:self.max_num_nbr]))) nbr_fea.append(list(map(lambda x: x[1], nbr[:self.max_num_nbr]))) nbr_fea_idx, nbr_fea = np.array(nbr_fea_idx), np.array(nbr_fea) nbr_fea = self.gdf.expand(nbr_fea) atom_fea = torch.Tensor(atom_fea) nbr_fea = torch.Tensor(nbr_fea) nbr_fea_idx = torch.LongTensor(nbr_fea_idx) targets = torch.Tensor(targets) return (atom_fea, nbr_fea, nbr_fea_idx), targets, cif_id
def get_convergence_data(jfile, params=['ENCUT', 'KPOINTS']): """ returns data dict in the following format {'Al': {'ENCUT': [ [500,1.232], [600,0.8798] ], 'KPOINTS':[ [], [] ] }, 'W': ... } Note: processes only INCAR parmaters and KPOINTS """ cutoff_jobs = jobs_from_file(jfile) data = {} for j in cutoff_jobs: jdir = os.path.join(j.parent_job_dir, j.job_dir) poscar_file = os.path.join(jdir, 'POSCAR') struct_m = Structure.from_file(poscar_file) species = ''.join([tos.symbol for tos in struct_m.types_of_specie]) if data.get(species): for p in params: if j.vis.incar.get(p): data[species][p].append( [j.vis.incar[p], j.final_energy / len(struct_m)]) elif p == 'KPOINTS': data[species]['KPOINTS'].append( [j.vis.kpoints.kpts, j.final_energy / len(struct_m)]) else: logger.warn( 'dont know how to parse the parameter {}'.format(p)) else: data[species] = {} for p in params: data[species][p] = [] data[species][p] = [] return data
def setUp(self): zno1 = Structure.from_file(get_path("ZnO-wz.cif"), primitive=False) zno55 = SlabGenerator(zno1, [1, 0, 0], 5, 5, lll_reduce=False, center_slab=False).get_slab() Ti = Structure(Lattice.hexagonal(4.6, 2.82), ["Ti", "Ti", "Ti"], [[0.000000, 0.000000, 0.000000], [0.333333, 0.666667, 0.500000], [0.666667, 0.333333, 0.500000]]) Ag_fcc = Structure(Lattice.cubic(4.06), ["Ag", "Ag", "Ag", "Ag"], [[0.000000, 0.000000, 0.000000], [0.000000, 0.500000, 0.500000], [0.500000, 0.000000, 0.500000], [0.500000, 0.500000, 0.000000]]) self.ti = Ti self.agfcc = Ag_fcc self.zno1 = zno1 self.zno55 = zno55 self.h = Structure(Lattice.cubic(3), ["H"], [[0, 0, 0]]) self.libcc = Structure(Lattice.cubic(3.51004), ["Li", "Li"], [[0, 0, 0], [0.5, 0.5, 0.5]])
def write_INCAR( self, incar_input: str = "INCAR", incar_output: str = "INCAR.lobster", poscar_input: str = "POSCAR", isym: int = -1, further_settings: dict = None, ): """ Will only make the run static, insert nbands, make ISYM=-1, set LWAVE=True and write a new INCAR. You have to check for the rest. Args: incar_input (str): path to input INCAR incar_output (str): path to output INCAR poscar_input (str): path to input POSCAR isym (int): isym equal to -1 or 0 are possible. Current Lobster version only allow -1. further_settings (dict): A dict can be used to include further settings, e.g. {"ISMEAR":-5} """ # reads old incar from file, this one will be modified incar = Incar.from_file(incar_input) warnings.warn("Please check your incar_input before using it. This method only changes three settings!") if isym == -1: incar["ISYM"] = -1 elif isym == 0: incar["ISYM"] = 0 else: ValueError("isym has to be -1 or 0.") incar["NSW"] = 0 incar["LWAVE"] = True # get nbands from _get_nbands (use basis set that is inserted) incar["NBANDS"] = self._get_nbands(Structure.from_file(poscar_input)) if further_settings is not None: for key, item in further_settings.items(): incar[key] = further_settings[key] # print it to file incar.write_file(incar_output)
def test_znucl_typat(self): """Test the order of typat and znucl in the Abinit input and enforce_typat, enforce_znucl.""" # Ga Ga1 1 0.33333333333333 0.666666666666667 0.500880 1.0 # Ga Ga2 1 0.66666666666667 0.333333333333333 0.000880 1.0 # N N3 1 0.333333333333333 0.666666666666667 0.124120 1.0 # N N4 1 0.666666666666667 0.333333333333333 0.624120 1.0 gan = Structure.from_file( os.path.join(PymatgenTest.TEST_FILES_DIR, "abinit", "gan.cif")) # By default, znucl is filled using the first new type found in sites. def_vars = structure_to_abivars(gan) def_znucl = def_vars["znucl"] self.assertArrayEqual(def_znucl, [31, 7]) def_typat = def_vars["typat"] self.assertArrayEqual(def_typat, [1, 1, 2, 2]) # But it's possible to enforce a particular value of typat and znucl. enforce_znucl = [7, 31] enforce_typat = [2, 2, 1, 1] enf_vars = structure_to_abivars(gan, enforce_znucl=enforce_znucl, enforce_typat=enforce_typat) self.assertArrayEqual(enf_vars["znucl"], enforce_znucl) self.assertArrayEqual(enf_vars["typat"], enforce_typat) self.assertArrayEqual(def_vars["xred"], enf_vars["xred"]) assert [s.symbol for s in species_by_znucl(gan)] == ["Ga", "N"] for itype1, itype2 in zip(def_typat, enforce_typat): assert def_znucl[itype1 - 1] == enforce_znucl[itype2 - 1] with self.assertRaises(Exception): structure_to_abivars(gan, enforce_znucl=enforce_znucl, enforce_typat=None)
def surf_energy(surf=[]): """ Helper function for surface energies Args: surf: list of Poscar surface objects Returns: surf_list: list of surface energies surf_header_list: list of surface names """ surf_list = [] surf_header_list = [] fi = str('SURF.INFO') f = open(fi, 'w') for s in surf: enp, contc = smart_converge(mat=s) strt = Structure.from_file(contc) m = strt.lattice.matrix if s.comment.split('@')[0] == 'sbulk': gs_energy = enp print("in surf_energy gs_energy for", s.comment, gs_energy) else: surf_en = 16 * ( float(enp) * (strt.composition.num_atoms) - float(strt.composition.num_atoms) * float(gs_energy)) / ( 2 * np.linalg.norm(np.cross(m[0], m[1]))) print("in surf_energy surf_en for", s.comment, surf_en) surf_list.append(surf_en) print(s.comment, '=', surf_en) line = str(s.comment) + str('=') + str(surf_en) + '\n' f.write(line) f.close() return surf_list, surf_header_list
def run_task(self, fw_spec): potcar_spec = self.get("potcar_spec", False) vasp_input_set_params = self.get("vasp_input_set_params") or {} # update the bandgap based on output from the previous calculation, # unless the user specified a bandgap via vasp_input_set_params if vasp_input_set_params.get("bandgap") is None: # First look for the gga_bandgap key in the FW spec, to save parsing time if fw_spec.get("gga_bandgap") is not None: vasp_input_set_params["bandgap"] = fw_spec.get("gga_bandgap") # If not found, parse the files from the previous calc to find the bandgap else: parse_potcar_file = not potcar_spec vasprun = Vasprun("vasprun.xml", parse_potcar_file=parse_potcar_file) bandgap = vasprun.eigenvalue_band_properties[0] vasp_input_set_params["bandgap"] = bandgap # read the structure from the output of the previous calculation structure = Structure.from_file("POSCAR") vis = MPScanRelaxSet(structure, **vasp_input_set_params) vis.write_input(".", potcar_spec=potcar_spec)
def compare_structures(args): """ Compare structures in files for similarity using structure matcher. Args: args (dict): Args from argparse. """ filenames = args.filenames if len(filenames) < 2: print("You need more than one structure to compare!") sys.exit(-1) try: structures = [Structure.from_file(fn) for fn in filenames] except Exception as ex: print("Error converting file. Are they in the right format?") print(str(ex)) sys.exit(-1) m = StructureMatcher() if args.group == "species" else StructureMatcher(comparator=ElementComparator()) for i, grp in enumerate(m.group_structures(structures)): print(f"Group {i}: ") for s in grp: print(f"- {filenames[structures.index(s)]} ({s.formula})") print()
def get_structures_from_paths(paths_list): structures = [] for path in paths_list: try: poscar_path = os.path.join(path, 'POSCAR.orig') incar_path = os.path.join(path, 'INCAR.orig') try: incar = Incar.from_file(incar_path) magmoms = incar.get('MAGMOM') undecorated_structure = Structure.from_file(poscar_path) structure = Structure(lattice=undecorated_structure.lattice, species=undecorated_structure.species, coords=undecorated_structure.frac_coords, site_properties={'magmom': magmoms}) structures.append(structure) except: print('%s does not have a MAGMOM tag' % incar_path) except: print('%s does not contain a valid POSCAR or INCAR' % path) return structures
def test_timeout(self): s = Structure.from_file(filename=os.path.join(PymatgenTest.TEST_FILES_DIR, "garnet.cif")) a = SpacegroupAnalyzer(s, 0.1) s["Al3+"] = {"Al3+": 0.5, "Ga3+": 0.5} adaptor = EnumlibAdaptor(s, 1, 1, enum_precision_parameter=0.01, timeout=0.0000000000001) self.assertRaises(TimeoutError, adaptor._run_multienum)
# putting the atom at a halfway distance between other atoms link = {'0': {}, '1': {}, '2': {'0': [6, 2, -1]}} # list of indices of atoms to be removed from each molecule remove = [[7], [7], []] # combined_mol = combine_mols(mols, cm_dist, angle, link=link, remove=remove) lead_acetate = Ligand(mols, cm_dist, angle=angle, link={}, remove=remove) lead_acetate.create_ligand() lead_acetate.to('xyz', 'lead_acetate.xyz') # put the ligand in a box boxed_lead_acetate = lead_acetate.get_boxed_structure(13, 13, 13) boxed_lead_acetate.to(fmt="poscar", filename="POSCAR_diacetate_boxed.vasp") # bulk PbS strt_pbs = Structure.from_file( os.path.join(PACKAGE_PATH, "test_files", "POSCAR_PbS")) # intital supercell, this wont be the final supercell if surface # coverage is specified supercell = [1, 1, 1] # miller index hkl = [1, 0, 0] # minimum slab thickness in Angstroms min_thick = 21 # minimum vacuum thickness in Angstroms # the maximum distance in the lignad will be added to this value min_vac = 10
def vac_antisite_def_struct_gen(mpid, mapi_key, cellmax, struct_file=None): if not mpid and not struct_file: print ("============\nERROR: Provide an mpid\n============") return # Get primitive structure from the Materials Project DB if not struct_file: if not mapi_key: with MPRester() as mp: struct = mp.get_structure_by_material_id(mpid) else: with MPRester(mapi_key) as mp: struct = mp.get_structure_by_material_id(mpid) else: struct = Structure.from_file(struct_file) sga = SpacegroupAnalyzer(struct) prim_struct = sga.find_primitive() #prim_struct_sites = len(prim_struct.sites) #conv_struct = sga.get_conventional_standard_structure() #conv_struct_sites = len(conv_struct.sites) #conv_prim_ratio = int(conv_struct_sites / prim_struct_sites) # Default VASP settings def_vasp_incar_param = {'ISIF':2, 'EDIFF':1e-6, 'EDIFFG':0.001,} kpoint_den = 15000 # Create bulk structure and associated VASP files sc_scale = get_sc_scale(inp_struct=prim_struct, final_site_no=cellmax) blk_sc = prim_struct.copy() blk_sc.make_supercell(scaling_matrix=sc_scale) site_no = blk_sc.num_sites # Rescale if needed while site_no > cellmax: max_sc_dim = max(sc_scale) i = sc_scale.index(max_sc_dim) sc_scale[i] -= 1 blk_sc = prim_struct.copy() blk_sc.make_supercell(scaling_matrix=sc_scale) site_no = blk_sc.num_sites blk_str_sites = set(blk_sc.sites) custom_kpoints = Kpoints.automatic_density(blk_sc, kppa=kpoint_den) mpvis = MPMetalRelaxSet(blk_sc, user_incar_settings=def_vasp_incar_param, user_kpoints_settings=custom_kpoints) if mpid: root_fldr = mpid else: root_fldr = struct.composition.reduced_formula fin_dir = os.path.join(root_fldr, 'bulk') mpvis.write_input(fin_dir) if not mpid: # write the input structure if mpid is not used struct.to(fmt='poscar', filename=os.path.join(fin_dir, 'POSCAR.uc')) # Create each defect structure and associated VASP files # First find all unique defect sites periodic_struct = sga.get_symmetrized_structure() unique_sites = list(set([periodic_struct.find_equivalent_sites(site)[0] \ for site in periodic_struct.sites])) temp_struct = Structure.from_sites(sorted(unique_sites)) prim_struct2 = SpacegroupAnalyzer(temp_struct).find_primitive() prim_struct2.lattice = prim_struct.lattice # a little hacky for i, site in enumerate(prim_struct2.sites): vac = Vacancy(structure=prim_struct, defect_site=site) vac_sc = vac.generate_defect_structure(supercell=sc_scale) # Get vacancy site information vac_str_sites = set(vac_sc.sites) vac_sites = blk_str_sites - vac_str_sites vac_site = next(iter(vac_sites)) site_mult = vac.get_multiplicity() vac_site_specie = vac_site.specie vac_symbol = vac_site_specie.symbol custom_kpoints = Kpoints.automatic_density(vac_sc, kppa=kpoint_den) mpvis = MPMetalRelaxSet(vac_sc, user_incar_settings=def_vasp_incar_param, user_kpoints_settings=custom_kpoints) vac_dir = 'vacancy_{}_mult-{}_sitespecie-{}'.format( str(i+1), site_mult, vac_symbol) fin_dir = os.path.join(root_fldr, vac_dir) mpvis.write_input(fin_dir) # Antisites generation at the vacancy site struct_species = blk_sc.species for specie in set(struct_species) - set([vac_site_specie]): specie_symbol = specie.symbol anti_sc = vac_sc.copy() anti_sc.append(specie, vac_site.frac_coords) mpvis = MPMetalRelaxSet(anti_sc, user_incar_settings=def_vasp_incar_param, user_kpoints_settings=custom_kpoints) anti_dir = 'antisite_{}_mult-{}_sitespecie-{}_subspecie-{}'.format( str(i+1), site_mult, vac_symbol, specie_symbol) fin_dir = os.path.join(root_fldr, anti_dir) mpvis.write_input(fin_dir)
def setUp(self): feo4 = Structure.from_file(os.path.join(test_dir, "LiFePO4.cif")) feo4.remove_species(["Li"]) feo4.remove_oxidation_states() self.feo4 = feo4
def make_deepmd_lammps (jdata, conf_dir) : deepmd_model_dir = jdata['deepmd_model_dir'] deepmd_type_map = jdata['deepmd_type_map'] ntypes = len(deepmd_type_map) deepmd_model_dir = os.path.abspath(deepmd_model_dir) deepmd_models = glob.glob(os.path.join(deepmd_model_dir, '*pb')) deepmd_models_name = [os.path.basename(ii) for ii in deepmd_models] vol_start = jdata['vol_start'] vol_end = jdata['vol_end'] vol_step = jdata['vol_step'] # # get equi props # equi_path = re.sub('confs', global_equi_name, conf_path) # equi_path = os.path.join(equi_path, 'lmp') # equi_log = os.path.join(equi_path, 'log.lammps') # if not os.path.isfile(equi_log) : # raise RuntimeError("the system should be equilibriated first") # natoms, epa, vpa = lammps.get_nev(equi_log) # task path task_path = re.sub('confs', global_task_name, conf_dir) task_path = os.path.abspath(task_path) os.makedirs(task_path, exist_ok = True) cwd = os.getcwd() conf_path = os.path.abspath(conf_dir) from_poscar = os.path.join(conf_path, 'POSCAR') to_poscar = os.path.join(task_path, 'POSCAR') if os.path.exists(to_poscar) : assert(filecmp.cmp(from_poscar, to_poscar)) else : os.chdir(task_path) os.symlink(os.path.relpath(from_poscar), 'POSCAR') os.chdir(cwd) volume = vasp.poscar_vol(to_poscar) natoms = vasp.poscar_natoms(to_poscar) vpa = volume / natoms # structrure ss = Structure.from_file(to_poscar) # lmp path lmp_path = os.path.join(task_path, 'deepmd') os.makedirs(lmp_path, exist_ok = True) # # lmp conf # conf_file = os.path.join(lmp_path, 'conf.lmp') # lammps.cvt_lammps_conf(to_poscar, conf_file) # ptypes = vasp.get_poscar_types(to_poscar) # lammps.apply_type_map(conf_file, deepmd_type_map, ptypes) os.chdir(lmp_path) for ii in deepmd_models_name : if os.path.exists(ii) : os.remove(ii) for (ii,jj) in zip(deepmd_models, deepmd_models_name) : os.symlink(os.path.relpath(ii), jj) share_models = glob.glob(os.path.join(lmp_path, '*pb')) for vol in np.arange(vol_start, vol_end, vol_step) : vol_path = os.path.join(lmp_path, 'vol-%.2f' % vol) print('# generate %s' % (vol_path)) os.makedirs(vol_path, exist_ok = True) os.chdir(vol_path) #print(vol_path) for ii in ['conf.lmp', 'conf.lmp'] + deepmd_models_name : if os.path.exists(ii) : os.remove(ii) # # link conf # os.symlink(os.path.relpath(conf_file), 'conf.lmp') # make conf scale_ss = ss.copy() scale_ss.scale_lattice(vol * natoms) scale_ss.to('POSCAR', 'POSCAR') lammps.cvt_lammps_conf('POSCAR', 'conf.lmp') ptypes = vasp.get_poscar_types('POSCAR') lammps.apply_type_map('conf.lmp', deepmd_type_map, ptypes) # link models for (ii,jj) in zip(share_models, deepmd_models_name) : os.symlink(os.path.relpath(ii), jj) # make lammps input scale = (vol / vpa) ** (1./3.) fc = lammps.make_lammps_press_relax('conf.lmp', ntypes, scale,lammps.inter_deepmd, deepmd_models_name) with open(os.path.join(vol_path, 'lammps.in'), 'w') as fp : fp.write(fc) os.chdir(cwd)
def make_meam_lammps_fixv (jdata, conf_dir) : meam_potfile_dir = jdata['meam_potfile_dir'] meam_potfile_dir = os.path.abspath(meam_potfile_dir) meam_potfile = jdata['meam_potfile'] meam_potfile = [os.path.join(meam_potfile_dir,ii) for ii in meam_potfile] meam_potfile_name = jdata['meam_potfile'] type_map = jdata['meam_type_map'] ntypes = len(type_map) meam_param = {'meam_potfile' : jdata['meam_potfile'], 'meam_type': jdata['meam_param_type']} vol_start = jdata['vol_start'] vol_end = jdata['vol_end'] vol_step = jdata['vol_step'] # get equi props equi_path = re.sub('confs', global_equi_name, conf_dir) task_path = re.sub('confs', global_task_name, conf_dir) equi_path = os.path.join(equi_path, 'meam') task_path = os.path.join(task_path, 'meam') equi_path = os.path.abspath(equi_path) task_path = os.path.abspath(task_path) equi_log = os.path.join(equi_path, 'log.lammps') equi_dump = os.path.join(equi_path, 'dump.relax') os.makedirs(task_path, exist_ok = True) task_poscar = os.path.join(task_path, 'POSCAR') lammps.poscar_from_last_dump(equi_dump, task_poscar, type_map) cwd = os.getcwd() volume = vasp.poscar_vol(task_poscar) natoms = vasp.poscar_natoms(task_poscar) vpa = volume / natoms # structrure ss = Structure.from_file(task_poscar) # make lammps.in fc = lammps.make_lammps_equi('conf.lmp', ntypes, lammps.inter_meam, meam_param, change_box = False) f_lammps_in = os.path.join(task_path, 'lammps.in') with open(f_lammps_in, 'w') as fp : fp.write(fc) # make vols for vol in np.arange(vol_start, vol_end, vol_step) : vol_path = os.path.join(task_path, 'vol-%.2f' % vol) print('# generate %s' % (vol_path)) os.makedirs(vol_path, exist_ok = True) os.chdir(vol_path) for ii in ['conf.lmp', 'conf.lmp', 'lammps.in'] + meam_potfile_name : if os.path.exists(ii) : os.remove(ii) # make conf scale_ss = ss.copy() scale_ss.scale_lattice(vol * natoms) scale_ss.to('POSCAR', 'POSCAR') lammps.cvt_lammps_conf('POSCAR', 'conf.lmp') ptypes = vasp.get_poscar_types('POSCAR') lammps.apply_type_map('conf.lmp', type_map, ptypes) # link lammps.in os.symlink(os.path.relpath(f_lammps_in), 'lammps.in') # link models for (ii,jj) in zip(meam_potfile, meam_potfile_name) : os.symlink(os.path.relpath(ii), jj) # make lammps input os.chdir(cwd)
import unittest import os from pymatgen.analysis.ferroelectricity.polarization import * from pymatgen.core.structure import Structure from pymatgen.io.vasp.outputs import Outcar from pymatgen.io.vasp.inputs import Potcar from pymatgen.util.testing import PymatgenTest test_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", 'test_files/BTO_221_99_polarization') bto_folders = ['nonpolar_polarization'] bto_folders += ['interpolation_{}_polarization'.format(str(i)) for i in range(1,9)][::-1] bto_folders += ['polar_polarization'] structures = [Structure.from_file(test_dir+"/"+folder+"/POSCAR") for folder in bto_folders] ions = np.matrix([[-44.363484, -44.363484, -44.79259988], [-44.324764, -44.324764, -69.43452043], [-44.286055, -44.286055, -69.8792077 ], [-44.247335, -44.247335, -70.32475473], [-44.208626, -44.208626, -70.77139856], [-44.169906, -44.169906, -71.21889307], [-44.131197, -44.131197, -71.66746921], [-44.092477, -44.092477, -72.1168782 ], [-44.053768, -44.053768, -72.56736141], [-44.015048, -44.015048, -73.01874336]]) class UtilsTest(PymatgenTest): def setUp(self):
def test_get_conventional_standard_structure(self): parser = CifParser( os.path.join(PymatgenTest.TEST_FILES_DIR, "bcc_1927.cif")) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 9.1980270633769461) self.assertAlmostEqual(conv.lattice.b, 9.1980270633769461) self.assertAlmostEqual(conv.lattice.c, 9.1980270633769461) parser = CifParser( os.path.join(PymatgenTest.TEST_FILES_DIR, "btet_1915.cif")) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 5.0615106678044235) self.assertAlmostEqual(conv.lattice.b, 5.0615106678044235) self.assertAlmostEqual(conv.lattice.c, 4.2327080177761687) parser = CifParser( os.path.join(PymatgenTest.TEST_FILES_DIR, "orci_1010.cif")) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 2.9542233922299999) self.assertAlmostEqual(conv.lattice.b, 4.6330325651443296) self.assertAlmostEqual(conv.lattice.c, 5.373703587040775) parser = CifParser( os.path.join(PymatgenTest.TEST_FILES_DIR, "orcc_1003.cif")) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 4.1430033493799998) self.assertAlmostEqual(conv.lattice.b, 31.437979757624728) self.assertAlmostEqual(conv.lattice.c, 3.99648651) parser = CifParser( os.path.join(PymatgenTest.TEST_FILES_DIR, "orac_632475.cif")) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 3.1790663399999999) self.assertAlmostEqual(conv.lattice.b, 9.9032878699999998) self.assertAlmostEqual(conv.lattice.c, 3.5372412099999999) parser = CifParser( os.path.join(PymatgenTest.TEST_FILES_DIR, "monoc_1028.cif")) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 117.53832420192903) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 14.033435583000625) self.assertAlmostEqual(conv.lattice.b, 3.96052850731) self.assertAlmostEqual(conv.lattice.c, 6.8743926325200002) parser = CifParser( os.path.join(PymatgenTest.TEST_FILES_DIR, "hex_1170.cif")) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 120) self.assertAlmostEqual(conv.lattice.a, 3.699919902005897) self.assertAlmostEqual(conv.lattice.b, 3.699919902005897) self.assertAlmostEqual(conv.lattice.c, 6.9779585500000003) structure = Structure.from_file( os.path.join(PymatgenTest.TEST_FILES_DIR, "tric_684654.json")) s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 74.09581916308757) self.assertAlmostEqual(conv.lattice.beta, 75.72817279281173) self.assertAlmostEqual(conv.lattice.gamma, 63.63234318667333) self.assertAlmostEqual(conv.lattice.a, 3.741372924048738) self.assertAlmostEqual(conv.lattice.b, 3.9883228679270686) self.assertAlmostEqual(conv.lattice.c, 7.288495840048958) structure = Structure.from_file( os.path.join(PymatgenTest.TEST_FILES_DIR, "tric_684654.json")) structure.add_site_property("magmom", [1.0] * len(structure)) s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure(keep_site_properties=True) self.assertEqual(conv.site_properties["magmom"], [1.0] * len(conv)) structure = Structure.from_file( os.path.join(PymatgenTest.TEST_FILES_DIR, "tric_684654.json")) structure.add_site_property("magmom", [1.0] * len(structure)) s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure( keep_site_properties=False) self.assertEqual(conv.site_properties.get("magmom", None), None)
def test_get_slabs(self): gen = SlabGenerator(self.get_structure("CsCl"), [0, 0, 1], 10, 10) #Test orthogonality of some internal variables. a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) self.assertEqual(len(gen.get_slabs()), 1) s = self.get_structure("LiFePO4") gen = SlabGenerator(s, [0, 0, 1], 10, 10) self.assertEqual(len(gen.get_slabs()), 5) self.assertEqual(len(gen.get_slabs(bonds={("P", "O"): 3})), 2) # There are no slabs in LFP that does not break either P-O or Fe-O # bonds for a miller index of [0, 0, 1]. self.assertEqual( len(gen.get_slabs(bonds={ ("P", "O"): 3, ("Fe", "O"): 3 })), 0) #If we allow some broken bonds, there are a few slabs. self.assertEqual( len( gen.get_slabs(bonds={ ("P", "O"): 3, ("Fe", "O"): 3 }, max_broken_bonds=2)), 2) # At this threshold, only the origin and center Li results in # clustering. All other sites are non-clustered. So the of # slabs is of sites in LiFePO4 unit cell - 2 + 1. self.assertEqual(len(gen.get_slabs(tol=1e-4)), 15) LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False) gen = SlabGenerator(LiCoO2, [0, 0, 1], 10, 10) lco = gen.get_slabs(bonds={("Co", "O"): 3}) self.assertEqual(len(lco), 1) a, b, c = gen.oriented_unit_cell.lattice.matrix self.assertAlmostEqual(np.dot(a, gen._normal), 0) self.assertAlmostEqual(np.dot(b, gen._normal), 0) scc = Structure.from_spacegroup("Pm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) gen = SlabGenerator(scc, [0, 0, 1], 10, 10) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1) gen = SlabGenerator(scc, [1, 1, 1], 10, 10, max_normal_search=1) slabs = gen.get_slabs() self.assertEqual(len(slabs), 1) # Test whether using units of hkl planes instead of Angstroms for # min_slab_size and min_vac_size will give us the same number of atoms natoms = [] for a in [1, 1.4, 2.5, 3.6]: s = Structure.from_spacegroup("Im-3m", Lattice.cubic(a), ["Fe"], [[0, 0, 0]]) slabgen = SlabGenerator(s, (1, 1, 1), 10, 10, in_unit_planes=True, max_normal_search=2) natoms.append(len(slabgen.get_slab())) n = natoms[0] for i in natoms: self.assertEqual(n, i)
def test_SiC_conv(self): """ Testing a full convergence calculation cycle on SiC using precomupted data. """ # the current version uses refence data from a run using the production version on zenobe # once all checks out the run should be done using the input generated using this version to replace the # reference wdir = tempfile.mkdtemp() os.chdir(wdir) temp_ABINIT_PS_EXT = os.environ.get('ABINIT_PS_EXT', None) temp_ABINIT_PS = os.environ.get('ABINIT_PS', None) os.environ['ABINIT_PS_EXT'] = '.psp8' os.environ['ABINIT_PS'] = wdir reference_dir = os.path.join(__reference_dir__, 'SiC_test_case') if not os.path.isdir(reference_dir): raise RuntimeError('py.test needs to be started in the HTGW root, ' '%s does not exist' % __reference_dir__) # copy input print(wdir) self.assertTrue(os.path.isdir(reference_dir)) src_files = os.listdir(reference_dir) for file_name in src_files: full_file_name = os.path.join(reference_dir, file_name) if os.path.isfile(full_file_name): shutil.copy(full_file_name, wdir) self.assertEqual(len(os.listdir(wdir)), 6) print(os.listdir(wdir)) structure = Structure.from_file('SiC.cif') structure.item = 'SiC.cif' print(' ==== generate flow === ') gwsetup(update=False) self.assertTrue(os.path.isdir(os.path.join(wdir, 'SiC_SiC.cif'))) print(os.listdir(os.path.join(wdir))) print(os.listdir(os.path.join(wdir, 'SiC_SiC.cif'))) self.assertTrue(os.path.isfile(os.path.join(wdir, 'SiC_SiC.cif', '__AbinitFlow__.pickle'))) self.assertEqual(len(os.listdir(os.path.join(wdir, 'SiC_SiC.cif', 'w0'))), 48) print(' ==== copy reference results from first calculation === ') shutil.rmtree(os.path.join(wdir, 'SiC_SiC.cif')) shutil.copytree(os.path.join(reference_dir, 'ref_res', 'SiC_SiC.cif'), os.path.join(wdir, 'SiC_SiC.cif')) self.assertTrue(os.path.isdir(os.path.join(wdir, 'SiC_SiC.cif'))) self.assertEqual(len(os.listdir(os.path.join(wdir, 'SiC_SiC.cif', 'w0'))), 68) print(' ==== process output === ') gwoutput() print(os.listdir('.')) self.assertTrue(os.path.isfile('plot-fits')) self.assertTrue(os.path.isfile('plots')) self.assertEqual(is_converged(hartree_parameters=True, structure=structure, return_values=True), {u'ecut': 44.0, u'ecuteps': 4.0, u'gap': 6.816130591466406, u'nbands': 60}) self.assertTrue(os.path.isfile('SiC_SiC.cif.full_res')) print(' ==== generate next flow === ') print(' version with bandstructure and dos ') gwsetup(update=False) self.assertTrue(os.path.isdir('SiC_SiC.cif.conv')) print(os.listdir(os.path.join(wdir, 'SiC_SiC.cif.conv', 'w0'))) self.assertEqual(len(os.listdir(os.path.join(wdir, 'SiC_SiC.cif.conv', 'w0'))), 15) print(' ==== copy reference from second flow === ') time.sleep(1) # the .conv directory should be older than the first one shutil.rmtree(os.path.join(wdir, 'SiC_SiC.cif.conv')) shutil.copytree(os.path.join(reference_dir, 'ref_res', 'SiC_SiC.cif.conv'), os.path.join(wdir, 'SiC_SiC.cif.conv')) self.assertTrue(os.path.isdir(os.path.join(wdir, 'SiC_SiC.cif.conv'))) self.assertEqual(len(os.listdir(os.path.join(wdir, 'SiC_SiC.cif.conv', 'w0'))), 13) print(' ==== process output === ') backup = sys.stdout sys.stdout = StringIO() # capture output gwoutput() out = sys.stdout.getvalue() # release output sys.stdout.close() # close the stream sys.stdout = backup # restore original stdout print('=== *** ====\n'+out+'=== *** ====\n') gap = 0 for l in out.split('\n'): if 'values' in l: gap = float(l.split(' ')[6]) self.assertEqual(gap, 7.114950664158926) print(os.listdir('.')) print('processed') self.assertTrue(os.path.isfile('SiC_SiC.cif.full_res')) full_res = read_grid_from_file(s_name(structure)+'.full_res') self.assertEqual(full_res, {u'all_done': True, u'grid': 0}) self.assertTrue(os.path.isdir(os.path.join(wdir, 'SiC_SiC.cif.res'))) self.assertEqual(len(os.listdir(os.path.join(wdir, 'SiC_SiC.cif.res'))), 5) print(os.listdir(os.path.join(wdir, 'SiC_SiC.cif.res'))) msrf = MySigResFile(os.path.join(wdir, 'SiC_SiC.cif.res', 'out_SIGRES.nc')) self.assertEqual(msrf.h**o, 6.6843830378711786) self.assertEqual(msrf.lumo, 8.0650328308487982) self.assertEqual(msrf.homo_gw, 6.2325949743130034) self.assertEqual(msrf.lumo_gw, 8.2504215095164763) self.assertEqual(msrf.fundamental_gap('ks'), msrf.lumo - msrf.h**o) self.assertEqual(msrf.fundamental_gap('gw'), msrf.lumo_gw - msrf.homo_gw) self.assertAlmostEqual(msrf.fundamental_gap('gamma'), gap, places=3) # since we now have a mysigresfile object we test the functionality msrf.get_scissor() # return self.qplist_spin[0].build_scissors(domains=[[-200, mid], [mid, 200]], k=1, plot=False) res = msrf.get_scissor_residues() self.assertEqual(res, [0.05322754684319431, 0.34320373172956475]) # return sc.residues #msrf.plot_scissor(title='') #msrf.plot_qpe(title='') # to be continued if temp_ABINIT_PS is not None: os.environ['ABINIT_PS_EXT'] = temp_ABINIT_PS_EXT os.environ['ABINIT_PS'] = temp_ABINIT_PS
def plot_ion_hull_and_voltages(ion, fmt='pdf'): """ Plots the phase diagram between the pure material and pure ion, Connecting the points on the convex hull of the phase diagram. Args: ion (str): name of atom that was intercalated, e.g. 'Li'. fmt (str): matplotlib format style. Check the matplotlib docs for options. """ # Calculated with the relax() function in # mat2d.stability.startup. If you are using other input # parameters, you need to recalculate these values! ion_ev_fu = {'Li': -1.7540797, 'Mg': -1.31976062, 'Al': -3.19134607} energy = Vasprun('vasprun.xml').final_energy composition = Structure.from_file('POSCAR').composition # Get the formula (with single-digit integers preceded by a '_'). twod_material = list(composition.reduced_formula) twod_formula = str() for i in range(len(twod_material)): try: int(twod_material[i]) twod_formula += '_{}'.format(twod_material[i]) except: twod_formula += twod_material[i] twod_ev_fu = energy / composition.get_reduced_composition_and_factor()[1] data = [(0, 0, 0, twod_ev_fu)] # (at% ion, n_ions, E_F, abs_energy) dirs = [dir for dir in os.listdir(os.getcwd()) if os.path.isdir(dir)] for directory in dirs: if is_converged(directory): os.chdir(directory) energy = Vasprun('vasprun.xml').final_energy composition = Structure.from_file('POSCAR').composition ion_fraction = composition.get_atomic_fraction(ion) no_ion_comp_dict = composition.as_dict() no_ion_comp_dict.update({ion: 0}) no_ion_comp = Composition.from_dict(no_ion_comp_dict) n_twod_fu = no_ion_comp.get_reduced_composition_and_factor()[1] n_ions = composition[ion] / n_twod_fu E_F = ((energy - composition[ion] * ion_ev_fu[ion] - twod_ev_fu * n_twod_fu)/ composition.num_atoms) data.append((ion_fraction, n_ions, E_F, energy / n_twod_fu)) os.chdir('../') data.append((1, 1, 0, ion_ev_fu[ion])) # Pure ion sorted_data = sorted(data, key=operator.itemgetter(0)) # Determine which compositions are on the convex hull. energy_profile = np.array([[item[0], item[2]] for item in sorted_data if item[2] <= 0]) hull = ConvexHull(energy_profile) convex_ion_fractions = [energy_profile[vertex, 0] for vertex in hull.vertices] convex_formation_energies = [energy_profile[vertex, 1] for vertex in hull.vertices] convex_ion_fractions.append(convex_ion_fractions.pop(0)) convex_formation_energies.append(convex_formation_energies.pop(0)) concave_ion_fractions = [pt[0] for pt in sorted_data if pt[0] not in convex_ion_fractions] concave_formation_energies = [pt[2] for pt in sorted_data if pt[0] not in convex_ion_fractions] voltage_profile = [] j = 0 k = 0 for i in range(1, len(sorted_data) - 1): if sorted_data[i][0] in convex_ion_fractions: voltage = -(((sorted_data[i][3] - sorted_data[k][3])- (sorted_data[i][1] - sorted_data[k][1]) * ion_ev_fu[ion]) / (sorted_data[i][1] - sorted_data[k][1])) voltage_profile.append((sorted_data[k][0], voltage)) voltage_profile.append((sorted_data[i][0], voltage)) j += 1 k = i voltage_profile.append((voltage_profile[-1][0], 0)) voltage_profile.append((1, 0)) voltage_profile_x = [tup[0] for tup in voltage_profile] voltage_profile_y = [tup[1] for tup in voltage_profile] ax = plt.figure(figsize=(14, 10)).gca() ax.plot([0, 1], [0, 0], 'k--') ax.plot(convex_ion_fractions, convex_formation_energies, 'b-', marker='o', markersize=12, markeredgecolor='none') ax.plot(concave_ion_fractions, concave_formation_energies, 'r', marker='o', linewidth=0, markersize=12, markeredgecolor='none') ax2 = ax.twinx() ax2.plot(voltage_profile_x, voltage_profile_y, 'k-', marker='o') ax.text(0, 0.002, r'$\mathrm{%s}$' % twod_formula, family='serif', size=24) ax.text(0.99, 0.002, r'$\mathrm{%s}$' % ion, family='serif', size=24, horizontalalignment='right') ax.set_xticklabels(ax.get_xticks(), family='serif', size=20) ax.set_yticklabels(ax.get_yticks(), family='serif', size=20) ax2.set_yticklabels(ax2.get_yticks(), family='serif', size=20) ax.set_xlabel('at% {}'.format(ion), family='serif', size=28) ax.set_ylabel(r'$\mathrm{E_F\/(eV/atom)}$', size=28) ax2.yaxis.set_label_position('right') if ion == 'Li': ax2.set_ylabel(r'$\mathrm{Potential\/vs.\/Li/Li^+\/(V)}$', size=28) elif ion == 'Mg': ax2.set_ylabel(r'$\mathrm{Potential\/vs.\/Mg/Mg^{2+}\/(V)}$', size=28) elif ion == 'Al': ax2.set_ylabel(r'$\mathrm{Potential\/vs.\/Al/Al^{3+}\/(V)}$', size=28) plt.savefig('{}_hull.{}'.format(ion, fmt), transparent=True)
def setUp(self): self.maxDiff = None # trivial example, simple square lattice for testing structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H'], [[0, 0, 0]]) self.square_sg = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) #TODO: decorating still fails because the structure graph gives a CN of 8 for this square lattice # self.square_sg.decorate_structure_with_ce_info() # body-centered square lattice for testing structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H', 'He'], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.bc_square_sg = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(-1, -1, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) # body-centered square lattice for testing # directions reversed, should be equivalent to as bc_square structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H', 'He'], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.bc_square_sg_r = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) self.bc_square_sg_r.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(-1, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(-1, -1, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(0, -1, 0), to_jimage=(0, 0, 0)) # MoS2 example, structure graph obtained from critic2 # (not ground state, from mp-1023924, single layer) stdout_file = os.path.join(os.path.dirname(__file__), "..", "..", "..", 'test_files/critic2/MoS2_critic2_stdout.txt') with open(stdout_file, 'r') as f: reference_stdout = f.read() self.structure = Structure.from_file(os.path.join(os.path.dirname(__file__), "..", "..", "..", 'test_files/critic2/MoS2.cif')) c2o = Critic2Output(self.structure, reference_stdout) self.mos2_sg = c2o.structure_graph(edge_weight="bond_length", edge_weight_units="Å") latt = Lattice.cubic(4.17) species = ["Ni", "O"] coords = [[0, 0, 0], [0.5, 0.5, 0.5]] self.NiO = Structure.from_spacegroup(225, latt, species, coords).get_primitive_structure() # BCC example. self.bcc = Structure(Lattice.cubic(5.0), ['He', 'He'], [[0, 0, 0], [0.5, 0.5, 0.5]]) warnings.simplefilter("ignore")
# make new structure if not matched (not already existed) struc_matched = False find_comp = subs_db.find({ "nspecies": nspecies, "species": species }) for y in find_comp: basedir_comp = x["basedir"] positionfilename_comp = y["positionfile"] struc_comp = StructureNode(basedir_comp) current_dir_comp = struc_comp.get_currentdir() filename_comp = os.path.join(current_dir_comp, positionfilename_comp) struc_comp = Structure.from_file(filename_comp) struc_matcher = StructureMatcher() match = struc_matcher.fit(new_struc, struc_comp) if match: struc_matched = True if not struc_matched: print("new_basedir", new_basedir) metadata = { "purpose": "converged_ionic", "achievement": "to_relax" } structurenode = StructureNode(new_basedir) structurenode.place_files(new_struc, source_uuid=source_uuid, metadata=metadata)
def make_confs(self, path_to_work, path_to_equi, refine=False): path_to_work = os.path.abspath(path_to_work) if os.path.exists(path_to_work): dlog.warning('%s already exists' % path_to_work) else: os.makedirs(path_to_work) path_to_equi = os.path.abspath(path_to_equi) if 'start_confs_path' in self.parameter and os.path.exists( self.parameter['start_confs_path']): init_path_list = glob.glob( os.path.join(self.parameter['start_confs_path'], '*')) struct_init_name_list = [] for ii in init_path_list: struct_init_name_list.append(ii.split('/')[-1]) struct_output_name = path_to_work.split('/')[-2] assert struct_output_name in struct_init_name_list path_to_equi = os.path.abspath( os.path.join(self.parameter['start_confs_path'], struct_output_name, 'relaxation', 'relax_task')) task_list = [] cwd = os.getcwd() equi_contcar = os.path.join(path_to_equi, 'CONTCAR') os.chdir(path_to_work) if os.path.isfile('POSCAR'): os.remove('POSCAR') if os.path.islink('POSCAR'): os.remove('POSCAR') os.symlink(os.path.relpath(equi_contcar), 'POSCAR') # task_poscar = os.path.join(output, 'POSCAR') # stress, deal with unsupported stress in dpdata #with open(os.path.join(path_to_equi, 'result.json')) as fin: # equi_result = json.load(fin) #equi_stress = np.array(equi_result['stress']['data'])[-1] equi_result = loadfn(os.path.join(path_to_equi, 'result.json')) equi_stress = equi_result['stress'][-1] dumpfn(equi_stress, 'equi.stress.json', indent=4) os.chdir(cwd) if refine: print('elastic refine starts') task_list = make_refine(self.parameter['init_from_suffix'], self.parameter['output_suffix'], path_to_work) # record strain # df = Strain.from_deformation(dfm_ss.deformations[idid]) # dumpfn(df.as_dict(), 'strain.json', indent=4) init_from_path = re.sub(self.parameter['output_suffix'][::-1], self.parameter['init_from_suffix'][::-1], path_to_work[::-1], count=1)[::-1] task_list_basename = list(map(os.path.basename, task_list)) for ii in task_list_basename: init_from_task = os.path.join(init_from_path, ii) output_task = os.path.join(path_to_work, ii) os.chdir(output_task) if os.path.isfile('strain.json'): os.remove('strain.json') copyfile(os.path.join(init_from_task, 'strain.json'), 'strain.json') #os.symlink(os.path.relpath( # os.path.join((re.sub(self.parameter['output_suffix'], self.parameter['init_from_suffix'], ii)), # 'strain.json')), # 'strain.json') os.chdir(cwd) else: norm_def = self.norm_deform shear_def = self.shear_deform norm_strains = [ -norm_def, -0.5 * norm_def, 0.5 * norm_def, norm_def ] shear_strains = [ -shear_def, -0.5 * shear_def, 0.5 * shear_def, shear_def ] if not os.path.exists(equi_contcar): raise RuntimeError("please do relaxation first") ss = Structure.from_file(equi_contcar) dfm_ss = DeformedStructureSet(ss, symmetry=False, norm_strains=norm_strains, shear_strains=shear_strains) n_dfm = len(dfm_ss) print('gen with norm ' + str(norm_strains)) print('gen with shear ' + str(shear_strains)) for ii in range(n_dfm): output_task = os.path.join(path_to_work, 'task.%06d' % ii) os.makedirs(output_task, exist_ok=True) os.chdir(output_task) for jj in [ 'INCAR', 'POTCAR', 'POSCAR', 'conf.lmp', 'in.lammps' ]: if os.path.exists(jj): os.remove(jj) task_list.append(output_task) dfm_ss.deformed_structures[ii].to('POSCAR', 'POSCAR') # record strain df = Strain.from_deformation(dfm_ss.deformations[ii]) dumpfn(df.as_dict(), 'strain.json', indent=4) os.chdir(cwd) return task_list
def write_KPOINTS( POSCAR_input: str = "POSCAR", KPOINTS_output="KPOINTS.lobster", reciprocal_density: int = 100, isym: int = -1, from_grid: bool = False, input_grid: list = [5, 5, 5], line_mode: bool = True, kpoints_line_density: int = 20, symprec: float = 0.01, ): """ writes a KPOINT file for lobster (only ISYM=-1 and ISYM=0 are possible), grids are gamma centered Args: POSCAR_input (str): path to POSCAR KPOINTS_output (str): path to output KPOINTS reciprocal_density (int): Grid density isym (int): either -1 or 0. Current Lobster versions only allow -1. from_grid (bool): If True KPOINTS will be generated with the help of a grid given in input_grid. Otherwise, they will be generated from the reciprocal_density input_grid (list): grid to generate the KPOINTS file line_mode (bool): If True, band structure will be generated kpoints_line_density (int): density of the lines in the band structure symprec (float): precision to determine symmetry """ structure = Structure.from_file(POSCAR_input) if not from_grid: kpointgrid = Kpoints.automatic_density_by_vol( structure, reciprocal_density).kpts mesh = kpointgrid[0] else: mesh = input_grid # The following code is taken from: SpacegroupAnalyzer # we need to switch off symmetry here latt = structure.lattice.matrix positions = structure.frac_coords unique_species = [] # type: List[Any] zs = [] magmoms = [] for species, g in itertools.groupby(structure, key=lambda s: s.species): if species in unique_species: ind = unique_species.index(species) zs.extend([ind + 1] * len(tuple(g))) else: unique_species.append(species) zs.extend([len(unique_species)] * len(tuple(g))) for site in structure: if hasattr(site, "magmom"): magmoms.append(site.magmom) elif site.is_ordered and hasattr(site.specie, "spin"): magmoms.append(site.specie.spin) else: magmoms.append(0) # For now, we are setting magmom to zero. (Taken from INCAR class) cell = latt, positions, zs, magmoms # TODO: what about this shift? mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0]) # exit() # get the kpoints for the grid if isym == -1: kpts = [] weights = [] all_labels = [] for gp in grid: kpts.append(gp.astype(float) / mesh) weights.append(float(1)) all_labels.append("") elif isym == 0: # time reversal symmetry: k and -k are equivalent kpts = [] weights = [] all_labels = [] newlist = [list(gp) for gp in list(grid)] mapping = [] for gp in newlist: minus_gp = [-k for k in gp] if minus_gp in newlist and minus_gp not in [[0, 0, 0]]: mapping.append(newlist.index(minus_gp)) else: mapping.append(newlist.index(gp)) for igp, gp in enumerate(newlist): if mapping[igp] > igp: kpts.append(np.array(gp).astype(float) / mesh) weights.append(float(2)) all_labels.append("") elif mapping[igp] == igp: kpts.append(np.array(gp).astype(float) / mesh) weights.append(float(1)) all_labels.append("") else: ValueError("Only isym=-1 and isym=0 are allowed.") # line mode if line_mode: kpath = HighSymmKpath(structure, symprec=symprec) if not np.allclose(kpath.prim.lattice.matrix, structure.lattice.matrix): raise ValueError( "You are not using the standard primitive cell. The k-path is not correct. Please generate a " "standard primitive cell first.") frac_k_points, labels = kpath.get_kpoints( line_density=kpoints_line_density, coords_are_cartesian=False) for k, f in enumerate(frac_k_points): kpts.append(f) weights.append(0.0) all_labels.append(labels[k]) if isym == -1: comment = ("ISYM=-1, grid: " + str(mesh) if not line_mode else "ISYM=-1, grid: " + str(mesh) + " plus kpoint path") elif isym == 0: comment = ("ISYM=0, grid: " + str(mesh) if not line_mode else "ISYM=0, grid: " + str(mesh) + " plus kpoint path") KpointObject = Kpoints( comment=comment, style=Kpoints.supported_modes.Reciprocal, num_kpts=len(kpts), kpts=kpts, kpts_weights=weights, labels=all_labels, ) KpointObject.write_file(filename=KPOINTS_output)
def from_file(cls, fmt, filename=None, structure_file=None, are_coops=False): """ Creates a CompleteCohp object from an output file of a COHP calculation. Valid formats are either LMTO (for the Stuttgart LMTO-ASA code) or LOBSTER (for the LOBSTER code). Args: cohp_file: Name of the COHP output file. Defaults to COPL for LMTO and COHPCAR.lobster/COOPCAR.lobster for LOBSTER. are_coops: Indicates whether the populations are COOPs or COHPs. Defaults to False for COHPs. fmt: A string for the code that was used to calculate the COHPs so that the output file can be handled correctly. Can take the values "LMTO" or "LOBSTER". structure_file: Name of the file containing the structure. If no file name is given, use CTRL for LMTO and POSCAR for LOBSTER. Returns: A CompleteCohp object. """ fmt = fmt.upper() if fmt == "LMTO": # LMTO COOPs and orbital-resolved COHP cannot be handled yet. are_coops = False orb_res_cohp = None if structure_file is None: structure_file = "CTRL" if filename is None: filename = "COPL" cohp_file = LMTOCopl(filename=filename, to_eV=True) elif fmt == "LOBSTER": if structure_file is None: structure_file = "POSCAR" if filename is None: filename = "COOPCAR.lobster" if are_coops \ else "COHPCAR.lobster" warnings.warn( "The bond labels are currently consistent with ICOHPLIST.lobster/ICOOPLIST.lobster, not with " "COHPCAR.lobster/COOPCAR.lobster. Please be aware!") cohp_file = Cohpcar(filename=filename, are_coops=are_coops) orb_res_cohp = cohp_file.orb_res_cohp else: raise ValueError("Unknown format %s. Valid formats are LMTO " "and LOBSTER." % fmt) structure = Structure.from_file(structure_file) efermi = cohp_file.efermi cohp_data = cohp_file.cohp_data energies = cohp_file.energies # Lobster shifts the energies so that the Fermi energy is at zero. # Shifting should be done by the plotter object though. spins = [Spin.up, Spin.down] if cohp_file.is_spin_polarized \ else [Spin.up] if fmt == "LOBSTER": energies += efermi if orb_res_cohp is not None: # If no total COHPs are present, calculate the total # COHPs from the single-orbital populations. Total COHPs # may not be present when the cohpgenerator keyword is used # in LOBSTER versions 2.2.0 and earlier. # TODO: Test this more extensively for label in orb_res_cohp: if cohp_file.cohp_data[label]["COHP"] is None: # print(label) cohp_data[label]["COHP"] = { sp: np.sum([orb_res_cohp[label][orbs]["COHP"][sp] for orbs in orb_res_cohp[label]], axis=0) for sp in spins} if cohp_file.cohp_data[label]["ICOHP"] is None: cohp_data[label]["ICOHP"] = \ {sp: np.sum([orb_res_cohp[label][orbs]["ICOHP"][sp] for orbs in orb_res_cohp[label]], axis=0) for sp in spins} if fmt == "LMTO": # Calculate the average COHP for the LMTO file to be # consistent with LOBSTER output. avg_data = {"COHP": {}, "ICOHP": {}} for i in avg_data: for spin in spins: rows = np.array([cohp_data[label][i][spin] for label in cohp_data]) avg = np.average(rows, axis=0) # LMTO COHPs have 5 significant figures avg_data[i].update({spin: np.array([round_to_sigfigs(a, 5) for a in avg], dtype=float)}) avg_cohp = Cohp(efermi, energies, avg_data["COHP"], icohp=avg_data["ICOHP"]) else: avg_cohp = Cohp(efermi, energies, cohp_data["average"]["COHP"], icohp=cohp_data["average"]["COHP"], are_coops=are_coops) del cohp_data["average"] cohp_dict = {label: Cohp(efermi, energies, cohp_data[label]["COHP"], icohp=cohp_data[label]["ICOHP"], are_coops=are_coops) for label in cohp_data} bond_dict = {label: {"length": cohp_data[label]["length"], "sites": [structure.sites[site] for site in cohp_data[label]["sites"]]} for label in cohp_data} return CompleteCohp(structure, avg_cohp, cohp_dict, bonds=bond_dict, are_coops=are_coops, orb_res_cohp=orb_res_cohp)
def test_writevaspfrominterpolatedposcar(self): nimages = 5 this_image = 1 autosort_tol = 0.5 fw1 = Firework([ CopyVaspOutputs(calc_dir=self.static_outdir, contcar_to_poscar=False, additional_files=["CONTCAR"]), PassCalcLocs(name="fw1") ], name="fw1") fw2 = Firework([ CopyVaspOutputs(calc_dir=self.opt_outdir, contcar_to_poscar=False, additional_files=["CONTCAR"]), PassCalcLocs(name="fw2") ], name="fw2") fw3 = Firework([ WriteVaspFromIOSetFromInterpolatedPOSCAR( start="fw1", end="fw2", this_image=this_image, nimages=nimages, autosort_tol=autosort_tol, vasp_input_set="MPStaticSet"), PassCalcLocs(name="fw3") ], name="fw3", parents=[fw1, fw2]) fw4 = Firework([PassCalcLocs(name="fw4")], name="fw4", parents=fw3) wf = Workflow([fw1, fw2, fw3, fw4]) self.lp.add_wf(wf) rapidfire(self.lp) fw4 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw4"})[0]) calc_locs = fw4.spec["calc_locs"] print(get_calc_loc("fw3", calc_locs)["path"]) # Check existence of structure files. self.assertTrue( os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR")) self.assertTrue( os.path.exists( get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_0")) self.assertTrue( os.path.exists( get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_1")) self.assertTrue( os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/INCAR")) self.assertTrue( os.path.exists( get_calc_loc("fw3", calc_locs)["path"] + "/KPOINTS")) self.assertTrue( os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/POTCAR")) # Check interpolation. struct_start = Structure.from_file( get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_0") struct_end = Structure.from_file( get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_1") struct_inter = Structure.from_file( get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR") structs = struct_start.interpolate(struct_end, nimages, interpolate_lattices=True, autosort_tol=autosort_tol) # Check x of 1st site. self.assertAlmostEqual(structs[this_image][1].coords[0], struct_inter[1].coords[0]) # Check c lattice parameter self.assertAlmostEqual(structs[this_image].lattice.abc[0], struct_inter.lattice.abc[0])
def standard_calculations_from_vasp_files( cls, POSCAR_input: str = "POSCAR", INCAR_input: str = "INCAR", POTCAR_input: str | None = None, dict_for_basis: dict | None = None, option: str = "standard", ): """ will generate Lobsterin with standard settings Args: POSCAR_input(str): path to POSCAR INCAR_input(str): path to INCAR POTCAR_input (str): path to POTCAR dict_for_basis (dict): can be provided: it should look the following: dict_for_basis={"Fe":'3p 3d 4s 4f', "C": '2s 2p'} and will overwrite all settings from POTCAR_input option (str): 'standard' will start a normal lobster run where COHPs, COOPs, DOS, CHARGE etc. will be calculated 'standard_from_projection' will start a normal lobster run from a projection 'standard_with_fatband' will do a fatband calculation, run over all orbitals 'onlyprojection' will only do a projection 'onlydos' will only calculate a projected dos 'onlycohp' will only calculate cohp 'onlycoop' will only calculate coop 'onlycohpcoop' will only calculate cohp and coop Returns: Lobsterin Object with standard settings """ warnings.warn( "Always check and test the provided basis functions. The spilling of your Lobster calculation might help" ) # warn that fatband calc cannot be done with tetrahedron method at the moment if option not in [ "standard", "standard_from_projection", "standard_with_fatband", "onlyprojection", "onlydos", "onlycohp", "onlycoop", "onlycobi", "onlycohpcoop", "onlycohpcoopcobi", "onlymadelung", ]: raise ValueError("The option is not valid!") Lobsterindict = {} # type: Dict[Any,Any] # this basis set covers most elements Lobsterindict["basisSet"] = "pbeVaspFit2015" # energies around e-fermi Lobsterindict["COHPstartEnergy"] = -35.0 Lobsterindict["COHPendEnergy"] = 5.0 if option in [ "standard", "onlycohp", "onlycoop", "onlycobi", "onlycohpcoop", "onlycohpcoopcobi", "standard_with_fatband", ]: # every interaction with a distance of 6.0 is checked Lobsterindict["cohpGenerator"] = "from 0.1 to 6.0 orbitalwise" # the projection is saved Lobsterindict["saveProjectionToFile"] = True if option == "standard_from_projection": Lobsterindict["cohpGenerator"] = "from 0.1 to 6.0 orbitalwise" Lobsterindict["loadProjectionFromFile"] = True # TODO: add cobi here! might be relevant lobster version if option == "onlycohp": Lobsterindict["skipdos"] = True Lobsterindict["skipcoop"] = True Lobsterindict["skipPopulationAnalysis"] = True Lobsterindict["skipGrossPopulation"] = True # lobster-4.1.0 Lobsterindict["skipcobi"] = True Lobsterindict["skipMadelungEnergy"] = True if option == "onlycoop": Lobsterindict["skipdos"] = True Lobsterindict["skipcohp"] = True Lobsterindict["skipPopulationAnalysis"] = True Lobsterindict["skipGrossPopulation"] = True # lobster-4.1.0 Lobsterindict["skipcobi"] = True Lobsterindict["skipMadelungEnergy"] = True if option == "onlycohpcoop": Lobsterindict["skipdos"] = True Lobsterindict["skipPopulationAnalysis"] = True Lobsterindict["skipGrossPopulation"] = True # lobster-4.1.0 Lobsterindict["skipcobi"] = True Lobsterindict["skipMadelungEnergy"] = True if option == "onlycohpcoopcobi": Lobsterindict["skipdos"] = True Lobsterindict["skipPopulationAnalysis"] = True Lobsterindict["skipGrossPopulation"] = True Lobsterindict["skipMadelungEnergy"] = True if option == "onlydos": Lobsterindict["skipcohp"] = True Lobsterindict["skipcoop"] = True Lobsterindict["skipPopulationAnalysis"] = True Lobsterindict["skipGrossPopulation"] = True # lobster-4.1.0 Lobsterindict["skipcobi"] = True Lobsterindict["skipMadelungEnergy"] = True if option == "onlyprojection": Lobsterindict["skipdos"] = True Lobsterindict["skipcohp"] = True Lobsterindict["skipcoop"] = True Lobsterindict["skipPopulationAnalysis"] = True Lobsterindict["skipGrossPopulation"] = True Lobsterindict["saveProjectionToFile"] = True # lobster-4.1.0 Lobsterindict["skipcobi"] = True Lobsterindict["skipMadelungEnergy"] = True if option == "onlycobi": Lobsterindict["skipdos"] = True Lobsterindict["skipcohp"] = True Lobsterindict["skipPopulationAnalysis"] = True Lobsterindict["skipGrossPopulation"] = True # lobster-4.1.0 Lobsterindict["skipcobi"] = True Lobsterindict["skipMadelungEnergy"] = True if option == "onlymadelung": Lobsterindict["skipdos"] = True Lobsterindict["skipcohp"] = True Lobsterindict["skipcoop"] = True Lobsterindict["skipPopulationAnalysis"] = True Lobsterindict["skipGrossPopulation"] = True Lobsterindict["saveProjectionToFile"] = True # lobster-4.1.0 Lobsterindict["skipcobi"] = True incar = Incar.from_file(INCAR_input) if incar["ISMEAR"] == 0: Lobsterindict["gaussianSmearingWidth"] = incar["SIGMA"] if incar["ISMEAR"] != 0 and option == "standard_with_fatband": raise ValueError( "ISMEAR has to be 0 for a fatband calculation with Lobster") if dict_for_basis is not None: # dict_for_basis={"Fe":'3p 3d 4s 4f', "C": '2s 2p'} # will just insert this basis and not check with poscar basis = [ key + " " + value for key, value in dict_for_basis.items() ] elif POTCAR_input is not None: # get basis from POTCAR potcar_names = Lobsterin._get_potcar_symbols( POTCAR_input=POTCAR_input) basis = Lobsterin.get_basis( structure=Structure.from_file(POSCAR_input), potcar_symbols=potcar_names) else: raise ValueError("basis cannot be generated") Lobsterindict["basisfunctions"] = basis if option == "standard_with_fatband": Lobsterindict["createFatband"] = basis return cls(Lobsterindict)