Skip to main content

A unified command-line toolkit for atomistic / MD structure workflows.

Project description

pymdkit

A single command-line tool that bundles a collection of atomistic / molecular-dynamics structure scripts behind one executable: pymdkit. 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 pymdkit <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 pymdkit command into the active conda environment, together with its dependencies (numpy, scipy, ase, pymatgen, pyxtal, mp_api, gemmi, tqdm).

Verify:

pymdkit --version
pymdkit --help                   # lists every command
pymdkit <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
add-groups Tag atoms with a GPUMD group index by element order
electrostatic-energy Compute CIF electrostatic energy with pymatgen EwaldSummation
ehull Auto-detect VASP job folders and compute E_hull vs Materials Project
gather-contcar Collect CONTCARs from VASP job folders into one folder, renamed <folder>.vasp
msd Diffusivity & conductivity from GPUMD MSD jobs (auto-scans <structure>/<temp>/)
outcar2xyz Collect SCF-converged VASP job folders (any name) into one extxyz file
rmsd Compute RMSD between two structure files, or all pairs in a folder
select-candidate Split a NEP training set into candidate/accurate sets by energy error
stru2xyz Convert structure file(s) of any format to extxyz
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

pymdkit add-groups -i opted.cif --elements Li Y Cl -o model.xyz
pymdkit add-groups -if cifs/ --elements Li Y Cl -of cifs-grouped/   # whole folder
pymdkit add-groups --elements Li Y Cl                              # scan subfolders, tag each model.xyz in place
pymdkit stru2xyz -i opted.vasp -o opted.xyz                        # convert one file
pymdkit stru2xyz -if vasp-opted -of xyz-opted                      # convert a whole folder
pymdkit stru2xyz                                                  # scan subfolders, convert structures in place
pymdkit supercell -i opted.vasp -o sc.vasp -max-abc 20            # cell lengths <= 20 A
pymdkit supercell -if vasp-opted -max-abc 20 -individual          # per-structure ./<name>/<name>.<ext>
pymdkit 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
pymdkit vasp-relax  -i opted.vasp                                  # relax inputs in current dir
pymdkit vasp-relax  -if optimal_occupancy                          # one ./<name>/ job folder per structure
pymdkit vasp-static -if cifs/ -custom-setting my_incar.txt         # static inputs, custom INCAR
pymdkit vasp-static -it traj.xyz                                    # one ./frame_N/ job per trajectory frame
pymdkit msd                                         # scans <structure>/<temp>/ -> per-job msd/ + msd_summary.txt
pymdkit msd --diffuse_ion Li --ion_charge 1         # choose the mobile ion for conductivity
pymdkit ehull --mp-api-key $MP_API_KEY              # scans ./ for VASP jobs -> ehull.txt
pymdkit gather-contcar -of vasp-opted               # CONTCARs -> vasp-opted/<folder>.vasp
pymdkit gather-contcar -of vasp-opted -ehull 0.028  # only structures with E_hull < 0.028 eV/atom
pymdkit outcar2xyz                                  # scans ./ for OUTCAR folders -> scf-converged.xyz
pymdkit outcar2xyz --position-only                  # write positions only, without energy/forces/stress
pymdkit substitute -i Li3YCl6.cif -se Li -sn 3 -we Na -wn 3 -on 100
pymdkit substitute -i Li3YCl6.cif -se Li -sn 3 -we none -on 100
pymdkit substitute -i Li96Ta6La11Cl72.cif -se Li1 Li2 -sn 20 67 -we none -on 100
pymdkit substitute -i Li96Ta6La11Cl72.cif -se Li2 -we none -ref La Ta -d 1.01 1.02
pymdkit substitute -i Li96Ta6La11Cl72.cif -se Li2 -we none -ref La Ta
pymdkit electrostatic-energy -i Li3YCl6.cif
pymdkit electrostatic-energy -if Li3YCl6-all
pymdkit select-candidate                            # RMSE bands: <low all accurate, >high all candidate, else worst 50%
pymdkit select-candidate -r 0.8                     # in the middle band, take worst 80% as candidate.xyz
pymdkit rmsd a.cif b.cif                            # RMSD of two files -> rmsd.txt
pymdkit rmsd vasp-opted/                            # all pairs in a folder -> rmsd.txt
pymdkit symmetrize -i opted.cif --symprec 0.01 --add_oxidation yes -o opted-symm.cif
pymdkit 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 outcar2xyz.

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

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.

ehull auto-detects every sub-folder of the current path that contains a vasprun.xml, 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 `pymdkit` 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)
        |-- add_groups.py
        |-- compute_ehull.py
        |-- compute_rmsd.py
        |-- electrostatic_energy.py
        |-- outcar2xyz.py
        |-- stru2xyz.py
        |-- substitute.py
        |-- supercell.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 pymdkit --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 pymdkit --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

Project details


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.1.5.tar.gz (54.5 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.1.5-py3-none-any.whl (61.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for pymdkit-1.1.5.tar.gz
Algorithm Hash digest
SHA256 b8d0b5fbe4b47e2031f73682149b204576a7774331b828791ee0a0c3b797f92e
MD5 c21f2d154816a6a949000556f4293f5e
BLAKE2b-256 dba36fbd1cfbf21dca3c97a55f8cc18ff889efdb5cd8342c7e0800eff1f881f6

See more details on using hashes here.

File details

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

File metadata

  • Download URL: pymdkit-1.1.5-py3-none-any.whl
  • Upload date:
  • Size: 61.1 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.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 4135bc39b500f5bf2c380fd0902507d89ebb0257dbe7f5f1abb8d5716c8a2576
MD5 70fb66801fc7baebe429093b6e2db8a3
BLAKE2b-256 6cd2972a63eb37d89f8615094de05e90fac2db4f9747079240d0c9cdb7c11ba9

See more details on using hashes here.

Supported by

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