def make_supercell( cell_structure: pmg.Structure, scaling_matrix: Optional[ScalingMatrix] = None, scaling_factors: Optional[Tuple[int, int, int]] = None, ) -> pmg.Structure: """Transforms a pymatgen ``Structure`` object into a supercell according to the scaling parameters. :param cell_structure: A pymatgen ``Structure`` object. :param scaling_matrix: A matrix of transforming the lattice vectors. Has to be all integers. e.g., [[2,1,0],[0,3,0],[0,0,1]] generates a new structure with lattice vectors a" = 2a + b, b" = 3b, c" = c where a, b, and c are the lattice vectors of the original structure. :param scaling_factors: A tuple of three numbers used to scale each lattice vector. Same as: ``scaling_matrix=[[scale_a, 0, 0], [0, scale_b, 0], [0, 0, scale_c]]`` :return: A pymatgen ``Structure`` object. """ if scaling_matrix is not None: cell_transformation: SupercellTransformation = SupercellTransformation( scaling_matrix=scaling_matrix) return cell_transformation.apply_transformation(cell_structure) elif scaling_factors is not None: cell_transformation = SupercellTransformation.from_scaling_factors( scale_a=scaling_factors[0], scale_b=scaling_factors[1], scale_c=scaling_factors[2], ) return cell_transformation.apply_transformation(cell_structure) else: return cell_structure
def test_from_scaling_factors(self): scale_factors = [random.randint(1, 5) for i in range(3)] t = SupercellTransformation.from_scaling_factors(*scale_factors) s = t.apply_transformation(self.struct) self.assertEqual( s.num_sites, 4 * functools.reduce(lambda a, b: a * b, scale_factors))
def test_append_transformation(self): t = SubstitutionTransformation({"Fe": "Mn"}) self.trans.append_transformation(t) self.assertEqual( "NaMnPO4", self.trans.final_structure.composition.reduced_formula) self.assertEqual(len(self.trans.structures), 3) coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = [ [3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603], ] struct = Structure(lattice, ["Si4+", "Si4+"], coords) ts = TransformedStructure(struct, []) ts.append_transformation( SupercellTransformation.from_scaling_factors(2, 1, 1)) alt = ts.append_transformation( PartialRemoveSpecieTransformation( "Si4+", 0.5, algo=PartialRemoveSpecieTransformation.ALGO_COMPLETE), 5, ) self.assertEqual(len(alt), 2)
def create_input(self): """ create input for all the benchmark calculations :return 0 on succes """ self.reset_bar() print('testing executable %s' % self.subject) print( "creating input for %s system sizes and %s calculations per size:" % (len(self.sizes), int(self.total / len(self.sizes)))) sys.stdout.write(self.bar_len * "-" + "\n") sys.stdout.flush() for s in self.sizes: sys.stdout.write("|") sys.stdout.flush() struc = copy.deepcopy(self.structure) trans = SupercellTransformation.from_scaling_factors(scale_a=s, scale_b=s, scale_c=s) struc = trans.apply_transformation(struc) for n in self.np_list: if self.kpar: kpar = itr(n) else: kpar = 1 self.inpset.incar_settings.update({'KPAR': kpar}) for x in self.parameter_lists: for o in self.parameter_lists[x]: sys.stdout.write("*") sys.stdout.flush() v = functions(x)(o, int(n / kpar)) self.inpset.incar_settings.update({x: v}) path = '%s_super%s_par%s%s%s' % (self.name, s, n, x, o) path = os.path.join(os.getcwd(), path) self.inpset.incar_settings.update( {'system': '%s_super%s' % (self.name, s)}) self.inpset.write_input(structure=struc, output_dir=path) q = self.manager.qadapter q.set_mpi_procs(n) job_string = q.get_script_str( job_name=self.name + 's' + str(s) + 'np' + str(n), executable=self.subject, launch_dir=path, partition=None, qerr_path='qerr.out', qout_path='qout.out') self.script_list.append(os.path.join(path, 'job.sh')) f = open(self.script_list[-1], 'w') f.write(job_string) f.close() sys.stdout.write("|\n") sys.stdout.flush() return 0
def test_append_transformation(self): t = SubstitutionTransformation({"Fe":"Mn"}) self.trans.append_transformation(t) self.assertEqual("NaMnPO4", self.trans.final_structure.composition.reduced_formula) self.assertEqual(len(self.trans.structures), 3) coords = list() coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = [[ 3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]] struct = Structure(lattice, ["Si4+", "Si4+"], coords) ts = TransformedStructure(struct, []) ts.append_transformation(SupercellTransformation.from_scaling_factors(2, 1, 1)) alt = ts.append_transformation(PartialRemoveSpecieTransformation('Si4+', 0.5, algo=PartialRemoveSpecieTransformation.ALGO_COMPLETE), 5) self.assertEqual(len(alt), 2)
def create_input(self): """ create input for all the benchmark calculations :return 0 on succes """ self.reset_bar() print('testing executable %s' % self.subject) print("creating input for %s system sizes and %s calculations per size:" % (len(self.sizes), int(self.total / len(self.sizes)))) sys.stdout.write(self.bar_len*"-"+"\n") sys.stdout.flush() for s in self.sizes: sys.stdout.write("|") sys.stdout.flush() struc = copy.deepcopy(self.structure) trans = SupercellTransformation.from_scaling_factors(scale_a=s, scale_b=s, scale_c=s) struc = trans.apply_transformation(struc) for n in self.np_list: if self.kpar: kpar = itr(n) else: kpar = 1 self.inpset.incar_settings.update({'KPAR': kpar}) for x in self.parameter_lists: for o in self.parameter_lists[x]: sys.stdout.write("*") sys.stdout.flush() v = functions(x)(o, int(n/kpar)) self.inpset.incar_settings.update({x: v}) path = '%s_super%s_par%s%s%s' % (self.name, s, n, x, o) path = os.path.join(os.getcwd(), path) self.inpset.incar_settings.update({'system': '%s_super%s' % (self.name, s)}) self.inpset.write_input(structure=struc, output_dir=path) q = self.manager.qadapter q.set_mpi_procs(n) job_string = q.get_script_str(job_name=self.name+'s'+str(s)+'np'+str(n), executable=self.subject, launch_dir=path, partition=None, qerr_path='qerr.out', qout_path='qout.out') self.script_list.append(os.path.join(path, 'job.sh')) f = open(self.script_list[-1], 'w') f.write(job_string) f.close() sys.stdout.write("|\n") sys.stdout.flush() return 0
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