Source code for pylbo.automation.api

from __future__ import annotations

import os
from typing import Union

from pylbo.automation.generator import ParfileGenerator
from pylbo.automation.runner import LegolasRunner


[docs]def generate_parfiles( parfile_dict: dict, basename: str = None, output_dir: Union[str, os.PathLike] = None, subdir: bool = True, prefix_numbers: bool = True, nb_prefix_digits: int = 4, ) -> list[str]: """ Generates parfiles based on a given configuration dictionary. The separate namelists do not have to be taken into account, and a normal dictionary should be supplied where the keys correspond to the namelist items that are required. Typechecking is done automatically during parfile generation. Parameters ---------- parfile_dict : dict Dictionary containing the keys to be placed in the parfile. basename : str The basename for the parfile, the `.par` suffix is added automatically and is not needed. If multiple parfiles are generated, these will be prepended by a 4-digit number (e.g. 0003myparfile.par). If not provided, the basename will default to `parfile`. output_dir : str, ~os.PathLike Output directory where the parfiles are saved, defaults to the current working directory if not specified. A subdirectory called `parfiles` will be created in which the parfiles will be saved. subdir : boolean If `True` (default), creates a subdirectory `parfiles` in the output folder. prefix_numbers : boolean If `True` prepends the `basename` by a n-digit number (e.g. xxxxmyparfile.par). The number of digits is specified by `nb_prefix_digits`. nb_prefix_digits : int Number of digits to prepend to the `basename` if `prefix_numbers` is `True`. Defaults to 4. Notes ----- This routine is quite flexible and specifically designed for parametric studies. You can specify both single values and list-like items as dictionary items. This routine will automatically generate multiple parfiles if lists/numpy arrays are present. Returns ------- parfiles : list A list with the paths to the parfiles that were generated. This list can be passed immediately to :func:`pylbo.run_legolas`. Examples -------- This will generate a single parfile in a subdirectory `parfile` of the current working directory. >>> import pylbo >>> config = { >>> "geometry": "Cartesian", >>> "x_start": 0, >>> "x_end": 1, >>> "equilibrium_type": "resistive_homo", >>> "gridpoints": 100, >>> "write_eigenfunctions": True, >>> "basename_datfile": "my_run", >>> "output_folder": "output", >>> } >>> parfile = pylbo.generate_parfiles(config) This will generate 10 parfiles in the directory `my_parfiles` relative to the current working directory. The first parfile will have `x_end = 1.0` and 100 gridpoints, the second one will have `x_end = 2.0` and 150 gridpoints, etc. >>> import pylbo >>> import numpy as np >>> config = { >>> "geometry": "Cartesian", >>> "x_start": 0, >>> "x_end": np.arange(1, 11) >>> "number_of_runs": 10 >>> "equilibrium_type": "resistive_homo", >>> "gridpoints": np.arange(100, 600, 50), >>> "write_eigenfunctions": True, >>> "basename_datfile": "my_run", >>> "output_folder": "output", >>> } >>> parfile_list = pylbo.generate_parfiles(config, output_dir="my_parfiles") """ pfgen = ParfileGenerator( parfile_dict=parfile_dict, basename=basename, output_dir=output_dir, subdir=subdir, prefix_numbers=prefix_numbers, nb_prefix_digits=nb_prefix_digits, ) pfgen.create_namelist_from_dict() return pfgen.generate_parfiles()
[docs]def run_legolas( parfiles: Union[str, list, os.PathLike], remove_parfiles: bool = False, nb_cpus: int = 1, executable: Union[str, os.PathLike] = None, ) -> None: """ Runs the legolas executable for a given list of parfiles. If more than one parfile is passed, the runs can be performed in parallel using the multiprocessing module. Parallelisation can be enabled by setting the `nb_cpus` kwarg to a number greater than one, and is disabled by default. Every CPU will have a single legolas executable subprocess associated with it. Parameters ---------- parfiles : str, list, numpy.ndarray A string, list or array containing the paths to the parfile(s). Accepts the output of :func:`pylbo.generate_parfiles`. remove_parfiles : bool If `True`, removes the parfiles after running Legolas. This will also remove the containing folder if it turns out to be empty after the parfiles are removed. If there are other files still in the folder it remains untouched. nb_cpus : int The number of CPUs to use when running Legolas. If equal to 1 then parallelisation is disabled. Defaults to the maximum number of CPUs available if a number larger than the available number is specified. executable : str, ~os.PathLike The path to the legolas executable. If not specified, defaults to the standard one in the legolas home directory. Notes ----- If multiprocessing is enabled, it is usually a good idea to have the number of runs requested divisible by the number of CPUs that are available. For example, if 24 runs are requested it is good practice to use either 2, 4, 6 or 8 CPUs, and avoid numbers like 3, 5 and 7. Examples -------- The example below will run a list of parfiles using using a local legolas executable from the current directory, on 4 CPU's. >>> import pylbo >>> from pathlib import Path >>> files = sorted(Path("parfiles").glob("*.dat")) >>> pylbo.run_legolas(files, nb_cpus=4, executable="legolas") """ runner = LegolasRunner(parfiles, remove_parfiles, nb_cpus, executable) runner.execute()