Esempio n. 1
0
def launch_workflow(code, structure, pseudo_family, kpoints_distance, ecutwfc,
                    ecutrho, hubbard_u, hubbard_v, hubbard_file_pk,
                    starting_magnetization, smearing,
                    automatic_parallelization, clean_workdir, max_num_machines,
                    max_wallclock_seconds, with_mpi, daemon):
    """Run a `PwBaseWorkChain`."""
    from aiida.orm import Bool, Float, Str, Dict
    from aiida.plugins import WorkflowFactory
    from aiida_quantumespresso.utils.resources import get_default_options, get_automatic_parallelization_options

    builder = WorkflowFactory('quantumespresso.pw.base').get_builder()

    parameters = {
        'SYSTEM': {
            'ecutwfc': ecutwfc,
            'ecutrho': ecutrho,
        },
    }

    try:
        hubbard_file = validate.validate_hubbard_parameters(
            structure, parameters, hubbard_u, hubbard_v, hubbard_file_pk)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    try:
        validate.validate_starting_magnetization(structure, parameters,
                                                 starting_magnetization)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    try:
        validate.validate_smearing(parameters, smearing)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    builder.pw.code = code
    builder.pw.structure = structure
    builder.pw.parameters = Dict(dict=parameters)
    builder.pseudo_family = Str(pseudo_family)
    builder.kpoints_distance = Float(kpoints_distance)

    if hubbard_file:
        builder.hubbard_file = hubbard_file

    if automatic_parallelization:
        automatic_parallelization = get_automatic_parallelization_options(
            max_num_machines, max_wallclock_seconds)
        builder.automatic_parallelization = Dict(
            dict=automatic_parallelization)
    else:
        builder.pw.metadata.options = get_default_options(
            max_num_machines, max_wallclock_seconds, with_mpi)

    if clean_workdir:
        builder.clean_workdir = Bool(True)

    launch.launch_process(builder, daemon)
Esempio n. 2
0
def launch_workflow(code, structure, pseudo_family, kpoints_distance, ecutwfc,
                    ecutrho, hubbard_u, hubbard_v, hubbard_file_pk,
                    starting_magnetization, smearing,
                    automatic_parallelization, clean_workdir, max_num_machines,
                    max_wallclock_seconds, with_mpi, daemon, final_scf):
    """Run a `PwRelaxWorkChain`."""
    from aiida.orm import Bool, Float, Dict, Str
    from aiida.plugins import WorkflowFactory
    from qe_tools import CONSTANTS

    from aiida_quantumespresso.utils.resources import get_default_options, get_automatic_parallelization_options

    builder = WorkflowFactory('quantumespresso.pw.relax').get_builder()

    cutoff_wfc, cutoff_rho = pseudo_family.get_recommended_cutoffs(
        structure=structure)

    parameters = {
        'CONTROL': {
            'calculation': 'relax',
        },
        'SYSTEM': {
            'ecutwfc': ecutwfc or cutoff_wfc / CONSTANTS.ry_to_ev,
            'ecutrho': ecutrho or cutoff_rho / CONSTANTS.ry_to_ev,
        },
    }

    try:
        hubbard_file = validate.validate_hubbard_parameters(
            structure, parameters, hubbard_u, hubbard_v, hubbard_file_pk)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    try:
        validate.validate_starting_magnetization(structure, parameters,
                                                 starting_magnetization)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    try:
        validate.validate_smearing(parameters, smearing)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    builder.structure = structure
    builder.base.kpoints_distance = Float(kpoints_distance)
    builder.base.pw.code = code
    builder.base.pw.pseudos = pseudo_family.get_pseudos(structure=structure)
    builder.base.pw.parameters = Dict(dict=parameters)

    if hubbard_file:
        builder.base.pw.hubbard_file = hubbard_file

    if automatic_parallelization:
        automatic_parallelization = get_automatic_parallelization_options(
            max_num_machines, max_wallclock_seconds)
        builder.base.automatic_parallelization = Dict(
            dict=automatic_parallelization)
    else:
        builder.base.pw.metadata.options = get_default_options(
            max_num_machines, max_wallclock_seconds, with_mpi)

    if clean_workdir:
        builder.clean_workdir = Bool(True)

    if final_scf:
        builder.base_final_scf.pseudo_family = Str(pseudo_family)
        builder.base_final_scf.kpoints_distance = Float(kpoints_distance)
        builder.base_final_scf.pw.code = code
        builder.base_final_scf.pw.parameters = Dict(dict=parameters)
        builder.base_final_scf.pw.metadata.options = get_default_options(
            max_num_machines, max_wallclock_seconds, with_mpi)

    launch.launch_process(builder, daemon)
Esempio n. 3
0
def launch(code, structure, pseudo_family, kpoints, max_num_machines,
           max_wallclock_seconds, daemon, ecutwfc, ecutrho, hubbard_u,
           hubbard_v, hubbard_file_pk, starting_magnetization, smearing,
           automatic_parallelization, clean_workdir):
    """
    Run the PwBaseWorkChain for a given input structure
    """
    from aiida.orm.data.base import Bool, Str
    from aiida.orm.data.parameter import ParameterData
    from aiida.orm.utils import WorkflowFactory
    from aiida.work.launch import run, submit
    from aiida_quantumespresso.utils.resources import get_default_options, get_automatic_parallelization_options

    PwBaseWorkChain = WorkflowFactory('quantumespresso.pw.base')

    parameters = {
        'SYSTEM': {
            'ecutwfc': ecutwfc,
            'ecutrho': ecutrho,
        },
    }

    try:
        hubbard_file = validate.validate_hubbard_parameters(
            structure, parameters, hubbard_u, hubbard_v, hubbard_file_pk)
    except ValueError as exception:
        raise click.BadParameter(exception.message)

    try:
        validate.validate_starting_magnetization(structure, parameters,
                                                 starting_magnetization)
    except ValueError as exception:
        raise click.BadParameter(exception.message)

    try:
        validate.validate_smearing(parameters, smearing)
    except ValueError as exception:
        raise click.BadParameter(exception.message)

    inputs = {
        'code': code,
        'structure': structure,
        'pseudo_family': Str(pseudo_family),
        'kpoints': kpoints,
        'parameters': ParameterData(dict=parameters),
    }

    if automatic_parallelization:
        automatic_parallelization = get_automatic_parallelization_options(
            max_num_machines, max_wallclock_seconds)
        inputs['automatic_parallelization'] = ParameterData(
            dict=automatic_parallelization)
    else:
        options = get_default_options(max_num_machines, max_wallclock_seconds)
        inputs['options'] = ParameterData(dict=options)

    if clean_workdir:
        inputs['clean_workdir'] = Bool(True)

    if daemon:
        workchain = submit(PwBaseWorkChain, **inputs)
        click.echo('Submitted {}<{}> to the daemon'.format(
            PwBaseWorkChain.__name__, workchain.pk))
    else:
        run(PwBaseWorkChain, **inputs)
Esempio n. 4
0
def run_calculation(
    name, 
    struct, 
    group, 
    codename, 
    pseudo_family, 
    k_distance=0.20, 
    scale_element_init_moment={}, 
    input_namelists={}, 
    code_runtime_options=None
):
    """
    This function converts a given initial structure into an AiiDA readable format
    to perform a static SCF calculation.
     
    Parameters
    ----------
    name : str
        The name of the structure or calculations eg. name='Fe'
    struct : Structure object
        The defect structure
    group : str
        The name of the group to store AiiDA nodes on AiiDA database. Its advisable to keep track
        of this name to make sure you organize your data
    codename : str
        The name of the code configured on AiiDA database to perform this type of calculations
    pseudo_family : str
        A pseudopotential family configured on AiiDA database
    k_distance : float
        The density of k-point mesh use for k-point integration in DFT. For more see this
        material cloud page for its usage: https://www.materialscloud.org/work/tools/qeinputgenerator
        Default=0.2.
    scale_element_init_moment : dict
        A user define dictionary type of magnetic ions to scale its magnetic moment.
        Default={}.
    input_namelists : dict
        A user define Quantum ESPRESSO (QE) input namelists. Default={}
    mu_plus : bool
        If True, to specify a total charge of the system and initialise a
        starting charge of muon. Defualt=False
    code_runtime_options : None
        The HPC requirements of number of nodes and k-points. Depends on the code 
        configure in `codename`.
        
    Returns
    -------
    Submit calculation to AiiDA daemon 
    """

    from aiida_quantumespresso.utils.resources import get_default_options, get_automatic_parallelization_options
    from aiida.orm import Group

    g, just_created = Group.objects.get_or_create(group)

    code = Code.get_from_string(codename)
    builder = code.get_builder()

    builder.metadata.label = "{} - Unitcell".format(name)
    builder.metadata.description = "Magnetic test for - {}".format(name)

    StructureData     = DataFactory("structure")
    labeled_structure, nspin, magnetic_elements_kinds = analyze_pymatgen_structure(struct, mark_muon=False)
    builder.structure = StructureData(pymatgen=labeled_structure)

    structure_copy = StructureData(pymatgen=labeled_structure)

    if nspin == 2:
        # Set all polarizations to 0.4
        for k in magnetic_elements_kinds.keys():
            for idx in magnetic_elements_kinds[k].keys():
                magnetic_elements_kinds[k][idx] = magnetic_elements_kinds[k][idx] * scale_element_init_moment.get(k, 1.)
    elif nspin == 4:
        raise NotImplemented("Non collinear case not implemented.")


    Dict = DataFactory('dict')
    parameters_dict = {
        'CONTROL': {
            'calculation': 'scf',
            'restart_mode': 'from_scratch',
        },
        'SYSTEM': {
            'ecutwfc': 60.,
            'ecutrho': 600.,
            'occupations':'smearing',
            'smearing': 'm-v',
            'degauss' : 0.02,
            'nspin': nspin, #
        },
        'ELECTRONS': {
            'conv_thr'    : 1.e-7,
            'mixing_beta' : 0.30,
            'mixing_mode' : 'local-TF'
        }
    }

    #print('Old Dictionary\n', parameters_dict)

    #override
    parameters_dict=merge(input_namelists, parameters_dict)

    #print('New Dictionary\n', parameters_dict)

    parameters = Dict(dict=parameters_dict)
    builder.parameters = parameters

    if nspin == 2:
        parameters_dict['SYSTEM']['starting_magnetization'] = merge_dict_of_dicts(magnetic_elements_kinds)

    KpointsData = DataFactory('array.kpoints')
    #kpoints = KpointsData()
    #kpoints.set_kpoints_mesh([2,2,2],offset=(0,0,0))

    kpoints = KpointsData()
    kpoints.set_cell_from_structure(builder.structure)
    kpoints.set_kpoints_mesh_from_density(k_distance, force_parity=False)
    kpoints.store()

    settings_dict={}
    num_k_points = np.prod(kpoints.get_kpoints_mesh()[0])
    if num_k_points==1:
        settings_dict={'gamma_only': True}
    else:
        settings_dict={'gamma_only': False}


    builder.pseudos = get_pseudos_from_structure(structure_copy, pseudo_family)

    #builder.metadata.options.resources = resources

    #builder.metadata.options.max_wallclock_seconds = 259200  #86400

    builder.parameters = parameters
    builder.kpoints = kpoints

    # AAAA: automatic_parallelization does not work!!!
    automatic_parallelization = False
    if automatic_parallelization:
        automatic_parallelization = get_automatic_parallelization_options(1,  24*60*60-60*5)
        builder.automatic_parallelization = Dict(dict=automatic_parallelization)
    else:
        if code_runtime_options is None or code_runtime_options == '':
                                        # num machines, time, mpi
            default_options = get_default_options(1, 24*60*60-60*5, True)
            builder.metadata.options = default_options
        else:
            exec_options = code_runtime_options.split('|')[0].split()
            default_options = get_default_options(int(exec_options[0]), int(exec_options[1]), True)
            builder.metadata.options = default_options
        if code_runtime_options is None or code_runtime_options == '':
            npool = np.min([4, num_k_points])
            settings_dict['cmdline'] = ['-nk', str(npool), '-ndiag', '1']
        else:
            parallel_options = code_runtime_options.split('|')[1]
            settings_dict['cmdline'] = parallel_options.strip().split()

    clean_workdir = False
    final_scf = False
    if clean_workdir:
        builder.clean_workdir = Bool(True)

    if final_scf:
        builder.final_scf = Bool(True)

    calc = submit(builder)
    if not (g is None):
        g.add_nodes(calc)

    print(name +' magnetic test calculation created  with PK = {}'.format(calc.pk))
    return calc
Esempio n. 5
0
def run_wc(
    index, 
    name, 
    struct, 
    group, 
    codename, 
    pseudo_family, 
    k_distance=0.20, 
    scale_element_init_moment={}, 
    input_namelists={}, 
    mu_plus=False, 
    code_runtime_options=None
):
    """
    This function converts a given initial structure into an AiiDA readable format
    to runs an AiiDA RELAX Workchain.
     
    Parameters
    ----------
    index : int
        An index of the structure supply eg. index=0
    name : str
        The name of the structure or calculations eg. name='Fe'
    struct : Structure object
        The defect structure
    group : str
        The name of the group to store AiiDA nodes on AiiDA database. Its advisable to keep track
        of this name to make sure you organize your data
    codename : str
        The name of the code configured on AiiDA database to perform this type of calculations
    pseudo_family : str
        A pseudopotential family configured on AiiDA database
    k_distance : float
        The density of k-point mesh use for k-point integration in DFT. For more see this
        material cloud page for its usage: https://www.materialscloud.org/work/tools/qeinputgenerator
        Default=0.2.
    scale_element_init_moment : dict
        A user define dictionary type of magnetic ions to scale its magnetic moment.
        Default={}.
    input_namelists : dict
        A user define Quantum ESPRESSO (QE) input namelists. Default={}
    mu_plus : bool
        If True, to specify a total charge of the system and initialise a
        starting charge of muon. Defualt=False
    code_runtime_options : None
        The HPC requirements of number of nodes and k-points. Depends on the code 
        configure in `codename`.
        
    Returns
    -------
    Submit calculation to AiiDA daemon 
    """

    from aiida_quantumespresso.utils.resources import get_default_options, get_automatic_parallelization_options

    builder = WorkflowFactory('quantumespresso.pw.relax').get_builder()
    builder.relaxation_scheme = Str('relax')

    builder.metadata.label = "{}-{}".format(name, index)
    builder.metadata.description = "Muon site relaxation workchain for {}, with initial position {} {} {}".format(name, *struct[-1].coords.tolist())
    #builder.meta_convergence=Bool(False)

    StructureData     = DataFactory("structure")
    #builder.structure = StructureData(pymatgen=struct)
    #builder.structure, nspin, magnetic_elements_kinds = pymatgen_to_aiida(struct, StructureData)
    labeled_structure, nspin, magnetic_elements_kinds = analyze_pymatgen_structure(struct)
    builder.structure = StructureData(pymatgen=labeled_structure)
    
    # Append all type of species, magnetic or not
    species = [str(site.specie.symbol) for site in labeled_structure]
    distinct_species =  list(set(species))
    for mag_kinds in magnetic_elements_kinds.values():
        distinct_species.append(list(mag_kinds.keys()))

    if nspin == 2:
        # Set all polarizations to 0.4
        for k in magnetic_elements_kinds.keys():
            for idx in magnetic_elements_kinds[k].keys():
                magnetic_elements_kinds[k][idx] = magnetic_elements_kinds[k][idx] * scale_element_init_moment.get(k, 1.)
    elif nspin == 4:
        raise NotImplemented("Non collinear case not implemented.")

    # Default QE inputs
    Dict = DataFactory('dict')
    parameters_dict = {
        'CONTROL': {
            'calculation': 'relax',
            'restart_mode': 'from_scratch',
            'nstep': 150
      #      'forc_conv_thr': 1,
      #      'etot_conv_thr': 1000
        },
        'SYSTEM': {
            'ecutwfc': 60.,
            'ecutrho': 600.,
            'occupations':'smearing',
            'smearing': 'gaussian',
            'degauss' : 0.02,
            'nspin': nspin, 
        },
        'ELECTRONS': {
            'electron_maxstep': 500,
            'conv_thr'    : 1.0e-7,
            'mixing_beta' : 0.30,
            'mixing_mode' : 'local-TF'
        }
    }
    if nspin == 2:
        parameters_dict['SYSTEM']['starting_magnetization'] = merge_dict_of_dicts(magnetic_elements_kinds)

    if mu_plus:
        parameters_dict['SYSTEM']['starting_charge'] = {'No': 0.6}
        parameters_dict['SYSTEM']['tot_charge'] = 1.

    input_namelistss = copy.deepcopy(input_namelists)
    if input_namelistss:
        # Remove some stuff from input namelist
        # lets comment the stuffs below
        # In my opinion are a mess
        # dictionary changes size for each iterations
        input_namelistss.pop('CONTROL',0)
        input_namelistss.pop('K_POINTS',0)
        input_namelistss.pop('CELL_PARAMETERS',0)
        input_namelistss.pop('ATOMIC_FORCES',0)
        
        if 'SYSTEM' in input_namelistss.keys():
            for kw in ('nat ntyp A B C cosAB cosAC cosBC nbnd tot_charge').split():
                r = input_namelistss['SYSTEM'].pop(kw,'')
                if r:
                    print('Your setting for {} has been removed'.format(r))

            for kw in input_namelistss['SYSTEM'].keys():
                r = ''
                if 'celldm' in kw:
                    r = input_namelistss['SYSTEM'].pop(kw)
                if 'starting_' in kw:
                    r = input_namelistss['SYSTEM'].pop(kw)
                if r:
                    print('Your setting for {} has been removed'.format(r))
        
        # add hubbard parameters
        lda_plus_u_kind = 0
        if 'Hubbard_U' in input_namelistss['SYSTEM'].keys():
            # Get hubbard values from user defined input nameliest
            hubbard_dict = input_namelistss['SYSTEM']['Hubbard_U']
            # The eligible hubbard elements define by user
            hubbard_species = _distinct_species(distinct_species)
            # Specify the hubbard parameters
            hubbard_parameters = set_hubbard_u_parameters(hubbard_species, hubbard_dict)  
            input_namelistss['SYSTEM']['Hubbard_U'] = hubbard_parameters            
            if 'Hubbard_J' in input_namelistss['SYSTEM'].keys():
                # Assumed same as Hubbard U parameters
                input_namelistss['SYSTEM']['Hubbard_J'] = hubbard_parameters
                lda_plus_u_kind = 1
            if 'Hubbard_V' in input_namelistss['SYSTEM'].keys():
                # Assumed same as Hubbard U parameters
                input_namelistss['SYSTEM']['Hubbard_V'] = hubbard_parameters               
                lda_plus_u_kind = 2            
        input_namelistss['SYSTEM']['lda_plus_u_kind'] = lda_plus_u_kind
        parameters_dict = merge(input_namelistss, parameters_dict)

    parameters = Dict(dict=parameters_dict)
 
    builder.base.pseudo_family = Str(pseudo_family)

    #builder.base.kpoints_distance = Float(0.4)
    KpointsData = DataFactory('array.kpoints')
    kpoints = KpointsData()
    kpoints.set_cell_from_structure(builder.structure)
    #set kpoint mesh based on density
    kpoints.set_kpoints_mesh_from_density(k_distance, force_parity=False)
    kpoints.store()

    settings_dict={}
    # Number of k-points to determine K-point integration type
    # Gamma or Automatic by Monkhorst-Pack
    num_k_points = np.prod(kpoints.get_kpoints_mesh()[0])
    if num_k_points==1:
        settings_dict={'gamma_only': True}
    else:
        settings_dict={'gamma_only': False}

    builder.base.kpoints = kpoints

    builder.base.pw.code = Code.get_from_string(codename)
    builder.base.pw.parameters = parameters

    #if hubbard_file:
    #    builder.base.pw.hubbard_file = hubbard_file

    # AAAA: automatic_parallelization does not work!!!
    automatic_parallelization = False
    if automatic_parallelization:
        automatic_parallelization = get_automatic_parallelization_options(1,  24*60*60-60*5)
        builder.base.automatic_parallelization = Dict(dict=automatic_parallelization)
    else:
        if code_runtime_options is None or code_runtime_options == '':
                                        # num machines, time, mpi
            default_options = get_default_options(1, 24*60*60-60*5, True)
            builder.base.pw.metadata.options = default_options
        else:
            exec_options = code_runtime_options.split('|')[0].split()
            #default_options = get_default_options(int(exec_options[0]), int(exec_options[1]), True)
            #builder.base.pw.metadata.options = default_options
            builder.base.pw.metadata.options.resources={'num_machines': int(exec_options[0])}
            builder.base.pw.metadata.options.max_wallclock_seconds = int(exec_options[1])
            builder.base.pw.metadata.options.withmpi = True
            #builder.base.pw.metadata.options.mpirun_extra_params='--map-by socket:PE=8 --rank-by core'.split()
        if code_runtime_options is None or code_runtime_options == '':
            npool = np.min([4, num_k_points])
            settings_dict['cmdline'] = ['-nk', str(npool), '-ndiag', '1']
        else:
            parallel_options = code_runtime_options.split('|')[1]
            settings_dict['cmdline'] = parallel_options.strip().split()

    builder.base.pw.settings = Dict(dict=settings_dict)

    clean_workdir = False
    final_scf = False
    if clean_workdir:
        builder.clean_workdir = Bool(True)

    if final_scf:
        builder.final_scf = Bool(True)

    calc = submit(builder)
    if not (group is None):
        group.add_nodes(calc)
    return calc
Esempio n. 6
0
def launch_workflow(code, structure, pseudo_family, kpoints_distance, ecutwfc,
                    ecutrho, hubbard_u, hubbard_v, hubbard_file_pk,
                    starting_magnetization, smearing,
                    automatic_parallelization, clean_workdir, max_num_machines,
                    max_wallclock_seconds, with_mpi, daemon):
    """Run a `PwBandsWorkChain`."""
    # pylint: disable=too-many-statements
    from aiida.orm import Bool, Float, Dict
    from aiida.plugins import WorkflowFactory

    from aiida_quantumespresso.utils.resources import get_default_options, get_automatic_parallelization_options

    builder = WorkflowFactory('quantumespresso.pw.bands').get_builder()

    cutoff_wfc, cutoff_rho = pseudo_family.get_recommended_cutoffs(
        structure=structure, unit='Ry')

    parameters = {
        'CONTROL': {
            'calculation': 'relax',
        },
        'SYSTEM': {
            'ecutwfc': ecutwfc or cutoff_wfc,
            'ecutrho': ecutrho or cutoff_rho,
        },
    }

    try:
        hubbard_file = validate.validate_hubbard_parameters(
            structure, parameters, hubbard_u, hubbard_v, hubbard_file_pk)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    try:
        validate.validate_starting_magnetization(structure, parameters,
                                                 starting_magnetization)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    try:
        validate.validate_smearing(parameters, smearing)
    except ValueError as exception:
        raise click.BadParameter(str(exception))

    pseudos = pseudo_family.get_pseudos(structure=structure)
    parameters = Dict(dict=parameters)

    builder.structure = structure
    builder.relax.base.pw.code = code
    builder.relax.base.pw.parameters = parameters
    builder.relax.base.pw.pseudos = pseudos
    builder.relax.base.kpoints_distance = Float(kpoints_distance)
    builder.relax.meta_convergence = Bool(False)
    builder.scf.pw.code = code
    builder.scf.pw.parameters = parameters
    builder.scf.pw.pseudos = pseudos
    builder.scf.kpoints_distance = Float(kpoints_distance)
    builder.bands.pw.code = code
    builder.bands.pw.parameters = parameters
    builder.bands.pw.pseudos = pseudos

    if hubbard_file:
        builder.relax.base.pw.hubbard_file = hubbard_file
        builder.scf.base.pw.hubbard_file = hubbard_file
        builder.bands.base.pw.hubbard_file = hubbard_file

    if automatic_parallelization:
        auto_para = Dict(dict=get_automatic_parallelization_options(
            max_num_machines, max_wallclock_seconds))
        builder.relax.base.automatic_parallelization = auto_para
        builder.scf.automatic_parallelization = auto_para
        builder.bands.automatic_parallelization = auto_para
    else:
        metadata_options = get_default_options(max_num_machines,
                                               max_wallclock_seconds, with_mpi)
        builder.relax.base.pw.metadata.options = metadata_options
        builder.scf.pw.metadata.options = metadata_options
        builder.bands.pw.metadata.options = metadata_options

    if clean_workdir:
        builder.clean_workdir = Bool(True)

    launch.launch_process(builder, daemon)