molecular-dynamics

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Molecular Dynamics

分子动力学模拟

Overview

概述

Molecular dynamics (MD) simulation computationally models the time evolution of molecular systems by integrating Newton's equations of motion. This skill covers two complementary tools:
  • OpenMM (https://openmm.org/): High-performance MD simulation engine with GPU support, Python API, and flexible force field support
  • MDAnalysis (https://mdanalysis.org/): Python library for reading, writing, and analyzing MD trajectories from all major simulation packages
Installation:
bash
conda install -c conda-forge openmm mdanalysis nglview
分子动力学(MD)模拟通过求解牛顿运动方程,对分子系统的时间演化进行计算建模。本技能涵盖两个互补工具:
安装:
bash
conda install -c conda-forge openmm mdanalysis nglview

or

or

pip install openmm mdanalysis
undefined
pip install openmm mdanalysis
undefined

When to Use This Skill

何时使用本技能

Use molecular dynamics when:
  • Protein stability analysis: How does a mutation affect protein dynamics?
  • Drug binding simulations: Characterize binding mode and residence time of a ligand
  • Conformational sampling: Explore protein flexibility and conformational changes
  • Protein-protein interaction: Model interface dynamics and binding energetics
  • RMSD/RMSF analysis: Quantify structural fluctuations from a reference structure
  • Free energy estimation: Compute binding free energy or conformational free energy
  • Membrane simulations: Model proteins in lipid bilayers
  • Intrinsically disordered proteins: Study IDR conformational ensembles
在以下场景中使用分子动力学模拟:
  • 蛋白质稳定性分析:突变如何影响蛋白质动力学?
  • 药物结合模拟:表征配体的结合模式和停留时间
  • 构象采样:探索蛋白质的灵活性和构象变化
  • 蛋白质-蛋白质相互作用:模拟界面动力学和结合能
  • RMSD/RMSF分析:量化相对于参考结构的结构波动
  • 自由能估算:计算结合自由能或构象自由能
  • 膜模拟:模拟脂质双分子层中的蛋白质
  • 内在无序蛋白质:研究IDR构象集合

Core Workflow: OpenMM Simulation

核心工作流:OpenMM模拟

1. System Preparation

1. 系统准备

python
from openmm.app import *
from openmm import *
from openmm.unit import *
import sys

def prepare_system_from_pdb(pdb_file, forcefield_name="amber14-all.xml",
                              water_model="amber14/tip3pfb.xml"):
    """
    Prepare an OpenMM system from a PDB file.

    Args:
        pdb_file: Path to cleaned PDB file (use PDBFixer for raw PDB files)
        forcefield_name: Force field XML file
        water_model: Water model XML file

    Returns:
        pdb, forcefield, system, topology
    """
    # Load PDB
    pdb = PDBFile(pdb_file)

    # Load force field
    forcefield = ForceField(forcefield_name, water_model)

    # Add hydrogens and solvate
    modeller = Modeller(pdb.topology, pdb.positions)
    modeller.addHydrogens(forcefield)

    # Add solvent box (10 Å padding, 150 mM NaCl)
    modeller.addSolvent(
        forcefield,
        model='tip3p',
        padding=10*angstroms,
        ionicStrength=0.15*molar
    )

    print(f"System: {modeller.topology.getNumAtoms()} atoms, "
          f"{modeller.topology.getNumResidues()} residues")

    # Create system
    system = forcefield.createSystem(
        modeller.topology,
        nonbondedMethod=PME,         # Particle Mesh Ewald for long-range electrostatics
        nonbondedCutoff=1.0*nanometer,
        constraints=HBonds,           # Constrain hydrogen bonds (allows 2 fs timestep)
        rigidWater=True,
        ewaldErrorTolerance=0.0005
    )

    return modeller, system
python
from openmm.app import *
from openmm import *
from openmm.unit import *
import sys

def prepare_system_from_pdb(pdb_file, forcefield_name="amber14-all.xml",
                              water_model="amber14/tip3pfb.xml"):
    """
    从PDB文件准备OpenMM系统。

    参数:
        pdb_file:清洁后的PDB文件路径(原始PDB文件请使用PDBFixer处理)
        forcefield_name:力场XML文件
        water_model:水模型XML文件

    返回:
        pdb, forcefield, system, topology
    """
    # 加载PDB
    pdb = PDBFile(pdb_file)

    # 加载力场
    forcefield = ForceField(forcefield_name, water_model)

    # 添加氢原子并溶剂化
    modeller = Modeller(pdb.topology, pdb.positions)
    modeller.addHydrogens(forcefield)

    # 添加溶剂盒(10 Å 填充,150 mM NaCl)
    modeller.addSolvent(
        forcefield,
        model='tip3p',
        padding=10*angstroms,
        ionicStrength=0.15*molar
    )

    print(f"系统:{modeller.topology.getNumAtoms()} 个原子, "
          f"{modeller.topology.getNumResidues()} 个残基")

    # 创建系统
    system = forcefield.createSystem(
        modeller.topology,
        nonbondedMethod=PME,         # 用于长程静电相互作用的粒子网格埃瓦尔德法
        nonbondedCutoff=1.0*nanometer,
        constraints=HBonds,           # 约束氢键(允许2 fs时间步长)
        rigidWater=True,
        ewaldErrorTolerance=0.0005
    )

    return modeller, system

2. Energy Minimization

2. 能量最小化

python
from openmm.app import *
from openmm import *
from openmm.unit import *

def minimize_energy(modeller, system, output_pdb="minimized.pdb",
                     max_iterations=1000, tolerance=10.0):
    """
    Energy minimize the system to remove steric clashes.

    Args:
        modeller: Modeller object with topology and positions
        system: OpenMM System
        output_pdb: Path to save minimized structure
        max_iterations: Maximum minimization steps
        tolerance: Convergence criterion in kJ/mol/nm

    Returns:
        simulation object with minimized positions
    """
    # Set up integrator (doesn't matter for minimization)
    integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)

    # Create simulation
    # Use GPU if available (CUDA or OpenCL), fall back to CPU
    try:
        platform = Platform.getPlatformByName('CUDA')
        properties = {'DeviceIndex': '0', 'Precision': 'mixed'}
    except Exception:
        try:
            platform = Platform.getPlatformByName('OpenCL')
            properties = {}
        except Exception:
            platform = Platform.getPlatformByName('CPU')
            properties = {}

    simulation = Simulation(
        modeller.topology, system, integrator,
        platform, properties
    )
    simulation.context.setPositions(modeller.positions)

    # Check initial energy
    state = simulation.context.getState(getEnergy=True)
    print(f"Initial energy: {state.getPotentialEnergy()}")

    # Minimize
    simulation.minimizeEnergy(
        tolerance=tolerance*kilojoules_per_mole/nanometer,
        maxIterations=max_iterations
    )

    state = simulation.context.getState(getEnergy=True, getPositions=True)
    print(f"Minimized energy: {state.getPotentialEnergy()}")

    # Save minimized structure
    with open(output_pdb, 'w') as f:
        PDBFile.writeFile(simulation.topology, state.getPositions(), f)

    return simulation
python
from openmm.app import *
from openmm import *
from openmm.unit import *

def minimize_energy(modeller, system, output_pdb="minimized.pdb",
                     max_iterations=1000, tolerance=10.0):
    """
    对系统进行能量最小化以消除空间位阻冲突。

    参数:
        modeller:包含拓扑结构和原子位置的Modeller对象
        system:OpenMM System
        output_pdb:保存最小化后结构的路径
        max_iterations:最大最小化步数
        tolerance:收敛标准,单位为kJ/mol/nm

    返回:
        包含最小化后原子位置的simulation对象
    """
    # 设置积分器(对最小化无影响)
    integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.004*picoseconds)

    # 创建模拟
    # 优先使用GPU(CUDA或OpenCL),否则回退到CPU
    try:
        platform = Platform.getPlatformByName('CUDA')
        properties = {'DeviceIndex': '0', 'Precision': 'mixed'}
    except Exception:
        try:
            platform = Platform.getPlatformByName('OpenCL')
            properties = {}
        except Exception:
            platform = Platform.getPlatformByName('CPU')
            properties = {}

    simulation = Simulation(
        modeller.topology, system, integrator,
        platform, properties
    )
    simulation.context.setPositions(modeller.positions)

    # 检查初始能量
    state = simulation.context.getState(getEnergy=True)
    print(f"初始能量:{state.getPotentialEnergy()}")

    # 执行最小化
    simulation.minimizeEnergy(
        tolerance=tolerance*kilojoules_per_mole/nanometer,
        maxIterations=max_iterations
    )

    state = simulation.context.getState(getEnergy=True, getPositions=True)
    print(f"最小化后能量:{state.getPotentialEnergy()}")

    # 保存最小化后的结构
    with open(output_pdb, 'w') as f:
        PDBFile.writeFile(simulation.topology, state.getPositions(), f)

    return simulation

3. NVT Equilibration

3. NVT平衡模拟

python
from openmm.app import *
from openmm import *
from openmm.unit import *

def run_nvt_equilibration(simulation, n_steps=50000, temperature=300,
                            report_interval=1000, output_prefix="nvt"):
    """
    NVT equilibration: constant N, V, T.
    Equilibrate velocities to target temperature.

    Args:
        simulation: OpenMM Simulation (after minimization)
        n_steps: Number of MD steps (50000 × 2fs = 100 ps)
        temperature: Temperature in Kelvin
        report_interval: Steps between data reports
        output_prefix: File prefix for trajectory and log
    """
    # Add position restraints for backbone during NVT
    # (Optional: restraint heavy atoms)

    # Set temperature
    simulation.context.setVelocitiesToTemperature(temperature*kelvin)

    # Add reporters
    simulation.reporters = []

    # Log file
    simulation.reporters.append(
        StateDataReporter(
            f"{output_prefix}_log.txt",
            report_interval,
            step=True,
            potentialEnergy=True,
            kineticEnergy=True,
            temperature=True,
            volume=True,
            speed=True
        )
    )

    # DCD trajectory (compact binary format)
    simulation.reporters.append(
        DCDReporter(f"{output_prefix}_traj.dcd", report_interval)
    )

    print(f"Running NVT equilibration: {n_steps} steps ({n_steps*2/1000:.1f} ps)")
    simulation.step(n_steps)
    print("NVT equilibration complete")

    return simulation
python
from openmm.app import *
from openmm import *
from openmm.unit import *

def run_nvt_equilibration(simulation, n_steps=50000, temperature=300,
                            report_interval=1000, output_prefix="nvt"):
    """
    NVT平衡:恒定粒子数(N)、体积(V)、温度(T)。
    将速度平衡至目标温度。

    参数:
        simulation:完成最小化后的OpenMM Simulation
        n_steps:MD步数(50000 × 2fs = 100 ps)
        temperature:温度,单位为开尔文
        report_interval:数据报告的步长间隔
        output_prefix:轨迹和日志文件的前缀
    """
    # NVT阶段为 backbone 添加位置约束
    # (可选:约束重原子)

    # 设置温度
    simulation.context.setVelocitiesToTemperature(temperature*kelvin)

    # 添加报告器
    simulation.reporters = []

    # 日志文件
    simulation.reporters.append(
        StateDataReporter(
            f"{output_prefix}_log.txt",
            report_interval,
            step=True,
            potentialEnergy=True,
            kineticEnergy=True,
            temperature=True,
            volume=True,
            speed=True
        )
    )

    # DCD轨迹(紧凑二进制格式)
    simulation.reporters.append(
        DCDReporter(f"{output_prefix}_traj.dcd", report_interval)
    )

    print(f"运行NVT平衡:{n_steps} 步 ({n_steps*2/1000:.1f} ps)")
    simulation.step(n_steps)
    print("NVT平衡完成")

    return simulation

4. NPT Equilibration and Production

4. NPT平衡与生产模拟

python
def run_npt_production(simulation, n_steps=500000, temperature=300, pressure=1.0,
                        report_interval=5000, output_prefix="npt"):
    """
    NPT production run: constant N, P, T.

    Args:
        n_steps: Production steps (500000 × 2fs = 1 ns)
        temperature: Temperature in Kelvin
        pressure: Pressure in bar
        report_interval: Steps between reports
    """
    # Add Monte Carlo barostat for pressure control
    system = simulation.context.getSystem()
    system.addForce(MonteCarloBarostat(pressure*bar, temperature*kelvin, 25))
    simulation.context.reinitialize(preserveState=True)

    # Update reporters
    simulation.reporters = []
    simulation.reporters.append(
        StateDataReporter(
            f"{output_prefix}_log.txt",
            report_interval,
            step=True,
            potentialEnergy=True,
            temperature=True,
            density=True,
            speed=True
        )
    )
    simulation.reporters.append(
        DCDReporter(f"{output_prefix}_traj.dcd", report_interval)
    )

    # Save checkpoints
    simulation.reporters.append(
        CheckpointReporter(f"{output_prefix}_checkpoint.chk", 50000)
    )

    print(f"Running NPT production: {n_steps} steps ({n_steps*2/1000000:.2f} ns)")
    simulation.step(n_steps)
    print("Production MD complete")
    return simulation
python
def run_npt_production(simulation, n_steps=500000, temperature=300, pressure=1.0,
                        report_interval=5000, output_prefix="npt"):
    """
    NPT生产模拟:恒定粒子数(N)、压力(P)、温度(T)。

    参数:
        n_steps:生产步数(500000 × 2fs = 1 ns)
        temperature:温度,单位为开尔文
        pressure:压力,单位为bar
        report_interval:报告的步长间隔
    """
    # 添加蒙特卡洛 barostat 用于压力控制
    system = simulation.context.getSystem()
    system.addForce(MonteCarloBarostat(pressure*bar, temperature*kelvin, 25))
    simulation.context.reinitialize(preserveState=True)

    # 更新报告器
    simulation.reporters = []
    simulation.reporters.append(
        StateDataReporter(
            f"{output_prefix}_log.txt",
            report_interval,
            step=True,
            potentialEnergy=True,
            temperature=True,
            density=True,
            speed=True
        )
    )
    simulation.reporters.append(
        DCDReporter(f"{output_prefix}_traj.dcd", report_interval)
    )

    # 保存检查点
    simulation.reporters.append(
        CheckpointReporter(f"{output_prefix}_checkpoint.chk", 50000)
    )

    print(f"运行NPT生产模拟:{n_steps} 步 ({n_steps*2/1000000:.2f} ns)")
    simulation.step(n_steps)
    print("生产级MD模拟完成")
    return simulation

Trajectory Analysis with MDAnalysis

使用MDAnalysis进行轨迹分析

1. Load Trajectory

1. 加载轨迹

python
import MDAnalysis as mda
from MDAnalysis.analysis import rms, align, contacts
import numpy as np
import matplotlib.pyplot as plt

def load_trajectory(topology_file, trajectory_file):
    """
    Load an MD trajectory with MDAnalysis.

    Args:
        topology_file: PDB, PSF, or other topology file
        trajectory_file: DCD, XTC, TRR, or other trajectory
    """
    u = mda.Universe(topology_file, trajectory_file)
    print(f"Universe: {u.atoms.n_atoms} atoms, {u.trajectory.n_frames} frames")
    print(f"Time range: 0 to {u.trajectory.totaltime:.0f} ps")
    return u
python
import MDAnalysis as mda
from MDAnalysis.analysis import rms, align, contacts
import numpy as np
import matplotlib.pyplot as plt

def load_trajectory(topology_file, trajectory_file):
    """
    使用MDAnalysis加载MD轨迹。

    参数:
        topology_file:PDB、PSF或其他拓扑文件
        trajectory_file:DCD、XTC、TRR或其他轨迹文件
    """
    u = mda.Universe(topology_file, trajectory_file)
    print(f"Universe:{u.atoms.n_atoms} 个原子,{u.trajectory.n_frames} 帧")
    print(f"时间范围:0 到 {u.trajectory.totaltime:.0f} ps")
    return u

2. RMSD Analysis

2. RMSD分析

python
def compute_rmsd(u, selection="backbone", reference_frame=0):
    """
    Compute RMSD of selected atoms relative to reference frame.

    Args:
        u: MDAnalysis Universe
        selection: Atom selection string (MDAnalysis syntax)
        reference_frame: Frame index for reference structure

    Returns:
        numpy array of (time, rmsd) values
    """
    # Align trajectory to minimize RMSD
    aligner = align.AlignTraj(u, u, select=selection, in_memory=True)
    aligner.run()

    # Compute RMSD
    R = rms.RMSD(u, select=selection, ref_frame=reference_frame)
    R.run()

    rmsd_data = R.results.rmsd  # columns: frame, time, RMSD
    return rmsd_data

def plot_rmsd(rmsd_data, title="RMSD over time", output_file="rmsd.png"):
    """Plot RMSD over simulation time."""
    fig, ax = plt.subplots(figsize=(10, 4))
    ax.plot(rmsd_data[:, 1] / 1000, rmsd_data[:, 2], 'b-', linewidth=0.5)
    ax.set_xlabel("Time (ns)")
    ax.set_ylabel("RMSD (Å)")
    ax.set_title(title)
    ax.axhline(rmsd_data[:, 2].mean(), color='r', linestyle='--',
               label=f'Mean: {rmsd_data[:, 2].mean():.2f} Å')
    ax.legend()
    plt.tight_layout()
    plt.savefig(output_file, dpi=150)
    return fig
python
def compute_rmsd(u, selection="backbone", reference_frame=0):
    """
    计算选定原子相对于参考帧的RMSD。

    参数:
        u:MDAnalysis Universe
        selection:原子选择字符串(MDAnalysis语法)
        reference_frame:参考结构的帧索引

    返回:
        包含(时间,rmsd)值的numpy数组
    """
    # 对齐轨迹以最小化RMSD
    aligner = align.AlignTraj(u, u, select=selection, in_memory=True)
    aligner.run()

    # 计算RMSD
    R = rms.RMSD(u, select=selection, ref_frame=reference_frame)
    R.run()

    rmsd_data = R.results.rmsd  # 列:帧,时间,RMSD
    return rmsd_data

def plot_rmsd(rmsd_data, title="RMSD随时间变化", output_file="rmsd.png"):
    """绘制RMSD随模拟时间的变化图。"""
    fig, ax = plt.subplots(figsize=(10, 4))
    ax.plot(rmsd_data[:, 1] / 1000, rmsd_data[:, 2], 'b-', linewidth=0.5)
    ax.set_xlabel("时间 (ns)")
    ax.set_ylabel("RMSD (Å)")
    ax.set_title(title)
    ax.axhline(rmsd_data[:, 2].mean(), color='r', linestyle='--',
               label=f'平均值: {rmsd_data[:, 2].mean():.2f} Å')
    ax.legend()
    plt.tight_layout()
    plt.savefig(output_file, dpi=150)
    return fig

3. RMSF Analysis (Per-Residue Flexibility)

3. RMSF分析(残基水平灵活性)

python
def compute_rmsf(u, selection="backbone", start_frame=0):
    """
    Compute per-residue RMSF (flexibility).

    Returns:
        resids, rmsf_values arrays
    """
    # Select atoms
    atoms = u.select_atoms(selection)

    # Compute RMSF
    R = rms.RMSF(atoms)
    R.run(start=start_frame)

    # Average by residue
    resids = []
    rmsf_per_res = []
    for res in u.select_atoms(selection).residues:
        res_atoms = res.atoms.intersection(atoms)
        if len(res_atoms) > 0:
            resids.append(res.resid)
            rmsf_per_res.append(R.results.rmsf[res_atoms.indices].mean())

    return np.array(resids), np.array(rmsf_per_res)
python
def compute_rmsf(u, selection="backbone", start_frame=0):
    """
    计算残基水平的RMSF(灵活性)。

    返回:
        resids, rmsf_values 数组
    """
    # 选择原子
    atoms = u.select_atoms(selection)

    # 计算RMSF
    R = rms.RMSF(atoms)
    R.run(start=start_frame)

    # 按残基平均
    resids = []
    rmsf_per_res = []
    for res in u.select_atoms(selection).residues:
        res_atoms = res.atoms.intersection(atoms)
        if len(res_atoms) > 0:
            resids.append(res.resid)
            rmsf_per_res.append(R.results.rmsf[res_atoms.indices].mean())

    return np.array(resids), np.array(rmsf_per_res)

4. Protein-Ligand Contacts

4. 蛋白质-配体接触分析

python
def analyze_contacts(u, protein_sel="protein", ligand_sel="resname LIG",
                      radius=4.5, start_frame=0):
    """
    Track protein-ligand contacts over trajectory.

    Args:
        radius: Contact distance cutoff in Angstroms
    """
    protein = u.select_atoms(protein_sel)
    ligand = u.select_atoms(ligand_sel)

    contact_frames = []
    for ts in u.trajectory[start_frame:]:
        # Find protein atoms within radius of ligand
        distances = contacts.contact_matrix(
            protein.positions, ligand.positions, radius
        )
        contact_residues = set()
        for i in range(distances.shape[0]):
            if distances[i].any():
                contact_residues.add(protein.atoms[i].resid)
        contact_frames.append(contact_residues)

    return contact_frames
python
def analyze_contacts(u, protein_sel="protein", ligand_sel="resname LIG",
                      radius=4.5, start_frame=0):
    """
    追踪轨迹中蛋白质与配体的接触情况。

    参数:
        radius:接触距离阈值,单位为埃
    """
    protein = u.select_atoms(protein_sel)
    ligand = u.select_atoms(ligand_sel)

    contact_frames = []
    for ts in u.trajectory[start_frame:]:
        # 找到配体半径范围内的蛋白质原子
        distances = contacts.contact_matrix(
            protein.positions, ligand.positions, radius
        )
        contact_residues = set()
        for i in range(distances.shape[0]):
            if distances[i].any():
                contact_residues.add(protein.atoms[i].resid)
        contact_frames.append(contact_residues)

    return contact_frames

Force Field Selection Guide

力场选择指南

SystemRecommended Force FieldWater Model
Standard proteinsAMBER14 (
amber14-all.xml
)
TIP3P-FB
Proteins + small moleculesAMBER14 + GAFF2TIP3P-FB
Membrane proteinsCHARMM36mTIP3P
Nucleic acidsAMBER99-bsc1 or AMBER14TIP3P
Disordered proteinsff19SB or CHARMM36mTIP3P
系统类型推荐力场水模型
标准蛋白质AMBER14 (
amber14-all.xml
)
TIP3P-FB
蛋白质+小分子AMBER14 + GAFF2TIP3P-FB
膜蛋白CHARMM36mTIP3P
核酸AMBER99-bsc1 或 AMBER14TIP3P
无序蛋白质ff19SB 或 CHARMM36mTIP3P

System Preparation Tools

系统准备工具

PDBFixer (for raw PDB files)

PDBFixer(处理原始PDB文件)

python
from pdbfixer import PDBFixer
from openmm.app import PDBFile

def fix_pdb(input_pdb, output_pdb, ph=7.0):
    """Fix common PDB issues: missing residues, atoms, add H, standardize."""
    fixer = PDBFixer(filename=input_pdb)
    fixer.findMissingResidues()
    fixer.findNonstandardResidues()
    fixer.replaceNonstandardResidues()
    fixer.removeHeterogens(True)    # Remove water/ligands
    fixer.findMissingAtoms()
    fixer.addMissingAtoms()
    fixer.addMissingHydrogens(ph)

    with open(output_pdb, 'w') as f:
        PDBFile.writeFile(fixer.topology, fixer.positions, f)

    return output_pdb
python
from pdbfixer import PDBFixer
from openmm.app import PDBFile

def fix_pdb(input_pdb, output_pdb, ph=7.0):
    """修复常见PDB问题:缺失残基、原子,添加氢原子,标准化结构。"""
    fixer = PDBFixer(filename=input_pdb)
    fixer.findMissingResidues()
    fixer.findNonstandardResidues()
    fixer.replaceNonstandardResidues()
    fixer.removeHeterogens(True)    # 移除水/配体
    fixer.findMissingAtoms()
    fixer.addMissingAtoms()
    fixer.addMissingHydrogens(ph)

    with open(output_pdb, 'w') as f:
        PDBFile.writeFile(fixer.topology, fixer.positions, f)

    return output_pdb

GAFF2 for Small Molecules (via OpenFF Toolkit)

用于小分子的GAFF2(通过OpenFF Toolkit)

python
undefined
python
undefined

For ligand parameterization, use OpenFF toolkit or ACPYPE

配体参数化可使用OpenFF Toolkit或ACPYPE

pip install openff-toolkit

pip install openff-toolkit

from openff.toolkit import Molecule, ForceField as OFFForceField from openff.interchange import Interchange
def parameterize_ligand(smiles, ff_name="openff-2.0.0.offxml"): """Generate GAFF2/OpenFF parameters for a small molecule.""" mol = Molecule.from_smiles(smiles) mol.generate_conformers(n_conformers=1)
off_ff = OFFForceField(ff_name)
interchange = off_ff.create_interchange(mol.to_topology())
return interchange
undefined
from openff.toolkit import Molecule, ForceField as OFFForceField from openff.interchange import Interchange
def parameterize_ligand(smiles, ff_name="openff-2.0.0.offxml"): """为小分子生成GAFF2/OpenFF参数。""" mol = Molecule.from_smiles(smiles) mol.generate_conformers(n_conformers=1)
off_ff = OFFForceField(ff_name)
interchange = off_ff.create_interchange(mol.to_topology())
return interchange
undefined

Best Practices

最佳实践

  • Always minimize before MD: Raw PDB structures have steric clashes
  • Equilibrate before production: NVT (50–100 ps) → NPT (100–500 ps) → Production
  • Use GPU: Simulations are 10–100× faster on GPU (CUDA/OpenCL)
  • 2 fs timestep with HBonds constraints: Standard; use 4 fs with HMR (hydrogen mass repartitioning)
  • Analyze only equilibrated trajectory: Discard first 20–50% as equilibration
  • Save checkpoints: MD runs can fail; checkpoints allow restart
  • Periodic boundary conditions: Required for solvated systems
  • PME for electrostatics: More accurate than cutoff methods for charged systems
  • MD模拟前务必进行能量最小化:原始PDB结构存在空间位阻冲突
  • 生产模拟前先平衡:NVT(50–100皮秒)→ NPT(100–500皮秒)→ 生产模拟
  • 使用GPU:GPU(CUDA/OpenCL)上的模拟速度比CPU快10–100倍
  • 约束氢键时使用2飞秒时间步长:标准设置;使用HMR(氢质量 repartitioning)时可使用4飞秒
  • 仅分析平衡后的轨迹:丢弃前20–50%的轨迹作为平衡阶段数据
  • 保存检查点:MD模拟可能失败,检查点可用于重启
  • 周期性边界条件:溶剂化系统必须使用
  • PME处理静电相互作用:对于带电系统,比截断方法更准确

Additional Resources

额外资源