Molecular Dynamics Preparation
This notebook demonstrates preparing Auto3D structures for MD simulations:
Topology generation - GROMACS, Amber, CHARMM formats
Force field assignment - GAFF, CGenFF, OPLS
Solvation - box setup and ion addition
Minimization - pre-equilibration
Workflow
Auto3D (3D structure) → Topology/Parameters → Solvation → Minimization → MD
[ ]:
import os
import tempfile
import subprocess
from pathlib import Path
import Auto3D
from Auto3D import Auto3DOptions, main
from rdkit import Chem
from rdkit.Chem import AllChem
print(f"Auto3D version: {Auto3D.__version__}")
1. Generate Optimized Structure
[ ]:
# Small drug molecule for MD
molecule = {"ibuprofen": "CC(C)CC1=CC=C(C=C1)C(C)C(=O)O"}
with tempfile.NamedTemporaryFile(mode='w', suffix='.smi', delete=False) as f:
for name, smi in molecule.items():
f.write(f"{smi} {name}\n")
input_file = f.name
# Generate structure
if __name__ == "__main__":
config = Auto3DOptions(
path=input_file,
k=1,
optimizing_engine="AIMNET",
use_gpu=True,
)
sdf_output = main(config)
print(f"Output: {sdf_output}")
2. Convert to PDB Format
[ ]:
def sdf_to_pdb(sdf_path, pdb_path=None):
"""
Convert SDF to PDB using RDKit.
"""
if pdb_path is None:
pdb_path = sdf_path.replace('.sdf', '.pdb')
mol = next(Chem.SDMolSupplier(sdf_path, removeHs=False))
if mol is not None:
Chem.MolToPDBFile(mol, pdb_path)
return pdb_path
return None
if 'sdf_output' in dir():
pdb_output = sdf_to_pdb(sdf_output)
print(f"PDB output: {pdb_output}")
3. GROMACS Topology with ACPYPE
ACPYPE (AnteChamber PYthon Parser interfacE) generates GROMACS topologies.
[ ]:
def generate_gromacs_topology(pdb_path, charge=0, multiplicity=1):
"""
Generate GROMACS topology using ACPYPE.
Requires: acpype installed (`pip install acpype` or `conda install -c conda-forge acpype`)
Args:
pdb_path: Input PDB file
charge: Net molecular charge
multiplicity: Spin multiplicity (1 for singlet)
"""
output_dir = Path(pdb_path).parent / "gromacs"
output_dir.mkdir(exist_ok=True)
cmd = f"acpype -i {pdb_path} -n {charge} -m {multiplicity} -o gmx -b LIG"
print(f"Running: {cmd}")
print("\nThis generates:")
print(" - LIG.acpype/LIG_GMX.gro (coordinates)")
print(" - LIG.acpype/LIG_GMX.top (topology)")
print(" - LIG.acpype/LIG_GMX.itp (include topology)")
print(" - LIG.acpype/posre_LIG.itp (position restraints)")
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return result.stdout
except Exception as e:
return f"Error: {e}. Install ACPYPE: pip install acpype"
print("GROMACS topology generation:")
print("-" * 40)
print(generate_gromacs_topology.__doc__)
4. GROMACS Solvation and Box Setup
[ ]:
def create_gromacs_box_commands(gro_file, top_file, box_size=3.0):
"""
Generate GROMACS commands for solvation.
"""
commands = f"""
# 1. Create box (cubic, {box_size} nm buffer)
gmx editconf -f {gro_file} -o box.gro -c -d {box_size} -bt cubic
# 2. Solvate with water (TIP3P)
gmx solvate -cp box.gro -cs spc216.gro -o solvated.gro -p {top_file}
# 3. Add ions (neutralize system)
gmx grompp -f ions.mdp -c solvated.gro -p {top_file} -o ions.tpr
gmx genion -s ions.tpr -o system.gro -p {top_file} -pname NA -nname CL -neutral
# 4. Energy minimization
gmx grompp -f em.mdp -c system.gro -p {top_file} -o em.tpr
gmx mdrun -v -deffnm em
"""
return commands.strip()
print("GROMACS solvation workflow:")
print(create_gromacs_box_commands("LIG_GMX.gro", "LIG_GMX.top"))
[ ]:
def create_em_mdp():
"""
Create energy minimization MDP file for GROMACS.
"""
mdp = """
; em.mdp - Energy minimization parameters
integrator = steep ; Steepest descent
emtol = 1000.0 ; Stop when max force < 1000 kJ/mol/nm
emstep = 0.01 ; Step size
nsteps = 50000 ; Max steps
; Neighbor searching
cutoff-scheme = Verlet
nstlist = 10
rlist = 1.2
; Electrostatics
coulombtype = PME
rcoulomb = 1.2
; Van der Waals
vdwtype = Cut-off
rvdw = 1.2
; Temperature/pressure (not used in EM)
tcoupl = no
pcoupl = no
"""
return mdp.strip()
print("Energy minimization MDP:")
print(create_em_mdp())
5. Amber Topology with Antechamber
[ ]:
def generate_amber_topology(pdb_path, charge=0):
"""
Generate Amber topology using Antechamber.
Requires: AmberTools installed
"""
base = Path(pdb_path).stem
commands = f"""
# 1. Generate mol2 with AM1-BCC charges
antechamber -i {pdb_path} -fi pdb -o {base}.mol2 -fo mol2 -c bcc -s 2 -nc {charge}
# 2. Check for missing parameters
parmchk2 -i {base}.mol2 -f mol2 -o {base}.frcmod
# 3. Create Amber topology with tleap
tleap -f - <<EOF
source leaprc.gaff2
LIG = loadmol2 {base}.mol2
loadamberparams {base}.frcmod
saveamberparm LIG {base}.prmtop {base}.inpcrd
savepdb LIG {base}_amber.pdb
quit
EOF
"""
return commands.strip()
print("Amber topology generation:")
print("-" * 40)
print(generate_amber_topology("ligand.pdb"))
6. OpenMM Python Interface
OpenMM provides a Python API for MD simulations.
[ ]:
def create_openmm_script(pdb_path, output_prefix="md"):
"""
Create OpenMM simulation script.
Requires: openmm, openmmforcefields
"""
script = f'''
"""OpenMM simulation script for small molecule."""
from openmm.app import *
from openmm import *
from openmm.unit import *
from openmmforcefields.generators import GAFFTemplateGenerator
# Load structure
pdb = PDBFile("{pdb_path}")
# Create force field with GAFF for small molecules
from openff.toolkit.topology import Molecule
molecule = Molecule.from_file("{pdb_path}")
gaff = GAFFTemplateGenerator(molecules=molecule)
forcefield = ForceField("amber14-all.xml", "amber14/tip3pfb.xml")
forcefield.registerTemplateGenerator(gaff.generator)
# Create system
modeller = Modeller(pdb.topology, pdb.positions)
modeller.addSolvent(forcefield, model="tip3p", padding=1.0*nanometer)
system = forcefield.createSystem(
modeller.topology,
nonbondedMethod=PME,
nonbondedCutoff=1.0*nanometer,
constraints=HBonds
)
# Setup simulation
integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.002*picoseconds)
simulation = Simulation(modeller.topology, system, integrator)
simulation.context.setPositions(modeller.positions)
# Minimize
print("Minimizing...")
simulation.minimizeEnergy()
# Equilibrate
print("Equilibrating...")
simulation.context.setVelocitiesToTemperature(300*kelvin)
simulation.step(10000) # 20 ps
# Production
print("Running production...")
simulation.reporters.append(DCDReporter("{output_prefix}.dcd", 1000))
simulation.reporters.append(StateDataReporter("{output_prefix}.log", 1000,
step=True, potentialEnergy=True, temperature=True))
simulation.step(50000) # 100 ps
print("Done!")
'''
return script.strip()
print("OpenMM simulation script:")
print("-" * 40)
print("Requires: pip install openmm openmmforcefields openff-toolkit")
print("\nScript generated for ligand.pdb:")
print(create_openmm_script("ligand.pdb")[:500] + "...")
7. Best Practices
Force Field Selection
Force Field |
Use Case |
Notes |
|---|---|---|
GAFF/GAFF2 |
Drug-like molecules |
Amber compatible |
CGenFF |
Drug-like molecules |
CHARMM compatible |
OPLS-AA |
General organics |
Good for liquids |
OpenFF |
Modern drug molecules |
Machine-learned |
Tips
Protonation: Match pH of your system
Charges: AM1-BCC or RESP for accuracy
Box size: At least 1.0 nm buffer for small molecules
Equilibration: NVT then NPT before production
Summary
This tutorial covered:
Auto3D → PDB conversion
GROMACS topology with ACPYPE
Amber topology with Antechamber
OpenMM Python interface
Solvation and box setup
Key workflow:
SMILES → Auto3D (optimized 3D) → PDB → Topology → Solvation → MD
[ ]:
# Cleanup
if 'input_file' in dir() and os.path.exists(input_file):
os.unlink(input_file)