Skip to main content

pymdkit

A single command-line tool that bundles a collection of atomistic / molecular-dynamics structure scripts behind one executable: pmk. Instead of copying individual scripts into each working folder and running python some_script.py, you install pymdkit once and call any tool from anywhere as pmk <command> [options].

Every command exposes named -flags (no positional guessing), and each underlying script is still runnable on its own.

Install

Create a clean conda environment, activate it, then install pymdkit with pip:

conda create -n pymdkit python=3.10
conda activate pymdkit
pip install pymdkit

This installs the pmk command into the active conda environment, together with its direct dependencies, including ASE, pymatgen, py4vasp-core, dpdata, matplotlib, and UMAP. Some of these packages may install their own transitive dependencies.

Verify:

pmk -version
pmk -help                   # lists every command
pmk <command> -help         # shows that command's flags

Commands

Commands that transform structures accept either a single file (-i/-o) or a whole folder (-if/-of); commands that analyse VASP runs scan the current directory for job sub-folders automatically.

Command What it does
gpumd-group Tag atoms with a GPUMD group index by element order
ewald Compute CIF electrostatic energy with pymatgen EwaldSummation
ehull Auto-detect VASP job folders and compute E_hull vs Materials Project
vasp-fe List VASP job final energies from lowest to highest
gather-contcar Collect CONTCARs from VASP job folders into one folder, renamed <folder>.vasp
gpumd-thermo Export and plot GPUMD thermo data and detect sustained equilibrium changes
pca Reduce descriptor data to two dimensions; optional FPS sampling
trj-extract Extract a GPUMD XYZ trajectory by time range
umap Reduce descriptor data to two dimensions with UMAP; optional FPS sampling
msd Diffusivity & conductivity from GPUMD MSD jobs (auto-scans <structure>/<temp>/)
nep-rmse Compute NEP energy/force/stress RMSE with terminal plots and optional candidate selection
perturb Generate perturbed structures with dpdata
vasp2xyz Collect SCF-converged VASP job folders (any name) into one extxyz file
submit-vasp Submit/resubmit VASP job folders while limiting active queue jobs
rmsd Compute RMSD between two structure files, or all pairs in a folder
chemsys-entry Download stable Materials Project structures for a chemical system
convert Convert structures, trajectories, or folders between ASE/pymatgen formats
substitute Randomly substitute or remove selected atoms/sites from a structure
supercell Build a supercell with cell lengths capped at a maximum (Angstrom); optional per-temperature GPUMD setup
symmetrize Import space-group symmetry into a structure file (or folder) -> CIF
vasp-relax Write VASP relaxation inputs for a structure (or folder); INCAR tags overridable
vasp-static Write VASP static / single-point inputs for a structure (or folder)

Examples

pmk gpumd-group -i opted.cif -elements Li Y Cl -o model.xyz
pmk gpumd-group -if cifs/ -elements Li Y Cl -of cifs-grouped/   # whole folder
pmk gpumd-group -elements Li Y Cl                              # scan subfolders, tag each model.xyz in place
pmk convert -i opted.vasp -o opted.xyz                          # convert one structure
pmk convert -if vasp-opted -of cif-opted -oe cif                # folder conversion target format
pmk convert -it train.xyz -ot train.extxyz                      # convert a complete trajectory
pmk supercell -i opted.vasp -o sc.vasp -max-abc 20            # cell lengths <= 20 A
pmk supercell -if vasp-opted -max-abc 20 -individual          # per-structure ./<name>/<name>.<ext>
pmk supercell -if extxyz-opted -max-abc 24 -individual -temp 500 600 -md-if input-files -add-groups Li Y Cl
                                                                  # GPUMD: ./<name>/model.xyz (grouped) + ./<name>/<T>/ jobs
pmk vasp-relax  -i opted.vasp                                  # relax inputs in current dir
pmk vasp-relax  -if optimal_occupancy                          # one ./<name>/ job folder per structure
pmk vasp-static -if cifs/ -custom-setting my_incar.txt         # static inputs, custom INCAR
pmk vasp-static -it traj.xyz                                    # one ./frame_N/ job per trajectory frame
pmk msd                                         # scans <structure>/<temp>/ -> per-job msd/ + msd_summary.txt
pmk msd -diffuse_ion Li -ion_charge 1         # choose the mobile ion for conductivity
pmk chemsys-entry -s Li La Ta Cl                 # MP stable entries -> Li-La-Ta-Cl-stable-entries/
pmk ehull -mp-api-key $MP_API_KEY              # scans ./ for VASP jobs -> ehull.txt
pmk ehull -local Li-La-Ta-Cl-stable-entries-opted
pmk vasp-fe                                # scans ./ for VASP jobs -> final-energy.txt with convergence status
pmk gather-contcar -of vasp-opted               # CONTCARs -> vasp-opted/<folder>.vasp
pmk gather-contcar -of vasp-opted -ehull 0.028  # only structures with E_hull < 0.028 eV/atom
pmk vasp2xyz                                    # scans ./ for VASP output folders -> scf-converged.xyz
pmk vasp2xyz -position-only                    # write positions only, without energy/forces/stress
pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30
nohup pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30 > submit-vasp.log 2>&1 &
pmk substitute -i Li3YCl6.cif -se Li -sn 3 -we Na -wn 3 -on 100
pmk substitute -i Li3YCl6.cif -se Li -sn 3 -we none -on 100
pmk substitute -i Li96Ta6La11Cl72.cif -se Li1 Li2 -sn 20 67 -we none -on 100
pmk substitute -i Li96Ta6La11Cl72.cif -se Li2 -we none -ref La Ta -d 1.01 1.02
pmk substitute -i Li96Ta6La11Cl72.cif -se Li2 -we none -ref La Ta
pmk ewald -i Li3YCl6.cif
pmk ewald -if Li3YCl6-all
pmk nep-rmse                                    # writes energy/force/stress train txt files, rmse_value.txt, and terminal plots
pmk nep-rmse -select -xyz train.xyz   # interactive candidate selection; writes candidate.xyz and accurate.xyz
pmk perturb -i example.xyz -atom 0.2 -lattice 0.03 -n 100 -o example-perturb-atom-0.2-lattice-0.03.xyz
pmk pca -i descriptor.out -o pca-descriptor.txt
pmk pca -i descriptor.out -o pca-descriptor.txt -fps 0.01 -it train.xyz
pmk umap -i descriptor.out -o umap-descriptor.txt -fps 0.01 -it train.xyz
pmk gpumd-thermo                              # current job, or recursively scan job folders
pmk gpumd-thermo -t thermo.out -in run.in
pmk trj-extract -it traj.xyz -in run.in -b 100 -e 200 -o traj-100ps-200ps.xyz

pmk rmsd a.cif b.cif                            # RMSD of two files -> rmsd.txt
pmk rmsd vasp-opted/                            # all pairs in a folder -> rmsd.txt
pmk symmetrize -i opted.cif -symprec 0.01 -add_oxidation yes -o opted-symm.cif
pmk symmetrize -if my_cifs/ -symprec 0.01 -add_oxidation no -of my_cifs-symm

VASP input commands (vasp-relax, vasp-static) always produce individual jobs (one structure per folder): -i writes into the current dir (or -o), -if creates one ./<name>/ folder per structure, and -it creates one ./frame_N/ folder per trajectory frame - all directly in the current path.

They start from sensible default INCAR settings; override them by passing a settings file with -custom-setting FILE. The file may be a Python-dict block or KEY = VALUE lines (a None/blank value clears a tag):

custom_settings = {
    "ENCUT": "600.0",
    "ISIF": "3",
    "MAGMOM": None
}

vasp-static -it traj.xyz (also available on vasp-relax) reads a multi-structure trajectory and writes one job sub-folder per frame (frame_1/, frame_2/, ..., prefix configurable via -frame-prefix). Each folder also keeps a frame_N.xyz, so Config_type survives for a later vasp2xyz.

nep-rmse -select, PCA FPS, and UMAP FPS copy selected extended-XYZ frame blocks directly from the input trajectory. No parser rewrites energy, stress, forces, positions, precision, or extra metadata.

For folder conversion, convert -if INPUT -of OUTPUT writes .xyz by default. Set another target extension with -oe, for example -oe cif or -oe vasp. Single-file and trajectory modes infer the target format from -o and -ot.

gpumd-thermo writes temperature.txt, potential-energy.txt, pressure.txt, lattice-parameters.txt, volume.txt, lattice-angles.txt, and a headless thermo.png in every detected GPUMD job folder. Its warning is a numerical reminder based on sustained drift or a level shift in the last run segment (or the last 80% when run.in has no run record); inspect the plot before deciding whether a trajectory is equilibrated.

Each command's full flag list is in pmk <command> -help.

For long VASP batch submission, run submit-vasp with nohup and & if you want it to keep sleeping, checking the queue, and submitting new jobs after you exit the terminal:

nohup pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30 > submit-vasp.log 2>&1 &

The command itself controls the loop: it submits until the active queue reaches -max-job-num, sleeps when the queue is full, checks again, and continues until all needed jobs are submitted. nohup ... & is what makes that loop continue in the background after logout.

substitute -ref removes selected sites near reference sites and writes one <input-stem>_substitute.cif in the current path. If -d is omitted, each cutoff is 0.7 * (selected covalent radius + reference covalent radius) using the covalent radii from Cordero et al., Dalton Trans., 2008, 2832-2838.

VASP-output readers (vasp2xyz, ehull, vasp-fe, and other future VASP-output commands) use the global priority vaspout.h5 > vasprun.xml > OUTCAR.

ehull auto-detects every sub-folder of the current path that contains a supported VASP output, groups them by chemical system (elements ordered by electronegativity, e.g. Li-Y-Cl), and builds/reuses one mp_cache_<system>.json per system - so a pure Li-Y-Cl batch yields a single mp_cache_Li-Y-Cl.json, while a mixed Li-Y-Cl + La-O batch yields both mp_cache_Li-Y-Cl.json and mp_cache_La-O.json. (Formation energy is reported alongside E_hull in ehull.txt.)

Layout

pymdkit/
|-- pyproject.toml              # package metadata + the `pmk` entry point
|-- README.md
`-- src/pymdkit/
    |-- pymdkit_main.py         # dispatcher: discovers and runs commands
    `-- commands/               # one module per command
        |-- _fileio.py          # shared -i/-o/-if/-of helper (not a command)
        |-- _vaspset.py         # shared VASP input-set helper (not a command)
        |-- gpumd_group.py
        |-- compute_ehull.py
        |-- compute_rmsd.py
        |-- ewald.py
        |-- vasp_fe.py
        |-- perturb.py
        |-- nep_rmse.py
        |-- chemsys_entry.py
        |-- submit_vasp.py
        |-- convert.py
        |-- substitute.py
        |-- supercell.py
        |-- vasp2xyz.py
        |-- vasp_relax.py
        |-- vasp_static.py
        |-- ...
        `-- symmetrize.py

Modules whose name starts with _ are shared helpers and are skipped by the dispatcher, so they never appear as commands.

Adding a new tool later

Drop a module in src/pymdkit/commands/ that defines four things:

COMMAND = "my-tool"                 # the subcommand name you'll type
HELP = "One-line description."

def add_arguments(parser):          # register flags
    parser.add_argument("-input", required=True)

def run(args):                      # do the work; return an exit code (0 = ok)
    ...
    return 0

if __name__ == "__main__":          # keeps the script runnable on its own
    import argparse
    _p = argparse.ArgumentParser(description=__doc__)
    add_arguments(_p)
    raise SystemExit(run(_p.parse_args()))

It will appear in pmk -help automatically - no central registration needed. Put heavy imports (pymatgen, ase, ...) inside run() where practical; the dispatcher reads each command's name and help without importing it, so pmk -help stays fast and a missing optional dependency only affects the one command that needs it.

Running a script standalone

Every command module still works directly, which is handy for debugging:

python src/pymdkit/commands/supercell.py -i in.cif -max-abc 20 -o sc.vasp

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymdkit-1.4.0.tar.gz (72.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymdkit-1.4.0-py3-none-any.whl (82.0 kB view details)

Uploaded Python 3

File details

Details for the file pymdkit-1.4.0.tar.gz.

File metadata

  • Download URL: pymdkit-1.4.0.tar.gz
  • Upload date:
  • Size: 72.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for pymdkit-1.4.0.tar.gz
Algorithm Hash digest
SHA256 5df53c5661d2c3d346d20d7a19da9991c1d84696806191c1d44ce38e0ae74322
MD5 48026ae0a60b34a8987be2d35466674c
BLAKE2b-256 76fd65b6b4fbf60ca31cfa0f0ef1faebb52b2517689580bb63ec0f3223432556

See more details on using hashes here.

File details

Details for the file pymdkit-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: pymdkit-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 82.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for pymdkit-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b735c49e869250d85f72c00233952c0bad90d064bcbb8cb57e63bf5c27de03c7
MD5 ca184d6a8a55819d41333969536e8b83
BLAKE2b-256 96f780cc0d74d703fa9d392623e95ae3edb7de0b186f7fb364ffd1413013cafe

See more details on using hashes here.

Release history Release notifications | RSS feed

1.7.1

2 files

1.7.0

2 files

1.6.12

2 files

1.6.11

2 files

1.6.10

2 files

1.6.9

2 files

1.6.8

2 files

1.6.7

2 files

1.6.6

2 files

1.6.5

2 files

1.6.4

2 files

1.6.3

2 files

1.6.2

2 files

1.6.1

2 files

1.6.0

2 files

1.5.9

2 files

1.5.8

2 files

1.5.7

2 files

1.5.6

2 files

1.5.5

2 files

1.5.4

2 files

1.5.3

2 files

1.5.2

2 files

1.5.1

2 files

1.5.0

2 files

1.4.13

2 files

1.4.12

2 files

1.4.11

2 files

1.4.10

2 files

1.4.9

2 files

1.4.8

2 files

1.4.7

2 files

1.4.6

2 files

1.4.5

2 files

1.4.4

2 files

1.4.3

2 files

1.4.2

2 files

1.4.1

2 files

This release

1.4.0 This release

2 files

1.3.0

2 files

1.2.12

2 files

1.2.11

2 files

1.2.10

2 files

1.2.9

2 files

1.2.8

2 files

1.2.7

2 files

1.2.6

2 files

1.2.5

2 files

1.2.4

2 files

1.2.3

2 files

1.2.2

2 files

1.2.1

2 files

1.2.0

2 files

1.1.10

2 files

1.1.9

2 files

1.1.8

2 files

1.1.7

2 files

1.1.6

2 files

1.1.5

2 files

1.1.4

2 files

1.1.3

2 files

1.1.2

2 files

1.1.1

2 files

1.1.0

2 files

1.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page