def test_wf_functions(self): # Test slab trans params generator for slab in self.slabs: trans_params = get_slab_trans_params(slab) trans = SlabTransformation(**trans_params) new_slab = trans.apply_transformation(slab.oriented_unit_cell) self.assertTrue(np.allclose(new_slab.cart_coords, slab.cart_coords)) self.assertTrue(np.allclose(new_slab.lattice.matrix, slab.lattice.matrix)) # Try something a bit more complicated formulas = ['Si', 'Sn', 'SrTiO3', 'Li2O'] structs = [PymatgenTest.get_structure(s) for s in formulas] for struct in structs: slabs = generate_all_slabs(struct, max_index=2, min_slab_size=10, min_vacuum_size=20) for slab in slabs: trans_params = get_slab_trans_params(slab) trans = SlabTransformation(**trans_params) new_slab = trans.apply_transformation(slab.oriented_unit_cell) old_coords = np.around(slab.frac_coords, 10) % 1 new_coords = np.around(new_slab.frac_coords, 10) % 1 self.assertTrue(np.allclose(old_coords, new_coords)) self.assertTrue(np.allclose(new_slab.lattice.matrix, slab.lattice.matrix))
def test_apply_transformation(self): trans = SubstituteSurfaceSiteTransformation("Au") pt = Structure(Lattice.cubic(5), ["Pt"], [[0, 0, 0]]) # fictitious slab = SlabTransformation([0, 0, 1], 20, 10).apply_transformation(pt) out = trans.apply_transformation(slab) self.assertEqual(out.composition.reduced_formula, "Pt3Au")
def test_apply_transformation(self): co = Molecule(["C", "O"], [[0, 0, 0], [0, 0, 1.23]]) trans = AddAdsorbateTransformation(co) pt = Structure(Lattice.cubic(5), ["Pt"], [[0, 0, 0]]) # fictitious slab = SlabTransformation([0, 0, 1], 20, 10).apply_transformation(pt) out = trans.apply_transformation(slab) self.assertEqual(out.composition.reduced_formula, "Pt4CO")
def test_apply_transformation(self): s = self.get_structure("LiFePO4") trans = SlabTransformation([0, 0, 1], 10, 10, shift = 0.25) gen = SlabGenerator(s, [0, 0, 1], 10, 10) slab_from_gen = gen.get_slab(0.25) slab_from_trans = trans.apply_transformation(s) self.assertArrayAlmostEqual(slab_from_gen.lattice.matrix, slab_from_trans.lattice.matrix) self.assertArrayAlmostEqual(slab_from_gen.cart_coords, slab_from_trans.cart_coords) fcc = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) trans = SlabTransformation([1, 1, 1], 10, 10) slab_from_trans = trans.apply_transformation(fcc) gen = SlabGenerator(fcc, [1, 1, 1], 10, 10) slab_from_gen = gen.get_slab() self.assertArrayAlmostEqual(slab_from_gen.lattice.matrix, slab_from_trans.lattice.matrix) self.assertArrayAlmostEqual(slab_from_gen.cart_coords, slab_from_trans.cart_coords)
def test_wf_functions(self): # Test slab trans params generator for slab in self.slabs: trans_params = get_slab_trans_params(slab) trans = SlabTransformation(**trans_params) new_slab = trans.apply_transformation(slab.oriented_unit_cell) self.assertTrue(np.allclose(new_slab.cart_coords, slab.cart_coords)) self.assertTrue( np.allclose(new_slab.lattice.matrix, slab.lattice.matrix)) # Try something a bit more complicated formulas = ['Si', 'Sn', 'SrTiO3', 'Li2O'] structs = [PymatgenTest.get_structure(s) for s in formulas] for struct in structs: slabs = generate_all_slabs(struct, max_index=2, min_slab_size=10, min_vacuum_size=20) for slab in slabs: trans_params = get_slab_trans_params(slab) trans = SlabTransformation(**trans_params) new_slab = trans.apply_transformation(slab.oriented_unit_cell) old_coords = np.around(slab.frac_coords, 10) % 1 new_coords = np.around(new_slab.frac_coords, 10) % 1 self.assertTrue(np.allclose(old_coords, new_coords)) self.assertTrue( np.allclose(new_slab.lattice.matrix, slab.lattice.matrix))
def test_apply_transformation(self): s = self.get_structure("LiFePO4") trans = SlabTransformation([0, 0, 1], 10, 10, shift=0.25) gen = SlabGenerator(s, [0, 0, 1], 10, 10) slab_from_gen = gen.get_slab(0.25) slab_from_trans = trans.apply_transformation(s) self.assertArrayAlmostEqual(slab_from_gen.lattice.matrix, slab_from_trans.lattice.matrix) self.assertArrayAlmostEqual(slab_from_gen.cart_coords, slab_from_trans.cart_coords) fcc = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3), ["Fe"], [[0, 0, 0]]) trans = SlabTransformation([1, 1, 1], 10, 10) slab_from_trans = trans.apply_transformation(fcc) gen = SlabGenerator(fcc, [1, 1, 1], 10, 10) slab_from_gen = gen.get_slab() self.assertArrayAlmostEqual(slab_from_gen.lattice.matrix, slab_from_trans.lattice.matrix) self.assertArrayAlmostEqual(slab_from_gen.cart_coords, slab_from_trans.cart_coords)
def get_slab_fw(slab, transmuter=False, db_file=None, vasp_input_set=None, parents=None, vasp_cmd="vasp", name="", add_slab_metadata=True, user_incar_settings=None): """ Function to generate a a slab firework. Returns a TransmuterFW if bulk_structure is specified, constructing the necessary transformations from the slab and slab generator parameters, or an OptimizeFW if only a slab is specified. Args: slab (Slab or Structure): structure or slab corresponding to the slab to be calculated transmuter (bool): whether or not to use a TransmuterFW based on slab params, if this option is selected, input slab must be a Slab object (as opposed to Structure) vasp_input_set (VaspInputSet): vasp_input_set corresponding to the slab calculation parents (Fireworks or list of ints): parent FWs db_file (string): path to database file vasp_cmd (string): vasp command name (string): name of firework add_slab_metadata (bool): whether to add slab metadata to task doc Returns: Firework corresponding to slab calculation """ vasp_input_set = vasp_input_set or MPSurfaceSet( slab, user_incar_settings=user_incar_settings) # If a bulk_structure is specified, generate the set of transformations, # else just create an optimize FW with the slab if transmuter: if not isinstance(slab, Slab): raise ValueError( "transmuter mode requires slab to be a Slab object") # Get transformation from oriented bulk and slab oriented_bulk = slab.oriented_unit_cell slab_trans_params = get_slab_trans_params(slab) trans_struct = SlabTransformation(**slab_trans_params) slab_from_bulk = trans_struct.apply_transformation(oriented_bulk) # Ensures supercell construction supercell_trans = SupercellTransformation.from_scaling_factors( round(slab.lattice.a / slab_from_bulk.lattice.a), round(slab.lattice.b / slab_from_bulk.lattice.b)) # Get site properties, set velocities to zero if not set to avoid # custodian issue site_props = slab.site_properties if 'velocities' not in site_props: site_props['velocities'] = [0. for s in slab] # Get adsorbates for InsertSitesTransformation if "adsorbate" in slab.site_properties.get("surface_properties", ""): ads_sites = [ site for site in slab if site.properties["surface_properties"] == "adsorbate" ] else: ads_sites = [] transformations = [ "SlabTransformation", "SupercellTransformation", "InsertSitesTransformation", "AddSitePropertyTransformation" ] trans_params = [ slab_trans_params, { "scaling_matrix": supercell_trans.scaling_matrix }, { "species": [site.species_string for site in ads_sites], "coords": [site.frac_coords for site in ads_sites] }, { "site_properties": site_props } ] fw = TransmuterFW(name=name, structure=oriented_bulk, transformations=transformations, transformation_params=trans_params, copy_vasp_outputs=True, db_file=db_file, vasp_cmd=vasp_cmd, parents=parents, vasp_input_set=vasp_input_set) else: fw = OptimizeFW(name=name, structure=slab, vasp_input_set=vasp_input_set, vasp_cmd=vasp_cmd, db_file=db_file, parents=parents, job_type="normal") # Add slab metadata if add_slab_metadata: parent_structure_metadata = get_meta_from_structure( slab.oriented_unit_cell) fw.tasks[-1]["additional_fields"].update({ "slab": slab, "parent_structure": slab.oriented_unit_cell, "parent_structure_metadata": parent_structure_metadata }) return fw
def get_slab_fw(slab, bulk_structure=None, slab_gen_params={}, db_file=None, vasp_input_set=None, parents=None, vasp_cmd="vasp", name=""): """ Function to generate a a slab firework. Returns a TransmuterFW if bulk_structure is specified, constructing the necessary transformations from the slab and slab generator parameters, or an OptimizeFW if only a slab is specified. Args: slab (Slab or Structure): structure or slab corresponding to the slab to be calculated bulk_structure (Structure): bulk structure corresponding to slab, if provided, slab firework is constructed as a TransmuterFW using the necessary transformations to get the slab from the bulk slab_gen_params (dict): dictionary of slab generation parameters used to generate the slab, necessary to get the slab that corresponds to the bulk structure vasp_input_set (VaspInputSet): vasp_input_set corresponding to the slab calculation parents (Fireworks or list of ints): parent FWs db_file (string): path to database file vasp_cmd (string): vasp command Returns: Firework """ vasp_input_set = vasp_input_set or MVLSlabSet(slab) # If a bulk_structure is specified, generate the set of transformations, else # just create an optimize FW with the slab if bulk_structure: if not isinstance(slab, Slab): raise ValueError( "structure input to get_slab_fw requires slab to be a slab object!" ) slab_trans_params = { "miller_index": slab.miller_index, "shift": slab.shift } slab_trans_params.update(slab_gen_params) # Get supercell parameters trans_struct = SlabTransformation(**slab_trans_params) slab_from_bulk = trans_struct.apply_transformation(bulk_structure) supercell_trans = SupercellTransformation.from_scaling_factors( round(slab.lattice.a / slab_from_bulk.lattice.a), round(slab.lattice.b / slab_from_bulk.lattice.b)) # Get adsorbates for InsertSitesTransformation if "adsorbate" in slab.site_properties.get("surface_properties", [None]): ads_sites = [ site for site in slab if site.properties["surface_properties"] == "adsorbate" ] else: ads_sites = [] transformations = [ "SlabTransformation", "SupercellTransformation", "InsertSitesTransformation", "AddSitePropertyTransformation" ] trans_params = [ slab_trans_params, { "scaling_matrix": supercell_trans.scaling_matrix }, { "species": [site.species_string for site in ads_sites], "coords": [site.frac_coords for site in ads_sites] }, { "site_properties": slab.site_properties } ] return TransmuterFW(name=name, structure=bulk_structure, transformations=transformations, transformation_params=trans_params, copy_vasp_outputs=True, db_file=db_file, vasp_cmd=vasp_cmd, parents=parents, vasp_input_set=vasp_input_set) else: return OptimizeFW(name=name, structure=slab, vasp_input_set=vasp_input_set, vasp_cmd=vasp_cmd, db_file=db_file, parents=parents, job_type="normal")
def get_slab_fw(slab, transmuter=False, db_file=None, vasp_input_set=None, parents=None, vasp_cmd="vasp", name="", add_slab_metadata=True): """ Function to generate a a slab firework. Returns a TransmuterFW if bulk_structure is specified, constructing the necessary transformations from the slab and slab generator parameters, or an OptimizeFW if only a slab is specified. Args: slab (Slab or Structure): structure or slab corresponding to the slab to be calculated transmuter (bool): whether or not to use a TransmuterFW based on slab params, if this option is selected, input slab must be a Slab object (as opposed to Structure) vasp_input_set (VaspInputSet): vasp_input_set corresponding to the slab calculation parents (Fireworks or list of ints): parent FWs db_file (string): path to database file vasp_cmd (string): vasp command name (string): name of firework add_slab_metadata (bool): whether to add slab metadata to task doc Returns: Firework corresponding to slab calculation """ vasp_input_set = vasp_input_set or MPSurfaceSet(slab) # If a bulk_structure is specified, generate the set of transformations, # else just create an optimize FW with the slab if transmuter: if not isinstance(slab, Slab): raise ValueError("transmuter mode requires slab to be a Slab object") # Get transformation from oriented bulk and slab oriented_bulk = slab.oriented_unit_cell slab_trans_params = get_slab_trans_params(slab) trans_struct = SlabTransformation(**slab_trans_params) slab_from_bulk = trans_struct.apply_transformation(oriented_bulk) # Ensures supercell construction supercell_trans = SupercellTransformation.from_scaling_factors( round(slab.lattice.a / slab_from_bulk.lattice.a), round(slab.lattice.b / slab_from_bulk.lattice.b)) # Get site properties, set velocities to zero if not set to avoid # custodian issue site_props = slab.site_properties if 'velocities' not in site_props: site_props['velocities'] = [0. for s in slab] # Get adsorbates for InsertSitesTransformation if "adsorbate" in slab.site_properties.get("surface_properties", ""): ads_sites = [site for site in slab if site.properties["surface_properties"] == "adsorbate"] else: ads_sites = [] transformations = [ "SlabTransformation", "SupercellTransformation", "InsertSitesTransformation", "AddSitePropertyTransformation"] trans_params = [slab_trans_params, {"scaling_matrix": supercell_trans.scaling_matrix}, {"species": [site.species_string for site in ads_sites], "coords": [site.frac_coords for site in ads_sites]}, {"site_properties": site_props}] fw = TransmuterFW(name=name, structure=oriented_bulk, transformations=transformations, transformation_params=trans_params, copy_vasp_outputs=True, db_file=db_file, vasp_cmd=vasp_cmd, parents=parents, vasp_input_set=vasp_input_set) else: fw = OptimizeFW(name=name, structure=slab, vasp_input_set=vasp_input_set, vasp_cmd=vasp_cmd, db_file=db_file, parents=parents, job_type="normal") # Add slab metadata if add_slab_metadata: parent_structure_metadata = get_meta_from_structure( slab.oriented_unit_cell) fw.tasks[-1]["additional_fields"].update( {"slab": slab, "parent_structure": slab.oriented_unit_cell, "parent_structure_metadata": parent_structure_metadata}) return fw