Ejemplo n.º 1
0
    def __init__(self,
                 directory,
                 nimages,
                 functional,
                 is_metal=False,
                 is_migration=False,
                 in_custodian=False,
                 number_nodes=None):
        """
        Create a FireWork for performing an NEB calculation.

        Args:
            directory (str): Directory in which the NEB calculation should be performed.
            nimages (int): Number of images to use for the NEB calculation.
            functional (tuple): Tuple with the functional choices. The first element
                contains a string that indicates the functional used ("pbe", "hse", ...),
                whereas the second element contains a dictionary that allows the user
                to specify the various functional tags.
            in_custodian (bool): Flag that indicates whether the calculation should be
                run inside a Custodian.
            is_metal (bool): Flag that indicates the material being studied is a
                metal, which changes the smearing from Gaussian to second order
                Methfessel-Paxton of 0.2 eV.
            is_migration (bool): Flag that indicates that the transition is a migration
                of an atom in the structure.
            number_nodes (int): Number of nodes that should be used for the calculations.
                Is required to add the proper `_category` to the Firework generated, so
                it is picked up by the right Fireworker.

        Returns:
            Firework: A firework that represents an NEB calculation.

        """
        # Create the PyTask that sets up the calculation
        setup_neb = PyTask(func="pybat.cli.commands.setup.neb",
                           kwargs={
                               "directory": directory,
                               "nimages": nimages,
                               "functional": functional,
                               "is_metal": is_metal,
                               "is_migration": is_migration
                           })

        # Create the PyTask that runs the calculation
        if in_custodian:
            vasprun = CustodianTask(directory=directory)
        else:
            vasprun = VaspTask(directory=directory)

        # Add number of nodes to spec, or "none"
        firework_spec = {"_launch_dir": os.getcwd()}
        if number_nodes is None:
            firework_spec.update({"_category": "none"})
        else:
            firework_spec.update({"_category": str(number_nodes) + "nodes"})

        # Combine the two FireTasks into one FireWork
        super(NebFirework, self).__init__(tasks=[setup_neb, vasprun],
                                          name="NEB calculation",
                                          spec=firework_spec)
Ejemplo n.º 2
0
    def __init__(self,
                 structure_file,
                 functional,
                 directory,
                 write_chgcar=False,
                 in_custodian=False,
                 number_nodes=None):
        """
        Create a FireWork for performing an SCF calculation.

        Args:
            structure_file (str): Path to the geometry file of the structure.
            functional (tuple): Tuple with the functional choices. The first element
                contains a string that indicates the functional used ("pbe", "hse", ...),
                whereas the second element contains a dictionary that allows the user
                to specify the various functional tags.
            directory (str): Directory in which the SCF calculation should be performed.
            write_chgcar (bool): Flag that indicates whether the CHGCAR file should
                be written.
            in_custodian (bool): Flag that indicates whether the calculation should be
                run inside a Custodian.
            number_nodes (int): Number of nodes that should be used for the calculations.
                Is required to add the proper `_category` to the Firework generated, so
                it is picked up by the right Fireworker.

        Returns:
            Firework: A firework that represents an SCF calculation.

        """
        # Create the PyTask that sets up the calculation
        setup_scf = PyTask(func="pybat.cli.commands.setup.scf",
                           kwargs={
                               "structure_file": structure_file,
                               "functional": functional,
                               "calculation_dir": directory,
                               "write_chgcar": write_chgcar
                           })

        # Create the PyTask that runs the calculation
        if in_custodian:
            vasprun = CustodianTask(directory=directory)
        else:
            vasprun = VaspTask(directory=directory)

        # Add number of nodes to spec, or "none"
        firework_spec = {"_launch_dir": os.getcwd()}
        if number_nodes is None:
            firework_spec.update({"_category": "none"})
        else:
            firework_spec.update({"_category": str(number_nodes) + "nodes"})

        # Combine the two FireTasks into one FireWork
        super(ScfFirework, self).__init__(tasks=[setup_scf, vasprun],
                                          name="SCF calculation",
                                          spec=firework_spec)
Ejemplo n.º 3
0
    def __init__(self,
                 structure_file,
                 functional,
                 directory,
                 is_metal=False,
                 in_custodian=False,
                 number_nodes=None,
                 fw_action=None):

        # Create the PyTask that sets up the calculation
        setup_relax = PyTask(func="pybat.cli.commands.setup.relax",
                             kwargs={
                                 "structure_file": structure_file,
                                 "functional": functional,
                                 "calculation_dir": directory,
                                 "is_metal": is_metal
                             })

        # Create the PyTask that runs the calculation
        if in_custodian:
            vasprun = CustodianTask(directory=directory)
        else:
            vasprun = VaspTask(directory=directory)

        # Extract the final cathode from the geometry optimization
        get_cathode = PyTask(func="pybat.cli.commands.get.get_cathode",
                             kwargs={
                                 "directory": os.path.join(directory),
                                 "write_cif": True
                             })

        # Create the PyTask that check the Pulay stresses
        pulay_task = PulayTask(directory=directory,
                               in_custodian=in_custodian,
                               number_nodes=number_nodes,
                               fw_action=fw_action)

        # Only add number of nodes to spec if specified
        firework_spec = {"_launch_dir": os.getcwd()}
        if number_nodes is None:
            firework_spec.update({"_category": "none"})
        else:
            firework_spec.update({"_category": str(number_nodes) + "nodes"})

        # Combine the FireTasks into one FireWork
        super(RelaxFirework, self).__init__(
            tasks=[setup_relax, vasprun, get_cathode, pulay_task],
            name="Geometry optimization",
            spec=firework_spec)
Ejemplo n.º 4
0
def migration_workflow(structure_file, migration_indices=(0, 0),
                       functional=("pbe", {}), is_metal=False,
                       in_custodian=False, number_nodes=None):
    """
    Set up a workflow that calculates the thermodynamics for a migration in
    the current directory.

    Can later be expanded to also include kinetic barrier calculation.

    Args:
        structure_file (str): Structure file of the cathode material. Note
            that the structure file should be a json format file that is
            derived from the Cathode class, i.e. it should contain the cation
            configuration of the structure.
        migration_indices (tuple): Tuple of the indices which designate the
            migrating site and the vacant site to which the cation will
            migrate. If no indices are provided, the user will be prompted.
        functional (tuple): Tuple with the functional choices. The first element
            contains a string that indicates the functional used ("pbe", "hse", ...),
            whereas the second element contains a dictionary that allows the user
            to specify the various functional tags.
        is_metal (bool): Flag that indicates the material being studied is a
            metal, which changes the smearing from Gaussian to second order
            Methfessel-Paxton of 0.2 eV. Defaults to False.
        in_custodian (bool): Flag that indicates that the calculations
            should be run within a Custodian. Defaults to False.
        number_nodes (int): Number of nodes that should be used for the calculations.
            Is required to add the proper `_category` to the Firework generated, so
            it is picked up by the right Fireworker.

    """

    # TODO Add setup steps to the workflow
    # In case adjustments need to made to the setup of certain calculations,
    #  after which the calculation needs to be rerun, not adding the setup
    # steps to the workflow means that these will have to be rerun manually,
    #  instead of simply relying on the fireworks commands.

    # Let the user define a migration
    migration_dir = define_migration(structure_file=structure_file,
                                     migration_indices=migration_indices,
                                     write_cif=True)

    # Set up the transition calculation
    transition(directory=migration_dir,
               functional=functional,
               is_metal=is_metal,
               is_migration=False)

    # Create the PyTask that runs the calculation
    if in_custodian:
        vasprun = CustodianTask(directory=os.path.join(migration_dir, "final"))
    else:
        vasprun = VaspTask(directory=os.path.join(migration_dir, "final"))

    # Add number of nodes to spec, or "none"
    firework_spec = {"_launch_dir": os.getcwd()}
    if number_nodes is None:
        firework_spec.update({"_category": "none"})
    else:
        firework_spec.update({"_category": str(number_nodes) + "nodes"})

    transition_firework = Firework(tasks=[vasprun],
                                   name="Migration Geometry optimization",
                                   spec=firework_spec)

    workflow = Workflow(fireworks=[transition_firework],
                        name=structure_file + migration_dir.split("/")[-1])

    LAUNCHPAD.add_wf(workflow)
Ejemplo n.º 5
0
def dimer_workflow(structure_file, dimer_indices=(0, 0), distance=0,
                   functional=("pbe", {}), is_metal=False, in_custodian=False,
                   number_nodes=None):
    """
    Set up a workflow that calculates the thermodynamics for a dimer
    formation in the current directory.

    Can later be expanded to also include kinetic barrier calculation.

    Args:
        structure_file (str): Structure file of the cathode material. Note
            that the structure file should be a json format file that is
            derived from the Cathode class, i.e. it should contain the cation
            configuration of the structure.
        dimer_indices (tuple): Indices of the oxygen sites which are to form a
            dimer. If no indices are provided, the user will be prompted.
        distance (float): Final distance between the oxygen atoms. If no
            distance is provided, the user will be prompted.
        functional (tuple): Tuple with the functional choices. The first element
            contains a string that indicates the functional used ("pbe", "hse", ...),
            whereas the second element contains a dictionary that allows the user
            to specify the various functional tags.
        is_metal (bool): Flag that indicates the material being studied is a
            metal, which changes the smearing from Gaussian to second order
            Methfessel-Paxton of 0.2 eV. Defaults to False.
        in_custodian (bool): Flag that indicates that the calculations
            should be run within a Custodian. Defaults to False.
        number_nodes (int): Number of nodes that should be used for the calculations.
            Is required to add the proper `_category` to the Firework generated, so
            it is picked up by the right Fireworker.

    """
    # TODO Change naming scheme

    # Let the user define a dimer, unless one is provided
    dimer_dir = define_dimer(structure_file=structure_file,
                             dimer_indices=dimer_indices,
                             distance=distance,
                             write_cif=True)

    # Set up the FireTask that sets up the transition calculation
    setup_transition = PyTask(
        func="pybat.cli.commands.setup.transition",
        kwargs={"directory": dimer_dir,
                "functional": functional,
                "is_metal": is_metal,
                "is_migration": False}
    )

    # Create the PyTask that runs the calculation
    if in_custodian:
        vasprun = CustodianTask(directory=os.path.join(dimer_dir, "final"))
    else:
        vasprun = VaspTask(directory=os.path.join(dimer_dir, "final"))

    # Extract the final cathode from the geometry optimization
    get_cathode = PyTask(
        func="pybat.cli.commands.get.get_cathode",
        kwargs={"directory": os.path.join(dimer_dir, "final"),
                "write_cif": True}
    )

    # Add number of nodes to spec, or "none"
    firework_spec = {"_launch_dir": os.getcwd()}
    if number_nodes is None:
        firework_spec.update({"_category": "none"})
    else:
        firework_spec.update({"_category": str(number_nodes) + "nodes"})

    transition_firework = Firework(tasks=[setup_transition, vasprun, get_cathode],
                                   name="Dimer Geometry optimization",
                                   spec=firework_spec)

    # Set up the SCF calculation directory
    scf_dir = os.path.join(dimer_dir, "scf_final")

    final_cathode = os.path.join(dimer_dir, "final", "final_cathode.json")

    # Set up the SCF calculation
    scf_firework = ScfFirework(
        structure_file=final_cathode, functional=functional,
        directory=scf_dir, write_chgcar=False, in_custodian=in_custodian,
        number_nodes=number_nodes
    )

    workflow = Workflow(fireworks=[transition_firework, scf_firework],
                        name=structure_file + dimer_dir.split("/")[-1],
                        links_dict={transition_firework: [scf_firework]})

    LAUNCHPAD.add_wf(workflow)
Ejemplo n.º 6
0
def get_wf_dimer(structure,
                 directory,
                 dimer_indices,
                 distance,
                 functional=("pbe", {}),
                 is_metal=False,
                 in_custodian=False,
                 number_nodes=None):
    """
    Set up a workflow that calculates the thermodynamics for a dimer
    formation in the current directory.

    Can later be expanded to also include kinetic barrier calculation.

    Args:
        structure (pybat.core.LiRichCathode): LiRichCathode for which to perform a
            dimer workflow. Should be a LiRichCathode, as only for this class the dimer
            scripts are defined.
        directory (str): Path to the directory in which the dimer calculation should
            be run.
        dimer_indices (tuple): Indices of the oxygen sites which are to form a
            dimer. If no indices are provided, the user will be prompted.
        distance (float): Final distance between the oxygen atoms. If no
            distance is provided, the user will be prompted.
        functional (tuple): Tuple with the functional choices. The first element
            contains a string that indicates the functional used ("pbe", "hse", ...),
            whereas the second element contains a dictionary that allows the user
            to specify the various functional tags.
        is_metal (bool): Flag that indicates the material being studied is a
            metal, which changes the smearing from Gaussian to second order
            Methfessel-Paxton of 0.2 eV. Defaults to False.
        in_custodian (bool): Flag that indicates that the calculations
            should be run within a Custodian. Defaults to False.
        number_nodes (int): Number of nodes that should be used for the calculations.
            Is required to add the proper `_category` to the Firework generated, so
            it is picked up by the right Fireworker.

    """
    # TODO Change naming scheme

    # Let the user define a dimer, unless one is provided
    setup_dimer = PyTask(func="pybat.cli.commands.define.dimer",
                         kwargs={
                             "structure": structure,
                             "directory": directory,
                             "dimer_indices": dimer_indices,
                             "distance": distance,
                             "write_cif": True
                         })

    # Set up the FireTask that sets up the transition calculation
    setup_transition = PyTask(func="pybat.cli.commands.setup.transition",
                              kwargs={
                                  "directory": directory,
                                  "functional": functional,
                                  "is_metal": is_metal
                              })

    # Create the PyTask that runs the calculation
    if in_custodian:
        vasprun = CustodianTask(directory=os.path.join(directory, "final"))
    else:
        vasprun = VaspTask(directory=os.path.join(directory, "final"))

    # Extract the final cathode from the geometry optimization
    get_cathode = PyTask(func="pybat.cli.commands.get.get_cathode",
                         kwargs={
                             "directory": os.path.join(directory, "final"),
                             "write_cif": True
                         })

    # Add number of nodes to spec, or "none"
    firework_spec = {}
    if number_nodes is None:
        firework_spec.update({"_category": "none"})
    else:
        firework_spec.update({"_category": str(number_nodes) + "nodes"})

    dimer_firework = Firework(
        tasks=[setup_dimer, setup_transition, vasprun, get_cathode],
        name="Dimer Geometry optimization",
        spec=firework_spec)

    # Set up the static calculation directory
    static_dir = os.path.join(directory, "static_final")
    final_cathode = os.path.join(directory, "final", "final_cathode.json")

    # Set up the static calculation
    static_fw = PybatStaticFW(structure=final_cathode,
                              functional=functional,
                              directory=static_dir,
                              write_chgcar=False,
                              in_custodian=in_custodian,
                              number_nodes=number_nodes)

    wf_name = str(structure.composition.reduced_composition).replace(" ", "")
    wf_name += "\n dimer" + str(dimer_indices)

    return Workflow(fireworks=[dimer_firework, static_fw],
                    name=wf_name,
                    links_dict={dimer_firework: [static_fw]})
Ejemplo n.º 7
0
def get_wf_migration(structure,
                     migration_indices=(0, 0),
                     functional=("pbe", {}),
                     is_metal=False,
                     in_custodian=False,
                     number_nodes=None):
    """
    Set up a workflow that calculates the reaction energy for a migration in
    the current directory.

    Can later be expanded to also include kinetic barrier calculation.

    Args:
        structure (pybat.core.Cathode): Cathode for which to calculate the reaction
            energy of the migration.
        migration_indices (tuple): Tuple of the indices which designate the
            migrating site and the vacant site to which the cation will
            migrate. If no indices are provided, the user will be prompted.
        functional (tuple): Tuple with the functional details. The first element
            contains a string that indicates the functional used ("pbe", "hse", ...),
            whereas the second element contains a dictionary that allows the user
            to specify the various functional tags.
        is_metal (bool): Flag that indicates the material being studied is a
            metal, which changes the smearing from Gaussian to second order
            Methfessel-Paxton of 0.2 eV. Defaults to False.
        in_custodian (bool): Flag that indicates that the calculations
            should be run within a Custodian. Defaults to False.
        number_nodes (int): Number of nodes that should be used for the calculations.
            Is required to add the proper `_category` to the Firework generated, so
            it is picked up by the right Fireworker.

    """

    # TODO Add setup steps to the workflow
    # In case adjustments need to made to the setup of certain calculations,
    #  after which the calculation needs to be rerun, not adding the setup
    # steps to the workflow means that these will have to be rerun manually,
    #  instead of simply relying on the fireworks commands.

    # TODO Can currently not be executed from jupyter notebook

    # Let the user define a migration
    migration_dir = define_migration(structure=structure,
                                     site=migration_indices[0],
                                     final_site=migration_indices[1],
                                     write_cif=True)

    # Set up the transition calculation
    transition(directory=migration_dir,
               functional=functional,
               is_metal=is_metal)

    # Create the PyTask that runs the calculation
    if in_custodian:
        vasprun = CustodianTask(directory=os.path.join(migration_dir, "final"))
    else:
        vasprun = VaspTask(directory=os.path.join(migration_dir, "final"))

    # Extract the final cathode from the geometry optimization
    get_cathode = PyTask(func="pybat.cli.commands.get.get_cathode",
                         kwargs={
                             "directory": os.path.join(migration_dir, "final"),
                             "write_cif": True
                         })

    # Add number of nodes to spec, or "none"
    firework_spec = {}
    if number_nodes is None:
        firework_spec.update({"_category": "none"})
    else:
        firework_spec.update({"_category": str(number_nodes) + "nodes"})

    transition_firework = Firework(tasks=[vasprun, get_cathode],
                                   name="Migration Geometry optimization",
                                   spec=firework_spec)

    # Set up the static calculation directory
    static_dir = os.path.join(migration_dir, "static_final")

    final_cathode = os.path.join(migration_dir, "final", "final_cathode.json")

    # Set up the static calculation
    static_fw = PybatStaticFW(structure=final_cathode,
                              functional=functional,
                              directory=static_dir,
                              write_chgcar=False,
                              in_custodian=in_custodian,
                              number_nodes=number_nodes)

    struc_name = str(structure.composition.reduced_composition).replace(
        " ", "")

    return Workflow(fireworks=[transition_firework, static_fw],
                    name=struc_name + " " + migration_dir.split("/")[-1],
                    links_dict={transition_firework: [static_fw]})
Ejemplo n.º 8
0
    def __init__(self, structure, functional, directory, is_metal=False,
                 in_custodian=False, number_nodes=None, fw_action=None):
        """
        Initialize a Firework for a geometry optimization.

        Args:
            structure: pymatgen.Structure OR path to structure file for which to run
                the geometry optimization.
            functional (tuple): Tuple with the functional choices. The first element
                contains a string that indicates the functional used ("pbe", "hse", ...),
                whereas the second element contains a dictionary that allows the user
                to specify the various functional tags.
            directory (str): Directory in which the geometry optimization should be
                performed.
            is_metal (bool): Flag that indicates the material being studied is a
                metal, which changes the smearing from Gaussian to second order
                Methfessel-Paxton of 0.2 eV.
            in_custodian (bool): Flag that indicates whether the calculation should be
                run inside a Custodian.
            number_nodes (int): Number of nodes that should be used for the calculations.
                Is required to add the proper `_category` to the Firework generated, so
                it is picked up by the right Fireworker.
            fw_action (fireworks.FWAction): FWAction to return after the final
                PulayTask is completed.
        """

        # Create the PyTask that sets up the calculation
        setup_optimize = PyTask(
            func="pybat.cli.commands.setup.optimize",
            kwargs={"structure": structure,
                    "functional": functional,
                    "directory": directory,
                    "is_metal": is_metal}
        )

        # Create the PyTask that runs the calculation
        if in_custodian:
            vasprun = CustodianTask(directory=directory)
        else:
            vasprun = VaspTask(directory=directory)

        # Extract the final cathode from the geometry optimization
        get_cathode = PyTask(
            func="pybat.cli.commands.get.get_cathode",
            kwargs={"directory": os.path.join(directory),
                    "write_cif": True}
        )

        # Create the PyTask that check the Pulay stresses
        pulay_task = PulayTask(directory=directory,
                               in_custodian=in_custodian,
                               number_nodes=number_nodes,
                               fw_action=fw_action)

        # Only add number of nodes to spec if specified
        firework_spec = {}
        if number_nodes is None or number_nodes == 0:
            firework_spec.update({"_category": "none"})
        else:
            firework_spec.update({"_category": str(number_nodes) + "nodes"})

        # Combine the FireTasks into one FireWork
        super(PybatOptimizeFW, self).__init__(
            tasks=[setup_optimize, vasprun, get_cathode, pulay_task],
            name="Geometry optimization", spec=firework_spec
        )