This package provides a set of scripts for supercomputer job submission for VASP, MACE multihead fine-tuning, and ATAT via Slurm. It is tailored to research performed in the Inverse Materials Design group, creating a unified interface for running calculations across different high-performance computing clusters (e.g., Athena, Ares, Helios, LUMI).
git clone https://git.sr.ht/~yantar92/IMDgroup-gorun
cd IMDgroup-gorun
pip install .
The tool relies on specific environment variables and a TOML configuration file to adapt to different cluster environments.
Add the following to your .bashrc or submission environment:
IMDGroup: Path to the directory containing configuration files (specifically$IMDGroup/dist/etc/gorun.toml).VASP_PATH: Root directory of the VASP installation. The scripts expect binaries at$VASP_PATH/bin/vasp_std, etc.VASP_PP_PATH: Path to VASP pseudopotentials (required for automatic POTCAR generation).CLUSTER_NAME: (Optional) Manually override the cluster name detection (usually automatic viauname -n).
The behavior of gorun is defined in a TOML file. This file maps
hostnames to cluster definitions and specifies available queues,
modules to load, and default resource limits.
Software-specific settings are namespaced under the server section.
[cluster.names]
lumi = ['uan01', 'uan02']
[lumi]
queues = ['standard', 'small']
[lumi.vasp]
setup = "module load LUMI/24.03 ..."
mpiexec = "srun"
[lumi.mace]
setup = "module use /appl/local/laifs/modules && module load lumi-aif-singularity-bindings"
sif = "/appl/local/laifs/containers/..."
python_env = "/projappl/.../mace_env"
[lumi.standard]
type = 'CPU'
partition = 'standard'
max-nodes = 512
max-time = '48:00:00'
All subcommands (vasp, mace-finetune, maps, atat-local,
gpu) accept a common set of flags in addition to their own options:
-
--config PATH: Path to TOML configuration file (default:$IMDGroup/dist/etc/gorun.toml). -
--queue NAME: Submit to a specific queue (default: let the scheduler pick the one with the earliest finish time). -
--local: Run directly on the login node instead of submitting viasbatch. -
--mark: Prepare the directory and create agorun_readymarker file, but do not submit. -
--force: Skip convergence checks. -
--keep FILE: Do not regenerateFILEif it already exists (repeatable). -
--max-slurm-jobs N: Wait until the number of running Slurm jobs drops below N before submitting (default: 0 = no limit). -
--dir DIR...: Run the pipeline in eachDIRinstead of the current directory (one or more, space-separated). gorun processes each directory in turn within a single process, avoiding the Python/import startup cost of invokinggorunonce per directory on slow filesystems (e.g. Lustre). Missing directories are skipped with a warning. A directory that fails is reported and the run continues, exiting non-zero at the end if any directory failed. Forvasp, positionalNODES=/=TIMEmust come before--dir.
Submit a VASP job from the current directory. The plain gorun
command (without subcommand) is treated as gorun vasp. Positional
arguments specify the number of nodes and the time limit:
# Submit job requesting 2 nodes for 24 hours
gorun vasp 2 24:00:00
# Shorthand:
gorun 2 24:00:00
# Use default nodes/time from config (positional args optional)
gorun vasp
-
--config PATH: Path to TOML configuration file (default:$IMDGroup/dist/etc/gorun.toml). -
--queue NAME: Submit to a specific queue (default: let the scheduler pick the one with the earliest finish time). -
--vasp {ncl,gam,std}: Select the VASP binary variant (default:ncl). -
--local: Run VASP directly on the login node instead of submitting viasbatch. Useful for testing short jobs. -
--mark: Prepare the directory and create agorun_readymarker file, but do not submit. Usegorun-all-ready.shto submit multiple marked directories later (see 5). -
--force: Skip convergence checks and run VASP even if the directory already contains converged output. -
--keep FILE: Do not regenerateFILEif it already exists (repeatable). For VASP, useful values arePOTCARandPOSCAR. Example:--keep POTCAR --keep POSCAR. -
--no-clean: Skip cleanup of old SLURM log files in NEB subdirectories. -
--no-incar-py: IgnoreINCAR.pyeven if present; run VASP directly. -
--no-vasp-config: Do not source the cluster's VASP module setup (theVASP-setupline from the config). Use when the environment is already configured upstream. -
--incar KEY:VAL ...: Modify INCAR parameters before submission. Space-separatedKEY:VALpairs. SetVALtoNoneto delete a key. Example:gorun vasp --incar ALGO:Normal NELM:200 NSW:50 -
--max_slurm_jobs N: Wait until the number of running Slurm jobs drops below N before submitting (default: 0 = no limit). -
NODES,TIME: Positional arguments: number of nodes and time limit inhh:mm:ssformat. Both are optional; defaults come from the config file.
# Submit to a specific GPU queue with 8 nodes for 48 hours
gorun vasp --queue plgrid-gpu-a100 8 48:00:00
# Use gamma-point-only VASP binary, 1 node, 1 hour
gorun vasp --vasp gam 1 1:00:00
# Run locally (no sbatch) for quick testing
gorun vasp --local 1 0:30:00
# Prepare directory for later batch submission
gorun vasp --mark 4 24:00:00
# Override INCAR settings before submission
gorun vasp --incar ISIF:3 NSW:100 2 24:00:00
# Force re-run even if already converged
gorun vasp --force 2 24:00:00
# Limit concurrent jobs to 20
gorun vasp --max-slurm-jobs 20 2 24:00:00
# Keep existing POTCAR (and use --keep for POSCAR too)
gorun vasp --keep POTCAR --keep POSCAR
# Run the same submission in several directories in one process
gorun vasp --mark --keep POTCAR --dir run1 run2
Before submission, gorun runs the following steps in order:
- Safety checks :: Aborts if
INCARis missing, or if a job is alreadyRUNNINGor queued in the same directory. - Convergence check :: If the directory contains converged output,
exits (unless
--forceis set). If multiple sequentialINCAR.*files exist, replacesINCARwith the next one and continues. - Backup :: If VASP outputs already exist, copies the directory to
gorun_N(incrementing N) and compresses the previous backup.WAVECARis excluded from backups. - INCAR modification :: If
--incarwas given, applies the changes now. - Input sanitization :: Cleans
INCAR,POSCAR,KPOINTS(newlines, BOMs, blank lines). - POTCAR generation :: Generates
POTCARfromPOSCARusing ASE with VASP-recommended pseudopotentials (PBE functional). Skips if--keep_potcaris set. - vdW kernel :: Copies
vdw_kernel.bindatfrom$VASP_PATHif the INCAR requests vdW corrections. - Cleanup :: Removes old SLURM log files and zero-size VASP outputs.
If no --queue is given, gorun calls sbatch --test-only for
every partition listed in the config. It estimates the finish time
for each option (waiting time + run time scaled by CPU count) and
selects the partition that finishes earliest.
If INCAR.py is present in the directory and --no_incar_py is not
set, gorun wraps VASP execution inside a Python script using ASE.
The script has the calculator pre-configured and can access a
IMDGVaspDir object via the variable vaspdir:
# Example INCAR.py contents
# Access the pre-set ASE calculator
from ase.constraints import FixAtoms
atoms.set_constraint(FixAtoms(mask=[atom.symbol == 'Li' for atom in atoms]))
energy = atoms.get_potential_energy()
The generated Slurm script exports VASP_COMMAND that points back to
gorun vasp --local --no-incar-py --force --no-clean --keep POSCAR for
the ASE calculator to invoke.
Submit a MACE multihead fine-tuning job. The canonical subcommand is
mace-finetune. For backward compatibility, gorun-mace-finetune
and gorun-mace are also available as top-level entry points.
The workflow implements Method 1 from the MACE documentation – a two-stage multihead replay protocol:
fine_tuning_select— select replay configurations that best match the target dataset chemistry.run_train— train with a dual-head architecture (target head + pretraining head) to prevent catastrophic forgetting.
Both stages run sequentially in a single Slurm job.
If a RUNFILE.sh or RUNFILE.py exists in the working directory, its
content replaces the canned two-stage workflow. RUNFILE.sh takes
precedence over RUNFILE.py. Both are wrapped so they inherit the
cluster environment (see 3.2).
Use this when the standard two-stage protocol does not fit your use
case – for example, when you want to run mace.cli.eval or a custom
training loop.
All MACE parameters are stored in INCAR.toml in the working
directory, analogous to how VASP reads INCAR. This avoids repeating
long CLI invocations and keeps the run configuration alongside the
data.
INCAR.toml uses TOML sections to route parameters to the correct
stage:
- Top-level: gorun-specific keys (
model_path,replay_xyz,data_path,split_ratio,e0s, etc.) and shared keys (device,default_dtype). [fine_tuning_select]: parameters forwarded to Stage 1 (mace.cli.fine_tuning_select):num_samples,subselect,filtering_type,weight_pt,weight_ft, etc.[run_train]: parameters forwarded to Stage 2 (mace.cli.run_train):batch_size,lr,max_num_epochs,swa,ema, and all their sub-options.
Keys the adapter does not recognise default to [run_train], so
flat INCAR.toml files from earlier versions still work.
Example:
model_path = "13_MACE-MATPES-PBE-0_medium.model"
replay_xyz = "matpes-pbe-replay-data.xyz"
data_path = "result.pkl"
e0s = "{3:-0.01686124,6:-1.26246048,11:-0.22829243}"
[fine_tuning_select]
num_samples = 50000
subselect = "fps"
[run_train]
batch_size = 12
lr = 0.0009
swa = true
ema = true
max_num_epochs = 200
Almost all MACE training hyperparameters live in INCAR.toml:
batch_size, lr, weight_decay, max_num_epochs, swa,
swa_lr, start_swa, ema, ema_decay, energy_weight,
forces_weight, stress_weight, valid_fraction, compute_stress,
loss, force_mh_ft_lr, device, default_dtype, etc.
When no INCAR.toml exists, gorun mace-finetune bootstraps a full
template with every parameter at its default value, then reports an
error (exit code 1) because the required parameters are still unset.
Edit the file and run again.
Precedence: --incar overrides (highest) > explicit CLI flags >
INCAR.toml values > hardcoded adapter defaults. For example, with
INCAR.toml setting batch_size = 8 in [run_train], running
gorun mace-finetune uses 8. Adding --incar run_train.batch_size:16
overrides to 16.
Write-back: After parsing, if the merged parameters differ from the
existing file, INCAR.toml is updated (with the previous version
backed up to INCAR.toml.old). Only parameters whose value differs
from the adapter default are written; the file stays sparse.
Non-adapter keys in INCAR.toml (e.g., notes = "my experiment") are
preserved across writes. Gorun-level flags (force, local,
keep, etc.) in INCAR.toml trigger a warning and are ignored.
Only workflow and data-source parameters are CLI flags. All MACE
training hyperparameters live in INCAR.toml and can be overridden
via --incar.
-
--model-path PATH: Path to the foundation model (.modelfile). Required unless set inINCAR.toml. -
--replay-xyz PATH: Path to the replay/reference data (.xyzfile). Required unless set inINCAR.toml. -
--data-path PATH: Single training file (.xyzor.pkl). Split into train/val using--split-ratio(default:0.20). Set inINCAR.tomlor on the CLI. -
--train-data-path PATH+--val-data-path PATH: Pre-split training and validation files (.xyzor.pkl). Both must be provided together. Set inINCAR.tomlor on the CLI. -
--split-ratio FLOAT: Fraction of--data-pathto use for validation (default:0.20).
If neither --data-path nor the pre-split pair is given, the adapter
expects an existing train.xyz in the working directory (use
--keep to preserve it).
-
--new-model-name NAME: Name for the output fine-tuned model (default:finetuned_model.model). -
--seed N: Random seed for train/val split and training (default:1). -
--e0s STR: E0s string forheads.json(default: empty). -
--no-fine-tuning-select: Skip Stage 1 (useful ifselected_configs.xyzalready exists).
--incar KEY:VAL ...: Override anyINCAR.tomlparameter from the command line. Use dot notation to target a section:--incar run_train.lr:0.001 fine_tuning_select.num_samples:50000. Bare keys (no dot) default to[run_train]:--incar batch_size:16.
This is the primary mechanism for adjusting MACE training parameters
when running from the CLI. For example, to override the learning
rate and number of epochs without editing INCAR.toml:
--incar run_train.lr:0.0005 run_train.max_num_epochs:150.
-
--keep FILE: Do not regenerateFILEif it already exists (repeatable). Useful values:train.xyz,val.xyz,heads.json. -
--time_limit HH:MM:SS: Time limit (optional; defaults come from config). -
--queue NAME: Submit to a specific queue (default: auto-select earliest finish). -
--mark: Prepare directory and create agorun_readymarker without submitting. -
--local: Run directly on the login node (for testing). -
--force: Skip convergence checks. -
--max-slurm-jobs N: Wait until running Slurm jobs drop below N (default: 0 = no limit).
Before submission, gorun mace-finetune runs the following steps:
- INCAR.toml :: Reads
INCAR.toml(if present) and merges values with CLI arguments. Bootstraps a template file if none exists. Writes back changes if parameters differ. - Validation :: Checks that required parameters (
model_path,replay_xyz) are set and that the foundation model and replay data exist. - Data preparation :: Reads structures from
--data-pathor--train-data-path/--val-data-path, strips ASE constraints (preserving forces/energy/stress viaSinglePointCalculator), splits if needed, writestrain.xyzandval.xyz(unless--keepis set), and generatesheads.json. - Backup :: If previous outputs exist (logs, model files, checkpoints),
backs up the directory to
gorun_N. - Submission :: Generates and submits the two-stage Slurm script (or runs the RUNFILE if present).
# Basic fine-tuning from a pickle file (auto-split 80-20)
gorun mace-finetune \
--model-path 13_MACE-MATPES-PBE-0_medium.model \
--replay-xyz matpes-pbe-replay-data.xyz \
--data-path result.pkl \
--e0s "{3:-0.01686124,6:-1.26246048,11:-0.22829243}"
# Pre-split train/val files
gorun mace-finetune \
--model-path foundation.model \
--replay-xyz replay.xyz \
--train-data-path train.xyz --val-data-path val.xyz
# Skip the select stage, specify time limit
gorun mace-finetune \
--model-path foundation.model \
--replay-xyz replay.xyz \
--data-path result.pkl \
--no-fine-tuning-select \
48:00:00
# Keep existing xyz files, override training params via --incar
gorun mace-finetune \
--model-path foundation.model \
--replay-xyz replay.xyz \
--data-path result.pkl \
--keep train.xyz --keep val.xyz \
--seed 42 \
--incar run_train.batch_size:4 run_train.lr:0.0005
# Prepare for later batch submission
gorun mace-finetune \
--model-path foundation.model \
--replay-xyz replay.xyz \
--data-path result.pkl \
--mark
# Use INCAR.toml for almost all parameters
gorun mace-finetune 48:00:00
# (model_path, replay_xyz, data_path, e0s, etc. read from INCAR.toml)
# INCAR.toml provides defaults; override batch size from CLI
gorun mace-finetune --incar run_train.batch_size:16
# First run in a directory: bootstraps INCAR.toml with all defaults
gorun mace-finetune --model-path foundation.model --replay-xyz replay.xyz --data-path result.pkl
# Backward-compatible shorthand (gorun mace)
gorun mace --model-path foundation.model --replay-xyz replay.xyz --data-path result.pkl
# Backward-compatible entry points
gorun-mace --model-path foundation.model --replay-xyz replay.xyz --data-path result.pkl
gorun-mace-finetune --model-path foundation.model --replay-xyz replay.xyz --data-path result.pkl
Submit a generic GPU job from the current directory. The computation
is defined by a RUNFILE.sh or RUNFILE.py in the working directory
(RUNFILE.sh takes precedence). Use --script-name to specify a
different file.
GPU environment setup (module loads, PyTorch flags, cache directories,
OMP_NUM_THREADS, etc.) is read from the server config under
[gpu] → setup::
[lumi.gpu]
setup = """\\
module use /appl/local/laifs/modules
module load lumi-aif-singularity-bindings
export GORUN_WRAPPER="singularity exec ... bash"
export GORUN_INNER_SETUP="... module loads inside the container ..."
"""
If a derived adapter (e.g. MACE) has its own [<name>] section, it
takes precedence; [gpu] is only used as a fallback when the
adapter-specific section is missing or empty (see
gorun mace-finetune).
The RUNFILE is wrapped in a heredoc passed through GORUN_WRAPPER
and GORUN_INNER_SETUP, so it inherits the configured environment
automatically.
-
--script-name NAME: Script to run instead ofRUNFILE.sh/RUNFILE.py..pyfiles are run withpython -u; everything else (including.sh) withbash. -
TIME: Positional argument: time limit inhh:mm:ssformat (optional; defaults come from the config).
# Use the default RUNFILE.sh in the current directory
gorun gpu 48:00:00
# Use a custom script
gorun gpu --script-name train.py 24:00:00
# Run locally for testing
gorun gpu --local
# Prepare directory for later batch submission
gorun gpu --mark 48:00:00
# Submit to a specific queue
gorun gpu --queue plgrid-gpu-a100 24:00:00
# Custom script + keep marker
gorun gpu --script-name eval.sh --mark
Wrapper to submit ATAT's maps (Cluster Expansion) code to Slurm.
Launches maps on the compute node and configures it to use
gorun-atat-local as the calculation script.
-
--kpoints DENSITY(required): K-point density for VASP sub-jobs. -
--max_strain FRAC: Maximum allowed strain before a structure is flagged as an error (default:0.1). -
--frac_tol FRAC: Distance tolerance for rejecting structures with atoms too close together (default:0.5). -
--skip_relax: Skip the relaxation step in each sub-job (run only the SCF calculation). -
--sublattice_cutoff DIST: Mark a structure as error if its sublattice deviation exceeds this value (default: off). -
--time_limit HH:MM:SS: Time limit for themapsparent job (optional). -
--queue NAME: Submit to a specific queue (default: auto-select earliest finish). -
--config PATH: Path to configuration TOML (default:$IMDGroup/dist/etc/gorun.toml). -
--gorun_command PATH: Path to thegorunexecutable used bypollmach(default:gorunfrom$PATH). -
--local: Runmapsdirectly on the login node instead of submitting viasbatch. -
--maps_args ARGS: Additional arguments to pass through to themapsexecutable (space-separated).
# Basic cluster-expansion run
gorun maps --kpoints=3000 --max_strain=0.1
# Skip relaxation (SCF only), tighter strain tolerance
gorun maps --kpoints=4000 --max_strain=0.05 --skip_relax
# Custom sublattice deviation cutoff
gorun maps --kpoints=3000 --sublattice_cutoff=0.15
# Pass additional arguments to maps
gorun maps --kpoints=3000 --maps_args="-e=4 -gs=0.001"
Worker script invoked by ATAT's pollmach to run individual
structural calculations. Each call processes a single str.out
generated by maps, creating VASP inputs from the parent directory
as template.
-
--kpoints DENSITY(required): K-point density for the VASP run. -
--frac_tol FRAC: Reject structures where any two atoms are closer than this tolerance (default:0, meaning no rejection by distance). -
--max_strain FRAC: Reject structures whose volume change exceeds this fraction (default:0.1). -
--skip_relax: Skip the ionic relaxation step. Only the SCF calculation is performed. -
--sublattice_cutoff DIST: Flag structures whose sublattice deviation equals or exceeds this value. Writeserror_sublatticemarker (default: off). -
VASP_COMMAND [ARGS](positional, remainder): Command to invoke VASP. All remaining arguments are passed through verbatim.
Each sub-job goes through the following checks:
- Input derivation :: Reads
str.outand the parent directory to create VASP input files (written into./ATAT). - Distance check :: Rejects the structure if atoms are too close
(writes
error_atoms_too_close). - K-point grid check :: Rejects if the grid has too few points along
an axis (writes
error_kpoints_dim_sparse). - Relaxation :: Runs VASP in
./ATAT(skipped with--skip_relax). - Volume distortion check :: Rejects if the cell volume changed by
more than
--max_strain(writeserror_strain). - Sublattice check :: Detects sublattice flips. If a flip is found,
attempts to fit the refined lattice and updates
str.out. If deviation exceeds--sublattice_cutoff(writeserror_sublattice). - SCF :: Runs a static SCF calculation in
./ATAT.SCF. - Energy output :: Writes the final energy to a file named
energy.
The package includes a companion Bash script gorun-all-ready.sh for
submitting multiple jobs in batch. This is useful when you have many
directories prepared with gorun vasp --mark and want to submit them while
respecting a limit on concurrent Slurm jobs.
-
-n NUM,--max-jobs NUM: Maximum number of concurrent Slurm jobs allowed (default:100). -
-d DIR,--directory DIR: Root directory to search forgorun_readymarkers (default: current directory). -
-t SEC,--timeout SEC: Sleep interval (in seconds) between queue checks when waiting for jobs to finish (default:5). -
-q,--quiet: Suppress informational output. Errors are still printed. -
--version: Print version number and exit.
# Submit all ready directories, limit to 4 concurrent jobs
gorun-all-ready.sh -n 4
# Search in a specific project tree, 8 concurrent jobs
gorun-all-ready.sh -d /path/to/project -n 8
# Quiet mode, check queue every 30 seconds
gorun-all-ready.sh -n 10 -t 30 -q
- Recursively searches for
gorun_readymarker files under the search directory. - For each directory containing a marker, checks the current number
of running/pending Slurm jobs (via
squeue -u $USER). - If the count is below the limit, runs
sbatch subin that directory and removes the marker. - If the limit is reached, waits for
--timeoutseconds, then re-checks the queue.
Exit codes: 0 = success, 1 = argument error, 2 = missing command,
3 = no gorun_ready files found, 4 = sbatch failure.
We acknowledge financial support from the National Centre for Research and Development (NCBR) under project WPC3/2022/50/KEYTECH/2024. Computational resources were provided by the Polish high-performance computing infrastructure PLGrid, including access to the LUMI supercomputer—owned by the EuroHPC Joint Undertaking and hosted by CSC in Finland together with the LUMI Consortium—through allocation PLL/2024/07/017633, as well as additional resources at the PLGrid HPC centres ACK Cyfronet AGH and WCSS under allocation PLG/2024/017498.