示例#1
0
文件: generate.py 项目: wangvei/spyns
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
示例#2
0
 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))
示例#3
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)
示例#4
0
    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
示例#5
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)
示例#6
0
    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
示例#7
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
示例#8
0
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")
示例#9
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):
    """
    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