Skip to main content
Docs

Search guides and API endpoints, for example “Idempotency-Key” or “submit job”.

    Tools · Computational Biology

    OpenMM MD

    Prepare a protein system and run a short Langevin equilibration with OpenMM, with optional RMSF, contact, buried-surface, and distance analytics.

    Updated October 1, 2026

    On this page

    Prices, workflows, and method papersOpen in the app

    OpenMM MD takes a protein structure from PDB to an equilibrated simulation in one job: it cleans the structure, assigns protonation states, solvates it, minimizes, and runs Langevin dynamics with OpenMM, then optionally analyzes the trajectory. It runs on a GPU by default (T4); CPU is for short test runs.

    How it works

    1. Prepare. PDBFixer repairs missing atoms and residues (and removes heterogens if you ask), PROPKA assigns protonation states at preparation.ph (7.4 by default), and OpenMM's Modeller adds a water box with padding_nm (1.0) of padding and ions at ionic_strength (0.15 M).
    2. Simulate. Energy minimization, then simulation.num_steps of Langevin dynamics (up to 500,000) at temperature_k (300 K). Hydrogen mass repartitioning (hmr, on by default) allows a 4 fs time step instead of 2 fs, so the default 50,000 steps cover about 0.2 ns.
    3. Analyze (optional). Each entry in analytics runs on the trajectory with MDAnalysis and writes a CSV.

    Ensembles

    simulation.ensembleBehavior
    nvt (default)Constant volume
    nptAdds a Monte Carlo barostat at pressure_bar (1.0 by default). Needs explicit water.

    Force fields and solvent

    preparation.force_fieldpreparation.solvent_model
    amber14 (default)tip3pfb (default), tip3p, tip4pew, spce, or implicit_obc2
    amber99sbildntip3p or implicit_obc2

    implicit_obc2 skips the water box and uses OBC2 generalized-Born implicit solvent, with NVT only. Only force fields we can license for this use are offered; CHARMM36 for proteins isn't available yet.

    Analytics

    metricFieldsMeasures
    rmsfselectionPer-atom fluctuation over the trajectory
    contact_mapselection_a, selection_b, cutoff (4.5 Å)How often each pair of residues is in contact
    buried_surface_areaselection_a, selection_bSurface area buried at the interface
    com_distanceselection_a, selection_bDistance between the two centers of mass

    Selections use MDAnalysis syntax, for example protein and name CA or segid A.

    System modes

    • protein_protein (default): a protein or complex from structure.pdb_text, as above.
    • membrane_small_molecule: a small molecule from ligand.smiles, parameterized with OpenFF Sage and placed in the water above a small prebuilt lipid bilayer patch (box_id: lnp_hspc_chol_v1, rebuilt as a POPC bilayer for CHARMM36) with 150 mM NaCl. It doesn't need a PDB, but in a workflow the step still needs its structure input connected.

    Outputs

    FileContents
    simulation/minimized.pdbThe minimized starting system
    simulation/trajectory.dcdThe trajectory
    simulation/equil_log.csvStep, potential energy, temperature, and density (plus volume for NPT)
    analytics/<metric>_<n>.csvOne file per analytics entry
    pipeline_summary.jsonThe settings used, files, and analytics results

    Intermediate structures (cleaned, protonated, and solvated) are in intermediate/. Analyze the trajectory further with the MD Trajectory Analyzer, or rescore binding with MM-GBSA Rescoring.

    Not covered

    • Constant-energy (NVE) runs.
    • CHARMM36, COMPASS, and DREIDING for proteins, and implicit solvents other than OBC2.

    Run it from the API

    Submit with Submit a job and the job_type below. Price it first with Estimate job reservation cost: submitting reserves that amount from your wallet, and the charge settles at the actual runtime.

    OpenMM MD openmm-md

    Job type
    openmm-md
    Hardware
    cput4 (default)l4a10l40sa100-40gba100-80gbh100h200b200
    Typical runtime
    2 h on Nvidia T4

    Payload

    Payload fields
    FieldTypeDescription
    system_modestring

    Default: "protein_protein"One of: "protein_protein", "protein_ligand", "small_molecule", "membrane_small_molecule"

    structurerequiredobject
    structure.pdb_textrequiredstring

    Limits: min length 1

    preparationobject
    preparation.phnumber

    Default: 7.4Limits: ≥ 0, ≤ 14

    preparation.remove_heterogensboolean

    Default: false

    preparation.padding_nmnumber

    Default: 1Limits: > 0

    preparation.ionic_strengthnumber

    Default: 0.15Limits: ≥ 0

    preparation.force_fieldstring

    Default: "amber14"One of: "amber14", "amber99sbildn"

    preparation.solvent_modelstring

    Default: "tip3pfb"One of: "tip3pfb", "tip3p", "tip4pew", "spce", "implicit_obc2"

    preparation.box_idstring

    Default: "lnp_hspc_chol_v1"

    simulationobject
    simulation.num_stepsinteger

    Default: 50000Limits: ≥ 1, ≤ 500000

    simulation.temperature_knumber

    Default: 300Limits: > 0

    simulation.hmrboolean

    Default: true

    simulation.ensemblestring

    Default: "nvt"One of: "nvt", "npt"

    simulation.pressure_barnumber

    Default: 1Limits: > 0

    analytics[]object[]

    Default: []

    analytics.metricrequiredstring

    One of: "rmsf", "contact_map", "buried_surface_area", "com_distance"

    analytics.selectionstring

    Limits: min length 1

    analytics.selection_astring

    Limits: min length 1

    analytics.selection_bstring

    Limits: min length 1

    analytics.cutoffnumber

    Limits: > 0

    ligandobject
    ligand.smilesrequiredstring

    Limits: min length 1

    Example

    from cognichem_client import CogniChem
    
    client = CogniChem.from_env()  # reads COGNICHEM_API_KEY
    payload = {
        "system_mode": "protein_protein",
        "structure": {
            "pdb_text": "REMARK  Minimal alanine tripeptide for unit testing.\nREMARK … (2,166 characters)",
        },
        "simulation": {"num_steps": 1},
        "analytics": [],
    }
    
    estimate = client.jobs.estimate(job_type="openmm-md", payload=payload, resource="t4")
    print(f"Reserves ${estimate.cost:.2f}")
    
    job = client.jobs.submit(
        job_name="my-openmm-md-run",
        job_type="openmm-md",
        payload=payload,
        resource="t4",
    )
    status = client.jobs.wait(job.process_id)
    if status.status == "completed":
        client.jobs.result(job.process_id, save_path=".")

    Sample data from the job catalog; long values are shortened here. Each job_name must be unique among your jobs.

    Workflow inputs

    • Molecules · optionalSMILES
    • Protein structurePDB

    Workflow outputs

    • ArchiveZIP
    • Protein structurePDB