简介这份资源面向计算化学与材料科学领域的研究者及研究生提供一套可复用的批量分子动力学模拟脚本与配套示例用于自动化处理一系列相似的MD任务减少重复手工配置适合已具备MD基础、希望提升批量模拟效率的中高级用户。压缩包共427个文件约14.62MB以in输入控制文件、ac与ac0等Antechamber中间文件、pdb结构文件、prmtop与inpcrd拓扑及坐标文件、frcmod力场参数、mol2分子文件为主另含sh批处理脚本、py脚本、log与out运行记录及少量文档覆盖从系统构建、参数准备到模拟执行与结果记录的完整环节。已有694人学习下载。借助其中的脚本与示例读者可快速理解批量模拟的参数设置与调用流程参考现成的分子体系配置和力场文件搭建测试环境并对照输入输出文件验证结果为相变、溶剂化效应或药物与受体相互作用等批量研究提供可借鉴的实践基础。1. 批量分子动力学模拟脚本从“一台机器跑一个算例”到“一晚上扫完参数面”做材料计算的人大概都经历过这种夜晚手上有十几个甚至几十个结构文件每个都要跑一遍能量最小化加 NVT 退火参数还分好几组温度、几组时间步长。手动改输入文件、提交任务、盯着队列、收数据一晚上过去只推进了三五个算例第二天组会还得现拼表格。这份批量分子动力学模拟脚本和示例解决的就是这个“参数面扫描”的重复劳动问题——它把输入生成、任务提交、状态轮询、结果归档串成一条流水线让一台普通工作站也能把几十个算例排着队跑完。适合已经会写单个 LAMMPS 或 GROMACS 输入、但还没把流程脚本化的研究生和一线计算工程师也适合想把课题组祖传手工流程整理成可复现管线的人。2. 批量脚本的骨架输入模板、任务清单与调度循环批量模拟的本质不是“写一个更长的输入文件”而是把一次模拟拆成“可变参数”和“不变模板”两部分再用一个外层循环把两者拼起来。这份资源的组织方式正是如此一个模板目录放基础输入一个参数表描述每个算例的差异一个调度脚本负责生成、提交、等待、收集。理解这三层结构后面改参数、加算例、换调度器都不会乱。2.1 为什么用“模板 参数表”而不是复制粘贴手工复制输入文件最大的问题是漂移改到第十个算例时你很可能忘了把某个 group 定义同步过去或者温度值改了一半。模板加参数表的做法把“结构”和“数值”分离模板只写一次参数表每行一个算例。常见做法是用一个 CSV 或 YAML 描述算例字段包括算例名、结构文件、温度、步数、随机种子。这样新增算例只是加一行回滚只是删一行复现时把参数表一起归档即可。下面是一个参数表的示例字段名可以按自己的模拟类型调整case_id,structure,temperature,steps,seed case_001,conf_a.data,300,500000,20240101 case_002,conf_a.data,600,500000,20240102 case_003,conf_b.data,300,500000,20240103 case_004,conf_b.data,600,500000,20240104case_id同时用作输出目录名保证结果可追溯structure是相对模板目录的路径temperature和steps是本次扫描的两个维度seed单独列出而不是让程序自动生成是为了让同一算例重跑时结果可比。参数表里不要放绝对路径否则换机器就废了。2.2 生成算例目录的脚本与占位符替换模板里用{{TEMPERATURE}}这类占位符标记可变位置生成脚本逐行读参数表为每个算例建目录并渲染输入。用 Python 写比 bash 稳因为字符串替换和路径处理不容易被空格坑到import csv, os, shutil TEMPLATE_DIR template RUNS_DIR runs def render(template_text, params): for key, value in params.items(): template_text template_text.replace({{ key.upper() }}, str(value)) return template_text with open(cases.csv, newline) as f: for row in csv.DictReader(f): case_dir os.path.join(RUNS_DIR, row[case_id]) os.makedirs(case_dir, exist_okTrue) # 复制结构文件到算例目录避免多算例共享同一文件被误改 shutil.copy(os.path.join(TEMPLATE_DIR, row[structure]), case_dir) with open(os.path.join(TEMPLATE_DIR, in.template)) as t: text t.read() rendered render(text, row) with open(os.path.join(case_dir, in.lammps), w) as out: out.write(rendered)render函数只做最朴素的占位符替换够用且好排查os.makedirs(..., exist_okTrue)让脚本可以重复执行而不报错把结构文件复制进算例目录是关键一步很多批量流程翻车就翻在多个算例引用同一个结构文件、某个算例的预处理把它改了。参数说明上TEMPLATE_DIR和RUNS_DIR建议做成命令行参数方便在不同项目间复用。2.3 调度循环提交、轮询、失败重试生成完算例只是第一步真正省时间的是调度循环。核心逻辑是维护一个“待跑队列”按并发上限提交任务定期检查进程或作业状态失败的算例记录日志后重试一次。单机场景下用subprocess起进程并检查返回码即可import subprocess, time, os MAX_CONCURRENT 4 pending sorted(os.listdir(RUNS_DIR)) running {} while pending or running: # 补满并发槽位 while pending and len(running) MAX_CONCURRENT: case pending.pop(0) case_dir os.path.join(RUNS_DIR, case) log open(os.path.join(case_dir, run.log), w) proc subprocess.Popen( [lmp, -in, in.lammps], cwdcase_dir, stdoutlog, stderrsubprocess.STDOUT ) running[case] (proc, log, time.time()) # 轮询已启动任务 for case in list(running): proc, log, start running[case] if proc.poll() is not None: log.close() if proc.returncode ! 0: print(f[FAIL] {case} rc{proc.returncode}) del running[case] time.sleep(10)MAX_CONCURRENT要按机器的物理核心数和每个算例的 MPI 进程数来定常见做法是“总核数除以单算例核数再留一个核给系统”cwdcase_dir保证相对路径都落在算例目录内日志单独落文件而不是打到终端是为了失败后能直接翻run.log找报错行。如果跑在集群上把Popen换成提交命令、把poll换成查队列状态即可循环骨架不变。3. 参数怎么设温度、步长、系综与输出频率的取舍批量跑起来之后真正决定结果能不能用的是参数设置。批量场景下参数错误会被放大几十倍——一个错误的步长设置意味着几十个算例全部白跑。这一章把几个最容易出问题的参数拎出来说清楚重点不是教科书定义而是“批量时该怎么定、定错了看什么现象”。3.1 时间步长与总步数的匹配时间步长和总步数是乘数关系批量扫描时最忌讳只改一个。常见做法是固定物理总时长比如 500 ps再根据体系类型选步长含氢原子的全原子体系一般 1 fs粗粒化或含约束的体系可以到 2 fs 甚至更大。如果参数表里steps是扫描维度务必在表里同时记录步长否则不同算例的物理时长不可比后处理画图时会出现“温度曲线长度不一样”的尴尬。判断步长是否过大有个实用信号能量漂移。跑完后看日志里的总能量随时间变化如果出现持续单向漂移而不是围绕均值波动多半是步长偏大或约束没设对。批量流程里可以在收集阶段加一个简单检查把能量漂移超过阈值的算例标出来避免逐个翻日志。3.2 系综选择与恒温器参数NVT 是最常见的批量扫描系综但恒温器的弛豫时间常数经常被忽略。设置过小会让体系像被强行搅拌温度曲线剧烈震荡设置过大则温度迟迟到不了目标值前一段数据不可用。经验值是弛豫时间取总模拟时长的百分之一到十分之一之间具体看体系。批量时建议把恒温器参数写进模板而不是参数表除非你确实要扫描它——扫描维度越多算例数指数增长一晚上跑不完。提示批量扫描前先用单个算例跑短时长比如总步数的十分之一确认温度能稳定到目标值再放开全量。这一步能省掉大量无效算例。3.3 输出频率与磁盘占用批量模拟的磁盘消耗很容易失控。轨迹输出频率设得太密几十个算例能把工作盘写满写到一半的算例直接失败。常见做法是热力学量每几百步输出一次轨迹每几千步输出一次并在参数表里显式记录输出间隔。跑之前估算一下单算例大小原子数乘以每帧字节数乘以帧数再乘以算例数和可用空间对一下。这个估算花两分钟能避免半夜磁盘满导致整批任务挂掉。4. 避坑与排查批量流程里最容易翻车的五件事批量脚本写起来不难难的是它在无人值守时出的问题往往没有明显报错。下面五条是这类流程里反复出现的坑每条按现象、原因、解决写照着排查能省不少时间。4.1 算例目录里混入了上一次的续跑文件现象重跑某个算例后结果和上次不一致或者模拟从中间状态开始而不是从头开始。原因很多 MD 引擎会在工作目录写 restart 或 checkpoint 文件脚本重复执行时没有清理引擎自动读取了旧状态。解决生成阶段对已存在的算例目录先清空或改名备份或者在输入里显式关闭自动续跑让每次运行都从初始结构开始。4.2 并发数按逻辑核数设机器被拖死现象批量跑起来后系统响应极慢甚至调度脚本自己被卡住。原因MAX_CONCURRENT按逻辑核数设置但每个算例内部又开了多线程或 MPI实际负载远超物理核心。解决并发数按“物理核数除以单算例核数”计算并给系统留至少一个核跑之前用单个算例测一下实际 CPU 占用别信标称值。4.3 相对路径在切换工作目录后失效现象手动在算例目录里能跑脚本一跑就报找不到文件。原因脚本用cwd切换了工作目录但输入文件里写的是相对模板目录的路径。解决生成阶段就把所有路径解析成算例目录内的相对路径或绝对路径输入文件里不出现跨目录引用结构文件复制进算例目录就是这个道理。4.4 失败算例被静默跳过现象跑完一看算例数对不上但终端没有明显报错。原因调度循环只检查进程是否结束没检查返回码或者日志被覆盖导致错误信息丢失。解决每个算例的日志单独落文件且不覆盖循环里显式判断返回码并汇总失败列表跑完后打印“成功 N 个、失败 M 个、失败清单如下”。4.5 参数表编码和空行导致解析错位现象某个算例的温度值变成了结构文件名或者最后一个算例莫名消失。原因CSV 里有空行、多余逗号或非 UTF-8 编码DictReader解析错位。解决参数表用纯 ASCII 字段名生成前先做一次行数和字段数校验空行直接跳过并打印警告不要用 Excel 直接另存容易带 BOM。5. 从能跑到可信结果收集、一致性校验与一个收尾习惯批量流程跑通只是及格线真正决定这份资源值不值得长期用的是“结果可信度”。几十个算例跑完你需要快速判断哪些结果能用、哪些要重跑而不是逐个打开轨迹看。我的做法是在调度循环之后加一个收集脚本把每个算例的关键标量平均温度、平均势能、能量漂移、运行时长抽成一张汇总表再按算例名排序输出。这样一眼就能看出哪个算例的温度偏离目标值、哪个势能明显异常。一致性校验有个便宜但有效的技巧对同一结构、不同随机种子的算例比较它们的平均势能。如果差异远大于热涨落量级说明采样不足或者某个参数设置有问题这批结果就不能直接拿去做统计。另一个检查是看运行时长分布某个算例耗时明显偏长往往是它触发了某种数值不稳定值得单独翻日志。import os, re, csv rows [] for case in sorted(os.listdir(runs)): log_path os.path.join(runs, case, run.log) if not os.path.exists(log_path): continue text open(log_path, errorsignore).read() # 从日志尾部抓取热力学输出的最后一行作为代表值 matches re.findall(r^\s*(\d)\s([-\d.])\s([-\d.]), text, re.M) if not matches: rows.append([case, NO_DATA, , ]) continue step, temp, pe matches[-1] rows.append([case, step, temp, pe]) with open(summary.csv, w, newline) as f: writer csv.writer(f) writer.writerow([case_id, last_step, temperature, potential_energy]) writer.writerows(rows)这段收集脚本的正则按自己引擎的日志格式改重点是“取最后一行代表值”和“无数据算例显式标记”不要让缺失数据静默消失。汇总表出来后用任何表格工具按温度分组看势能分布异常值一目了然。从那以后我每次批量跑之前都会先用两个算例做一次端到端演练生成、提交、轮询、收集全走一遍确认汇总表能正确出数再放开全量。这个习惯帮我拦下过路径错误、日志覆盖和并发设置过高好几类问题。希望帮到你。本文还有配套的精品资源点击获取