def run_sweep(args_dict, base_outdir, extra_argsets=None, **kwargs):
    """Run a parameter sweep


    args_dict is a dictionary of argument lists.

    extra_argsets is a list of argdicts for arguments which have to come
    in groups.
    """

    # Generate list of parameter sets
    if extra_argsets is not None:
        parameter_dicts = sum([generate_argdicts(args_dict, a) for a in extra_argsets], [])
    else:
        parameter_dicts = generate_argdicts(args_dict, None)

    # Find out which arguments have different values in different runs
    varying_args = utils.find_varying_value_keys(parameter_dicts)

    # Run on all args.
    out = utils.parallel_map(_run, parameter_dicts, it.repeat(base_outdir),
                             it.repeat(varying_args), **kwargs)

    # Extract err_codes etc into separate lists and force execution (just
    # in case it's still an iterator)
    err_codes, outdirs = utils.unzip(list(out))

    return err_codes, outdirs
def parse_parameter_sweep(root_dirs, skip_failed=False, **kwargs):
    """Recursively parse directories inside each root_dir, in parallel unless
    serial_mode=True is set.

    If skip_failed then skip anything for which run_failed(dir) returns
    false.
    """
    result_dirs = []
    for root_dir in root_dirs:
        for dirname, _, _ in os.walk(root_dir):
            has_info = os.path.isfile(pjoin(dirname, "info"))
            fail_skip = skip_failed and run_failed(dirname)

            if has_info and not fail_skip:
                result_dirs.append(dirname)
            elif fail_skip:
                print("Skipping", dirname, "because it failed")

    results = utils.parallel_map(parse_run, result_dirs, **kwargs)

    return results
def main():

    parser = argparse.ArgumentParser(description=main.__doc__,

    # Don't mess up my formating in the help message
    formatter_class=argparse.RawDescriptionHelpFormatter)

    parser.add_argument('--clean', action='store_true', help='delete old data')
    parser.add_argument('--serial', action='store_true',
                         help="Don't do parallel sweeps")
    parser.add_argument('--outdir', help='delete old data')
    parser.add_argument('--quick', action='store_true',
                        help='quick version of parameters for testing')
    args = parser.parse_args()

    if args.outdir is None:
        args.outdir = os.path.abspath('../experiments/intermag')

    argsdict = {
                '-driver' : ['ll', 'llg'],
                '-tmax' : 4,
                '-hlib-bem' : 0,
                '-renormalise' : 0,
                '-mesh' : ['ut_sphere'], # 'sq_square'],
                '-ms-method' : ['implicit', 'disabled', 'decoupled', 'sphere'],
                '-solver' : 'gmres',
                "-matrix-type" : "som",
                '-prec' : 'som-main-ilu-1',
                '-ts' : ['rk2', 'midpoint-bdf', 'euler'],
                '-scale' : 2,
                '-fd-jac' : 1,
                '-damping' : [1.0, 0.1, 0.01],
                '-check-angles' : 1,
                }
    refines = [1, 2, 3, 4]

    # Only do a couple of things for a test run
    if args.quick:
        argsdict['-ms-method'] = 'disabled'
        argsdict['-damping'] = 1.0
        argsdict['-ts'] = 'euler'
        refines = [1, 2, 3]


    # The exact function to run
    f = par(locate_stable_points,
            refines_list = refines,
            dt_guess=0.1,
            dir_naming_args=mm.argdict_varying_args(argsdict),
            root_outdir=args.outdir,
            nbisection=2)

    # Create list of all possible combinations of args
    argsets = mm.product_of_argdict(argsdict)

    # Filter out impossible combinations, bit hacky...
    def is_bad_combination(data):
        if data['-ts'] == 'rk2' or data['-ts'] == 'euler':
            if data['-driver'] == 'llg' or data['-ms-method'] == 'implicit':
                return True
        elif data['-ts'] == 'midpoint-bdf' or data['-ts'] == 'bdf2':
            if data['-driver'] == 'll':
                return True

        return False

    argsets = [a for a in argsets if not is_bad_combination(a)]


    dts = list(utils.parallel_map(f, argsets, serial_mode=args.serial))

    print(dts)

    return 0