Esempio n. 1
0
    def setUp(self):
        try:
            __import__("igraph", fromlist=["Graph"])
        except (ImportError, ModuleNotFoundError):
            raise unittest.SkipTest(
                "Skipping because python-igraph not installed")

        self.fw1 = Firework(
            PyTask(func="math.pow",
                   inputs=["base", "exponent"],
                   outputs=["first power"]),
            name="pow(2, 3)",
            spec={
                "base": 2,
                "exponent": 3
            },
        )
        self.fw2 = Firework(
            PyTask(func="math.pow",
                   inputs=["first power", "exponent"],
                   outputs=["second power"]),
            name="pow(pow(2, 3), 4)",
            spec={"exponent": 4},
        )
        self.fw3 = Firework(PyTask(func="print", inputs=["second power"]),
                            name="the third one")
Esempio n. 2
0
    def setUp(self):
        try:
            __import__('igraph', fromlist=['Graph'])
        except (ImportError, ModuleNotFoundError):
            raise unittest.SkipTest('Skipping because python-igraph not installed')

        self.fw1 = Firework(
            PyTask(
                func='math.pow',
                inputs=['base', 'exponent'],
                outputs=['first power']
            ),
            name='pow(2, 3)',
            spec={'base': 2, 'exponent': 3}
        )
        self.fw2 = Firework(
            PyTask(
                func='math.pow',
                inputs=['first power', 'exponent'],
                outputs=['second power']
            ),
            name='pow(pow(2, 3), 4)',
            spec={'exponent': 4}
        )
        self.fw3 = Firework(
            PyTask(
                func='print',
                inputs=['second power']
            ),
            name='the third one'
        )
Esempio 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)
Esempio n. 4
0
def make_firework(atoms, fw_name, vasp_settings):
    '''
    This function makes a FireWorks rocket to perform a VASP relaxation

    Args:
        atoms           `ase.Atoms` object to relax
        fw_name         Dictionary of tags/etc to use as the FireWorks name
        vasp_settings   Dictionary of VASP settings to pass to Vasp()
    Returns:
        firework    An instance of a `fireworks.Firework` object that is set up
                    to perform a VASP relaxation
    '''
    # Warn the user if they're submitting a big one
    if len(atoms) > 80:
        warnings.warn(
            'You are making a firework with %i atoms in it. This may '
            'take awhile.' % len(atoms), RuntimeWarning)

    # Take the `vasp_functions` submodule in GASpy and then pass it out to each
    # FireWork rocket to use.
    vasp_filename = vasp_functions.__file__
    if vasp_filename.split(
            '.')[-1] == 'pyc':  # Make sure we use the source file
        vasp_filename = vasp_filename[:-3] + 'py'
    with open(vasp_filename) as file_handle:
        vasp_functions_contents = file_handle.read()
    pass_vasp_functions = FileWriteTask(
        files_to_write=[{
            'filename': 'vasp_functions.py',
            'contents': vasp_functions_contents
        }])

    # Convert the atoms object to a string so that we can pass it through
    # FireWorks, and then tell the FireWork rocket to use our `vasp_functions`
    # submodule to unpack the string
    atom_trajhex = encode_atoms_to_trajhex(atoms)
    read_atoms_file = PyTask(func='vasp_functions.hex_to_file',
                             args=['slab_in.traj', atom_trajhex])

    # Tell the FireWork rocket to perform the relaxation
    relax = PyTask(func='vasp_functions.runVasp',
                   args=['slab_in.traj', 'slab_relaxed.traj', vasp_settings],
                   stored_data_varname='opt_results')

    fw_name['user'] = getpass.getuser()
    firework = Firework([pass_vasp_functions, read_atoms_file, relax],
                        name=fw_name)
    return firework
Esempio n. 5
0
    def __init__(self, structure, supercell_matrix, t_min=5, t_max=2000, t_step=5,
                 name="phonon", vasp_input_set=None, override_default_vasp_params=None,
                 vasp_cmd="vasp", metadata=None, tag=None, qpoint_mesh=(50, 50, 50),
                 prev_calc_loc=True, db_file=None, parents=None, stable_tor=0.01,
                 **kwargs):

        metadata = metadata or {}
        tag = tag or metadata.get('tag')
        # generate a tag with a warning
        if tag is None:
            tag = str(uuid4())
            warnings.warn('No ``tag`` was passed explicitly or in ``metadata`` to PhononFW. In order to find this Firework later, you should assign one. This was assigned: {}'.format(tag))
            metadata['tag'] = tag

        override_default_vasp_params = override_default_vasp_params or {}
        ncell = int(0.5+np.linalg.det(supercell_matrix))
        tmp = copy.deepcopy(override_default_vasp_params)
        if 'user_incar_settings' in tmp:
          if 'magmom' in tmp['user_incar_settings']:
            mag = tmp['user_incar_settings']['magmom']
            supermag = []
            for site in mag:
                n = str(site).split('*')
                if len(n)==1:
                    supermag.append('{}*{}'.format(ncell,float(n[0])))
                else:
                    supermag.append('{}*{}'.format(ncell*int(n[0]),float(n[1])))
            tmp['user_incar_settings']['magmom']=supermag
            print("phonon setting", tmp)

        vasp_input_set = vasp_input_set or ForceConstantsSet(structure, **tmp)

        supercell_structure = deepcopy(structure)
        supercell_structure.make_supercell(supercell_matrix)
        supercell_site_properties = deepcopy(supercell_structure.site_properties)

        t = []

        # We need to get the POSCAR from the previous run or from the passed Structure
        # so it can be transformed to a supercell in the next step
        if parents:
            if prev_calc_loc:
                t.append(CopyVaspOutputs(calc_loc=prev_calc_loc, contcar_to_poscar=True))
        else:
            # write the input set first, just to get the POSCAR file in the directory
            # the other inputs will get overridden by WriteVaspFromIOSetPrevStructure
            t.append(WriteVaspFromIOSetPrevStructure(structure=structure, vasp_input_set=vasp_input_set, site_properties=site_properties))

        t.append(SupercellTransformation(supercell_matrix=supercell_matrix))
        t.append(WriteVaspFromIOSetPrevStructure(vasp_input_set=vasp_input_set, site_properties=supercell_site_properties))
        t.append(RunVaspCustodianNoValidate(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<", gzip_output=False))
        # we skipped the validation so we can potentially fix the vasprun.xml file.
        # Fix and validate here.
        t.append(PyTask(func='dfttk.vasprun_fix.fix_vasprun', args=['vasprun.xml']))
        t.append(PassCalcLocs(name=name))
        t.append(CalculatePhononThermalProperties(supercell_matrix=supercell_matrix, t_min=t_min, t_max=t_max, t_step=t_step, db_file=">>db_file<<", tag=tag, metadata=metadata))
        t.append(PhononStable(supercell_matrix=supercell_matrix, db_file=">>db_file<<", tag=tag, metadata=metadata, qpoint_mesh=qpoint_mesh, stable_tor=stable_tor))

        super(PhononFW, self).__init__(t, parents=parents, name="{}-{}".format(
            structure.composition.reduced_formula, name), **kwargs)
Esempio n. 6
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)
Esempio n. 7
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)
Esempio n. 8
0
    def setUp(self):
        try:
            from fireworks.utilities.dagflow import DAGFlow
        except Exception:
            raise unittest.SkipTest("Skipping test, DagFlow not installed")

        self.fw1 = Firework(PyTask(func='math.pow',
                                   inputs=['base', 'exponent'],
                                   outputs=['first power']),
                            name='pow(2, 3)',
                            spec={
                                'base': 2,
                                'exponent': 3
                            })
        self.fw2 = Firework(PyTask(func='math.pow',
                                   inputs=['first power', 'exponent'],
                                   outputs=['second power']),
                            name='pow(pow(2, 3), 4)',
                            spec={'exponent': 4})
        self.fw3 = Firework(PyTask(func='print', inputs=['second power']),
                            name='the third one')
Esempio n. 9
0
    def test_dagflow_clashing_outputs(self):
        """ subsequent task overwrites output of a task """
        from fireworks.utilities.dagflow import DAGFlow

        tasks = [
            PyTask(func='math.pow',
                   inputs=['first power 1', 'exponent'],
                   outputs=['second power']),
            PyTask(func='math.pow',
                   inputs=['first power 2', 'exponent'],
                   outputs=['second power'])
        ]
        fwk = Firework(tasks,
                       spec={
                           'exponent': 4,
                           'first power 1': 8,
                           'first power 2': 4
                       })
        msg = 'Several tasks may not use the same name in outputs list.'
        with self.assertRaises(AssertionError) as context:
            DAGFlow.from_fireworks(Workflow([fwk], {})).check()
        self.assertTrue(msg in str(context.exception))
Esempio n. 10
0
    def test_dagflow_input(self):
        """ missing input """

        fw2 = Firework(PyTask(func='math.pow',
                              inputs=['first power', 'exponent'],
                              outputs=['second power']),
                       name='pow(pow(2, 3), 4)')
        wfl = Workflow([self.fw1, fw2], {self.fw1: [fw2], fw2: []})
        msg = (r"An input field must have exactly one source', 'step', "
               r"'pow(pow(2, 3), 4)', 'entity', 'exponent', 'sources', []")
        with self.assertRaises(AssertionError) as context:
            DAGFlow.from_fireworks(wfl)
        self.assertTrue(msg in str(context.exception))
Esempio n. 11
0
    def test_dagflow_clashing_outputs(self):
        """subsequent task overwrites output of a task"""
        from fireworks.utilities.dagflow import DAGFlow

        tasks = [
            PyTask(func="math.pow",
                   inputs=["first power 1", "exponent"],
                   outputs=["second power"]),
            PyTask(func="math.pow",
                   inputs=["first power 2", "exponent"],
                   outputs=["second power"]),
        ]
        fwk = Firework(tasks,
                       spec={
                           "exponent": 4,
                           "first power 1": 8,
                           "first power 2": 4
                       })
        msg = "Several tasks may not use the same name in outputs list."
        with self.assertRaises(AssertionError) as context:
            DAGFlow.from_fireworks(Workflow([fwk], {})).check()
        self.assertTrue(msg in str(context.exception))
Esempio n. 12
0
    def test_dagflow_missing_input(self):
        """missing input"""
        from fireworks.utilities.dagflow import DAGFlow

        fw2 = Firework(
            PyTask(func="math.pow",
                   inputs=["first power", "exponent"],
                   outputs=["second power"]),
            name="pow(pow(2, 3), 4)",
        )
        wfl = Workflow([self.fw1, fw2], {self.fw1: [fw2], fw2: []})
        msg = (
            r"Every input in inputs list must have exactly one source.', 'step', "
            r"'pow(pow(2, 3), 4)', 'entity', 'exponent', 'sources', []")
        with self.assertRaises(AssertionError) as context:
            DAGFlow.from_fireworks(wfl).check()
        self.assertTrue(msg in str(context.exception))
Esempio n. 13
0
 def test_dagflow_output(self):
     """ clashing inputs """
     from fireworks.utilities.dagflow import DAGFlow
     fw2 = Firework(
         PyTask(
             func='math.pow',
             inputs=['first power', 'exponent'],
             outputs=['second power']
         ),
         name='pow(pow(2, 3), 4)',
         spec={'exponent': 4, 'first power': 8}
     )
     wfl = Workflow([self.fw1, fw2], {self.fw1: [fw2], fw2: []})
     msg = (r"'An input field must have exactly one source', 'step', "
            r"'pow(pow(2, 3), 4)', 'entity', 'first power', 'sources'")
     with self.assertRaises(AssertionError) as context:
         DAGFlow.from_fireworks(wfl)
     self.assertTrue(msg in str(context.exception))
Esempio n. 14
0
 def test_dagflow_race_condition(self):
     """ two parent firework outputs overwrite each other """
     from fireworks.utilities.dagflow import DAGFlow
     task = PyTask(func='math.pow',
                   inputs=['base', 'exponent'],
                   outputs=['second power'])
     fw1 = Firework(task, name='pow(2, 3)', spec={'base': 2, 'exponent': 3})
     fw2 = Firework(task, name='pow(2, 3)', spec={'base': 2, 'exponent': 3})
     wfl = Workflow([fw1, fw2, self.fw3], {
         fw1: [self.fw3],
         fw2: [self.fw3]
     })
     msg = (
         r"'Every input in inputs list must have exactly one source.', 'step', "
         r"'the third one', 'entity', 'second power', 'sources', [0, 1]")
     with self.assertRaises(AssertionError) as context:
         DAGFlow.from_fireworks(wfl).check()
     self.assertTrue(msg in str(context.exception))
Esempio n. 15
0
    def __init__(self,
                 structure,
                 supercell_matrix,
                 t_min=5,
                 t_max=2000,
                 t_step=5,
                 name="phonon",
                 vasp_input_set=None,
                 vasp_cmd="vasp",
                 metadata=None,
                 tag=None,
                 prev_calc_loc=True,
                 db_file=None,
                 parents=None,
                 **kwargs):

        metadata = metadata or {}
        tag = tag or metadata.get('tag')
        # generate a tag with a warning
        if tag is None:
            tag = str(uuid4())
            warnings.warn(
                'No ``tag`` was passed explicitly or in ``metadata`` to PhononFW. In order to find this Firework later, you should assign one. This was assigned: {}'
                .format(tag))
            metadata['tag'] = tag

        vasp_input_set = vasp_input_set or ForceConstantsSet(structure)

        supercell_structure = deepcopy(structure)
        supercell_structure.make_supercell(supercell_matrix)
        supercell_site_properties = deepcopy(
            supercell_structure.site_properties)

        t = []

        # We need to get the POSCAR from the previous run or from the passed Structure
        # so it can be transformed to a supercell in the next step
        if parents:
            if prev_calc_loc:
                t.append(
                    CopyVaspOutputs(calc_loc=prev_calc_loc,
                                    contcar_to_poscar=True))
        else:
            # write the input set first, just to get the POSCAR file in the directory
            # the other inputs will get overridden by WriteVaspFromIOSetPrevStructure
            t.append(
                WriteVaspFromIOSet(structure=structure,
                                   vasp_input_set=vasp_input_set))

        t.append(SupercellTransformation(supercell_matrix=supercell_matrix))
        t.append(
            WriteVaspFromIOSetPrevStructure(
                vasp_input_set=vasp_input_set,
                site_properties=supercell_site_properties))
        t.append(
            RunVaspCustodianNoValidate(vasp_cmd=vasp_cmd,
                                       auto_npar=">>auto_npar<<",
                                       gzip_output=False))
        # we skipped the validation so we can potentially fix the vasprun.xml file.
        # Fix and validate here.
        t.append(
            PyTask(func='dfttk.vasprun_fix.fix_vasprun', args=['vasprun.xml']))
        t.append(PassCalcLocs(name=name))
        t.append(
            CalculatePhononThermalProperties(supercell_matrix=supercell_matrix,
                                             t_min=t_min,
                                             t_max=t_max,
                                             t_step=t_step,
                                             db_file=db_file,
                                             tag=tag,
                                             metadata=metadata))

        super(PhononFW,
              self).__init__(t,
                             parents=parents,
                             name="{}-{}".format(
                                 structure.composition.reduced_formula, name),
                             **kwargs)
launchpad = LaunchPad(host=host,
                      name=name,
                      username=username,
                      password=password)

db = connect('missing.db')

for i, d in enumerate(db.select()):

    #if i != 0:
    #    continue
    slab = d.toatoms()
    kvp = d.key_value_pairs
    kvp['metal'] = slab.get_chemical_symbols()[0]
    param = d.data
    slab.info = param

    # Encode the atoms
    encoding = atoms_to_encode(slab)

    # Two steps - write the input structure to an input file, then relax
    t0 = PyTask(func='qescripts.fwio.encode_to_atoms', args=[encoding])
    t1 = PyTask(func='qescripts.fwespresso.get_potential_energy',
                stored_data_varname='trajectory')

    # Package the tasks into a firework, the fireworks into a workflow,
    # and submit the workflow to the launchpad
    firework = Firework([t0, t1], spec={'_priority': 1}, name=search_keys)
    workflow = Workflow([firework])
    launchpad.add_wf(workflow)
Esempio n. 17
0
def dos_workflow(structure_file, fix_part, fix_thickness, is_metal, k_product,
                 in_custodian):
    """
    Set up a workflow to calculate the DOS of a slab file. Will set up two
    FireWorks:

    "Slab Geometry Optimization": Optimizes the geometry of the slab given
    by the structure file. The user can also specify the part of the slab
    that is fixed using selective dynamics, as well as the number of layers
    to fix.

    "DOS Calculation": Calculates the density of states of the slab, as well as
    the local potential, which can be used to determine the vacuum level.

    After it is set up, the workflow is sent to the LAUNCHPAD.

    Args:
        structure_file (str): Name of the structure file which contains the
            slab geometry.
        fix_part (str): Defines the part of the slab that will remain fixed
            during the geometry optimization.
        fix_thickness (int): Number of atomic layers to fix for the geometry
            optimization.
        is_metal (bool): Specifies whether or not the material is metallic.
            Sets the smearing method to Methfessel-Paxton.
        k_product (int): Determines the density of the k-mesh in the density of
            states calculation. k_product represents the product of the number
        of k-points corresponding to a certain lattice vector with the
            length of that lattice vector.
    """

    # TODO add checks
    # Currently the workflow will be submitted even if the file doesn't exist!

    current_dir = os.getcwd()

    # Set up the geometry optimization from the structure file. All input is
    # provided by the CLI arguments and options. The directory where the
    # geometry optimization is set up is returned and passed as output,
    # so it can be used by Firework children to run the calculation.
    setup_relax = PyTask(func="quotas.cli.commands.slab.relax",
                         kwargs={
                             "structure_file": structure_file,
                             "fix_part": fix_part,
                             "fix_thickness": fix_thickness,
                             "is_metal": is_metal,
                             "verbose": False
                         },
                         outputs=["relax_dir"])

    if in_custodian:
        # Run the VASP calculation within a Custodian
        run_relax = PyTask(func="quotas.workflow.run_custodian",
                           inputs=["relax_dir"])
    else:
        # Run the VASP calculation.
        run_relax = PyTask(func="quotas.workflow.run_vasp",
                           inputs=["relax_dir"])

    relax_firework = Firework(tasks=[setup_relax, run_relax],
                              name="Slab Geometry optimization",
                              spec={"_launch_dir": current_dir})

    # Set up the DOS calculation, based on the structure found from the
    # geometry optimization.
    setup_dos = PyTask(func="quotas.cli.commands.slab.dos",
                       inputs=["relax_dir"],
                       kwargs={"k_product": k_product},
                       outputs=["dos_dir"])

    if in_custodian:
        # Run the VASP calculation within a Custodian
        run_dos = PyTask(func="quotas.workflow.run_custodian",
                         inputs=["dos_dir"])
    else:
        # Run the VASP calculation
        run_dos = PyTask(func="quotas.workflow.run_vasp", inputs=["dos_dir"])

    dos_firework = Firework(tasks=[setup_dos, run_dos], name="DOS calculation")

    # Postprocessing
    # TODO Add postprocessing firework

    # Extract the necessary output
    # Calculate the work function -> send to database?

    # Add the workflow to the launchpad
    workflow = Workflow(fireworks=[relax_firework, dos_firework],
                        links_dict={relax_firework: [dos_firework]},
                        name=structure_file + " DOS calculation")

    LAUNCHPAD.add_wf(workflow)
Esempio n. 18
0
def bulk_optics_workflow(structure_file, is_metal, hse_calc, k_product,
                         in_custodian):
    """
    Sets up a workflow that calculates the dielectric function for the bulk
    structure of a material.

    Returns:

    """

    current_dir = os.getcwd()

    # Set up the geometry optimization from the structure file. All input is
    # provided by the CLI arguments and options. The directory where the
    # geometry optimization is set up is returned and passed as output,
    # so it can be used by Firework children to run the calculation.
    setup_relax = PyTask(func="quotas.cli.commands.bulk.relax",
                         kwargs={
                             "structure_file": structure_file,
                             "is_metal": is_metal,
                             "hse_calc": hse_calc,
                             "verbose": False
                         },
                         outputs=["relax_dir"])

    if in_custodian:
        # Run the VASP calculation within a Custodian
        run_relax = PyTask(func="quotas.workflow.run_custodian",
                           inputs=["relax_dir"])
    else:
        # Run the VASP calculation
        run_relax = PyTask(func="quotas.workflow.run_vasp",
                           inputs=["relax_dir"])

    relax_firework = Firework(tasks=[setup_relax, run_relax],
                              name="Bulk Geometry optimization",
                              spec={"_launch_dir": current_dir})

    # Set up the dielectric function calculation
    setup_optics = PyTask(func="quotas.cli.commands.bulk.optics",
                          inputs=["relax_dir"],
                          kwargs={
                              "k_product": k_product,
                              "is_metal": is_metal,
                              "hse_calc": hse_calc,
                              "verbose": False
                          },
                          outputs=["optics_dir"])

    if in_custodian:
        # Run the VASP calculation within a Custodian
        run_optics = PyTask(func="quotas.workflow.run_custodian",
                            inputs=["optics_dir"])
    else:
        # Run the VASP calculation
        run_optics = PyTask(func="quotas.workflow.run_vasp",
                            inputs=["optics_dir"])

    optics_firework = Firework(tasks=[setup_optics, run_optics],
                               name="Optics calculation")

    # Add the workflow to the launchpad
    workflow = Workflow(fireworks=[relax_firework, optics_firework],
                        links_dict={relax_firework: [optics_firework]},
                        name=structure_file + " Optics calculation")

    LAUNCHPAD.add_wf(workflow)
Esempio n. 19
0
def test_custodian(structure_file, fix_part, fix_thickness, is_metal,
                   k_product):
    """
    Testscript for using Custodian to gracefully recover from errors.

    Returns:
        None

    """

    current_dir = os.getcwd()

    # Set up the geometry optimization from the structure file. All input is
    # provided by the CLI arguments and options. The directory where the
    # geometry optimization is set up is returned and passed as output,
    # so it can be used by Firework children to run the calculation.
    setup_relax = PyTask(func="quotas.cli.commands.slab.relax",
                         kwargs={
                             "structure_file": structure_file,
                             "fix_part": fix_part,
                             "fix_thickness": fix_thickness,
                             "is_metal": is_metal,
                             "verbose": False
                         },
                         outputs=["relax_dir"])

    # Run the VASP calculation.
    run_relax = PyTask(func="quotas.workflow.run_custodian",
                       inputs=["relax_dir"])

    relax_firework = Firework(tasks=[setup_relax, run_relax],
                              name="Slab Geometry optimization",
                              spec={"_launch_dir": current_dir})

    # -----> Here we would add a check to see if the job completed
    # successfully. If not, we can add another FireWork that makes the
    # necessary adjustments and restarts the calculation.

    # Set up the calculation
    setup_dos = PyTask(func="quotas.cli.commands.slab.dos",
                       inputs=["relax_dir"],
                       kwargs={"k_product": k_product},
                       outputs=["dos_dir"])

    # Run the VASP calculation.
    run_dos = PyTask(func="quotas.workflow.run_custodian", inputs=["dos_dir"])

    dos_firework = Firework(tasks=[setup_dos, run_dos], name="DOS calculation")

    # ----> Here we would add another check...

    ## Firework 3

    # Extract the necessary output

    # Calculate the work function

    # Add the workflow to the launchpad
    workflow = Workflow(fireworks=[relax_firework, dos_firework],
                        links_dict={relax_firework: [dos_firework]},
                        name=structure_file + " DOS calculation (Custodian)")

    LAUNCHPAD.add_wf(workflow)
Esempio n. 20
0
    def run_task(self, fw_spec):
        """

        Args:
            fw_spec:

        Returns:
            FWAction

        """
        # Extract the parameters into variables; this makes for cleaner code IMO
        directory = self["directory"]
        in_custodian = self.get("in_custodian", False)
        number_nodes = self.get("number_nodes", None)
        tolerance = self.get("tolerance", PulayTask.pulay_tolerance)
        fw_action = self.get('fw_action', {})

        # Check if the lattice vectors have changed significantly
        initial_structure = Structure.from_file(
            os.path.join(directory, "POSCAR"))
        final_structure = Structure.from_file(
            os.path.join(directory, "CONTCAR"))

        sum_differences = np.linalg.norm(initial_structure.lattice.matrix -
                                         final_structure.lattice.matrix)

        # If the difference is small, return an empty FWAction
        if sum_differences < tolerance:
            if fw_action:
                return FWAction.from_dict(fw_action)
            else:
                return FWAction()

        # Else, set up another geometry optimization
        else:
            print(
                "Lattice vectors have changed significantly during geometry "
                "optimization. Performing another full geometry optimization to "
                "make sure there were no Pulay stresses present.\n\n")

            # Create the ScriptTask that copies the CONTCAR to the POSCAR
            copy_contcar = ScriptTask.from_str(
                "cp " + os.path.join(directory, "CONTCAR") + " " +
                os.path.join(directory, "POSCAR"))

            # 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 again
            pulay_task = PulayTask(directory=directory,
                                   in_custodian=in_custodian,
                                   number_nodes=number_nodes,
                                   tolerance=tolerance,
                                   fw_action=fw_action)

            # Add number of nodes to spec, or "none"
            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 two FireTasks into one FireWork
            optimize_fw = Firework(
                tasks=[copy_contcar, vasprun, get_cathode, pulay_task],
                name="Pulay Step",
                spec=firework_spec)

            return FWAction(additions=optimize_fw)
Esempio n. 21
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
        )
Esempio n. 22
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]})
Esempio n. 23
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]})
Esempio n. 24
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)
Esempio n. 25
0
def processfile(runfile):
    """Function to process testopia run yaml file and create workflows, add them 
    to run in fireworks"""
    with open(runfile, 'r') as f:
        run_details = yaml.load(f)
    testcases = run_details['test_run']['cases']
    print 'testcases:\n'
    print testcases
    testcasetype = type(testcases)
    print testcasetype
    run_id = int(run_details['test_run']['run_id'])
    print run_id
    environment_id = int(run_details['test_run']['environment_id'])
    print environment_id
    tcms = Testopia.from_config('/var/dt/tf/etc/testopia.cfg')
    environment_details = tcms.environment_get(environment_id)
    print environment_details
    rundetailsfromtcms = tcms.testrun_get(run_id)
    product_version = rundetailsfromtcms['product_version']
    build_id = rundetailsfromtcms['build_id']
    buildinfo = tcms.build_get(build_id)
    print buildinfo
    build_name = buildinfo['name']
    print "build name: " + build_name
    print "product_version " + product_version
    environment_name = environment_details['name']
    print environment_name
    environment_file = '/var/dt/tf/etc/environments/' + environment_name + '.py'
    environment_filepyc = environment_file + 'c'
    if os.path.isfile(environment_filepyc):
        print "environment pyc file is present, deleting it"
        os.remove(environment_filepyc)
    else:
        print "No cached environment pyc file found"
    print environment_file
    testsonfire = []
    fwsequence = {}
    fwkey = ''
    fwvalue = ''
    for testcase in testcases.keys():
        case_id = int(testcase)
        testcase_name = run_details['test_run']['cases'][testcase]['summary']
        argsf = [
            run_id, case_id, build_id, environment_id, environment_name,
            environment_file, testcase_name, product_version, build_name
        ]
        fw_test = Firework(PyTask(func='HookFW.runCase', args=argsf))
        print "argsf are:"
        print argsf
        testsonfire.append(fw_test)
        if fwvalue:
            fwsequence[fwvalue] = fw_test
            fwvalue = fw_test
        else:
            fwvalue = fw_test

    #To be run as last firework in the workflow, to compile logs for the entire set of testcases

    rebotcmd = "cd /var/dt/tf/logs/" + str(
        run_id
    ) + '; rebot -N "DTTF" -R */*.xml; ln -s report.html index.html; echo ok '
    fw_test = Firework(ScriptTask.from_str(rebotcmd))
    testsonfire.append(fw_test)
    fwsequence[fwvalue] = fw_test
    print "tests on fire:"
    print testsonfire
    print "test sequence:"
    print fwsequence
    workflow = Workflow(testsonfire, fwsequence)
    launchpad = LaunchPad()
    launchpad.add_wf(workflow)