- 科研
- 科学计算
- 高性能计算
【免费下载链接】lammps
Public development project of the LAMMPS MD software package
fix ave/time是 LAMMPS 中最常用的时间平均与数据输出工具:它以固定的时间间隔采样一个或多个由 compute、fix 或 variable 产生的全局量,在更长时间尺度上做平均,并把结果交给thermo_style等其他输出命令使用或直接写入文件。本文基于 doc/src/fix_ave_time.rst 官方文档,结合 src/fix_ave_time.cpp 与 src/fix_ave_time.h 源码以及仓库内的实际用例与单元测试,系统讲解语法、采样时序(Nevery/Nrepeat/Nfreq)、三种平均模式(one/running/window)、通配符展开、文件输出与 YAML 结构化数据,以及底层实现原理与常见陷阱。读完本文,你可以熟练配置各类全局量的时间平均、正确设计输出文件格式,并理解其内部工作机制。
命令语法与核心参数
fix ave/time的完整语法如下:
fix ID group-ID ave/time Nevery Nrepeat Nfreq value1 value2 ... keyword args ...- ID、group-ID:与所有 fix 命令相同的通用参数;其中 group-ID 在本命令中会被忽略(见下文)。
- ave/time:本 fix 的样式名(style name)。
- Nevery:每隔多少个时间步采样一次输入值。
- Nrepeat:每个平均周期内使用输入值的次数(即采样点数)。
- Nfreq:每隔多少个时间步计算一次平均结果。
- value:一个或多个输入值,形式为
c_ID、c_ID[N]、f_ID、f_ID[N]、v_name(支持通配符,详见下文)。 - 关键字:
mode、file、append、ave、start、off、overwrite、format、title1、title2、title3,零个或多个。
输入值(value)的三种来源
| 前缀 | 含义 | 取值规则 |
|---|---|---|
c_ID | 由 ID 为ID的 compute 计算出的全局标量/向量 | c_ID取全局标量,c_ID[N]取全局向量第 N 个元素;c_ID[N]中的 N 支持通配符 |
f_ID | 由 ID 为ID的 fix 计算出的全局标量/向量 | f_ID取全局标量,f_ID[N]取全局向量第 N 个元素;N 支持通配符 |
v_name | 由名为name的 equal-style 或 vector-style variable 计算的值 | v_name取标量,v_name[N]取向量第 N 个元素;N 支持通配符 |
三种来源都必须产生全局量(global quantity),不能是 per-atom 或 local 量:
- compute 中只有样式名不含
atom的才是全局量 compute;只有少数 fix 产生全局量(需查阅各 fix 的文档页)。 - variable 只有
equal和vector两种样式可用于本命令;atom样式产生 per-atom 值,不能使用。 - 若需要对 per-atom 量做空间/时间平均或直方图统计,应使用 fix ave/chunk、fix ave/atom、fix ave/histo;若需把 per-atom 量求和为单一全局量,应使用 compute reduce。
mode:标量模式还是向量模式
mode关键字决定了所有输入值的统一类型:
mode = scalar(默认):所有输入值必须是全局标量,或带括号索引的向量元素(取第 I 个值)。mode = vector:所有输入值必须是全局向量,或带括号索引的数组列(取第 I 列)。所有向量必须等长,该长度即输出行数。
无论哪种模式,每个输入值都是独立平均的:每个标量独立平均,或每个向量元素/数组列独立平均。
官方示例
以下示例摘自 doc/src/fix_ave_time.rst 的 Examples 一节:
fix 1 all ave/time 100 5 1000 c_myTemp c_thermo_temp file temp.profile fix 1 all ave/time 100 5 1000 c_thermo_press[2] ave window 20 & title1 "My output values" fix 1 all ave/time 100 5 1000 c_thermo_press[*] fix 1 all ave/time 1 100 1000 f_indent f_indent[1] file temp.indent off 1- 第一个例子每 100 步采样
c_myTemp和c_thermo_temp两个值、每 1000 步输出一次平均,并写入temp.profile。 - 第二个例子对
c_thermo_press[2]做 20 个窗口的滑动平均,同时自定义文件首行标题。 - 第三个例子用通配符
c_thermo_press[*]把压力向量所有分量全部纳入平均。 - 第四个例子混合了 fix 产生的标量
f_indent与其向量元素f_indent[1],并用off 1让第一个值不做平均。
Nevery/Nrepeat/Nfreq:时间平均的采样时序
这三个参数共同决定了在哪些时间步采样、哪些时间步输出平均结果。其规则(见文档说明,且在源码 src/fix_ave_time.cpp 中强制校验)为:
- 平均结果在
Nfreq的整数倍时间步上生成。 - 每个平均周期使用
Nrepeat个采样值,这些采样值在前一段模拟中每隔Nevery步取一次。 - 约束条件:
Nfreq必须是Nevery的整数倍(源码中校验nfreq % nevery);- 采样时间步不能重叠,即
Nrepeat × Nevery不能超过Nfreq(源码校验nrepeat*nevery > nfreq时报错); Nevery即使Nrepeat = 1也必须非零(源码校验nevery <= 0时报错)。
时序示例:若Nevery=2, Nrepeat=6, Nfreq=100,则第 90、92、94、96、98、100 步的取值用于计算第 100 步的平均值;类似地,第 190、192、194、196、198、200 步的取值用于计算第 200 步的平均值。若Nrepeat=1, Nfreq=100,则不做时间平均,直接在第 100、200 等步输出原始采样值——此时本命令就退化为一个"定时输出全局量到文件"的便捷工具。
从源码看,这个时序在nextvalid()(src/fix_ave_time.cpp)中实现:先计算下一个Nfreq倍数步,再回退(Nrepeat-1)*Nevery步作为本周期第一次采样的时间步;end_of_step()(src/fix_ave_time.cpp)只在ntimestep == nvalid时触发,每采完Nrepeat个点就把nvalid推进到下一个周期起点。
三种平均模式:one / running / window
ave关键字决定每个Nfreq周期产生的值如何与之前周期的值再做一次平均,然后才被其他输出命令访问或写入文件:
ave one(默认):各Nfreq周期产生的值相互独立,按原样输出,不再做跨周期平均。ave running:所有Nfreq周期产生的值做累计平均(cumulative),每次输出的是当前值与此前所有值的平均。运行平均从 fix 定义时开始,只能通过 unfix 删除该 fix 或重新定义 fix 来重置。ave window M:在长度为 M 的滑动窗口内做平均,输出最近 M 个Nfreq周期的均值。例如M=3, Nfreq=1000时,第 10000 步的输出是第 8000、9000、10000 步单个值的平均;早期步数不足 M 个值时,则对已有值求平均。
三种模式在源码中分别对应enum { ONE, RUNNING, WINDOW }(src/fix_ave_time.cpp)与invoke_scalar()/invoke_vector()中的三条分支(src/fix_ave_time.cpp):one直接覆盖累加缓冲,running累加并递增归一化因子norm,window用环形缓冲vector_list/array_list维护最近 M 个值(iwindow循环回绕,满窗后window_limit=1且norm=nwindow)。
start:平均起点
start Nstart指定从哪个时间步开始平均,默认从第 0 步开始。由于很多输入值在 0 时刻取值为 0.0,把start设为一个较大值可以避免把 0.0 混入 running 或 windowed 平均中。源码nextvalid()中while (nvalid < startstep) nvalid += nfreq;正是用startstep作为Nfreq倍数的下界。
off:跳过某个值的平均
off M将第 M 个输入值(M 取值 1 到 Nvalues)标记为不做时间平均,而是始终保存并输出最近一次采样值。这适用于那些由 compute/fix/variable 产生、实际上近似常数或本身就是"当前值"的输入(例如为了与其它时间平均值一起生成格式规整的输出文件)。源码在解析时记录offlist,校验1 <= M <= nvalues(src/fix_ave_time.cpp),采样时对offcol列直接赋值而非累加(src/fix_ave_time.cpp),输出时乘回norm以保持原始数值(src/fix_ave_time.cpp)。
通配符:一次指定多个向量分量或数组列
输入值中括号内的索引 I 可以用星号通配符一次指定多个值,形式为*、*n、m*或m*n。设 N 为向量长度(scalar 模式)或数组列数(vector 模式):
*:所有索引 1 到 N;*n:索引 1 到 n(含);m*:索引 m 到 N(含);m*n:索引 m 到 n(含)。
使用通配符等价于把向量元素或数组列逐个列出。例如文档中的等价示例——compute rdf产生一个 3 列、每列长度 50 的全局数组:
compute myRDF all rdf 50 1 2 fix 1 all ave/time 100 1 100 c_myRDF[*] file tmp1.rdf mode vector fix 2 all ave/time 100 1 100 c_myRDF[1] c_myRDF[2] c_myRDF[3] file tmp2.rdf mode vector两个 fix 完全等价。源码中通配符由utils::expand_args()在解析阶段展开(src/fix_ave_time.cpp),展开后每个分量成为独立输入值。
注意(vector-style variable):对于 vector-style variable,只允许
*n或m*n形式,必须指定上界,因为变量长度要到求值时才确定。若指定的 n 大于实际向量长度,缺失位置的输出值为 0。
源码印证了这一点:invoke_scalar()中对变量取值时,if (val.argindex > nvec) scalar = 0.0;(src/fix_ave_time.cpp),即越界分量输出 0.0。
输入值的具体取值规则
c_前缀:必须引用输入脚本中已定义的 compute ID。scalar 模式:无括号取全局标量,带括号取全局向量第 I 个元素;vector 模式:无括号取全局向量,带括号取全局数组第 I 列。I 可含通配符。f_前缀:必须引用已定义的 fix ID,规则同 compute。注意部分 fix 只在特定时间步产生值,这些时间步必须与Nevery兼容,否则会报错——源码在解析时校验nevery % val.val.f->global_freq(src/fix_ave_time.cpp),即 fix 的计算频率必须整除 Nevery。v_前缀:必须引用已定义的变量名。scalar 模式只允许 equal-style 或 vector-style 变量,其中 vector-style 变量必须带括号指定第 I 个元素;vector 模式只允许 vector-style 变量且不带括号。
equal和vector样式变量的公式可以引用单个原子属性、热力学关键字,也可以求值时调用其他 compute、fix 或变量——因此变量是表达待平均量的非常通用的手段。
另一个实用组合:compute reduce可以把 per-atom 量求和为全局标量或向量,再交给fix ave/time使用;此外还可以使用输入脚本之外由thermo_style或其它 fix(如 fix nvt、fix temp/rescale)隐式定义的 compute——这些命令的文档页会给出这些 compute 的 ID。
文件输出:file / append / overwrite / format / 标题行
file或append关键字指定输出文件名,两者互斥(file覆盖已存在文件,append追加到已存在文件或新建)。每Nfreq步,为每个输入值写入一个量或一个向量:
- scalar 模式:每次输出一行,文件最终成为一系列行,即每个输入值一列数字。
- vector 模式:每次输出一个数字块,行数为输入向量长度、列数为输入值个数,文件最终成为一系列这样的块。
YAML 结构化输出
若文件名以.yaml或.yml结尾(4May2022 版本起支持),输出格式符合 YAML 标准,便于用支持 YAML 的脚本和工具直接导入数据。Howto_structured_data 展示了如何用 Python 的pyyaml、pandas、matplotlib以极少的代码解析和绘图。源码中通过utils::strmatch(arg[iarg+1],"\\.[yY][aA]?[mM][lL]$")检测 YAML 后缀并切换输出分支(src/fix_ave_time.cpp),YAML 输出以keywords:与data:两个节构成,文件末尾由析构函数写入...结束符(src/fix_ave_time.cpp)。
overwrite:只保留最新输出
overwrite关键字让输出文件被持续覆盖为最新结果,文件里始终只保留一个时间步的输出。该选项只能与ave running组合使用,源码在解析时校验if (ave != RUNNING && overwrite) error(src/fix_ave_time.cpp)。实现上每次输出后fseek回到文件头并ftruncate截断(src/fix_ave_time.cpp)。
仓库的弹性常数计算示例中就有典型用法:
fix CB all ave/time 1 ${nthermo} ${nthermo} c_born[*] ave running file born.out overwrite(见 examples/ELASTIC_T/BORN_MATRIX/Argon/Analytical/in.ljcov,对 Born 矩阵的全部张量分量做累计平均并保持文件只有最新结果。)
format:数值格式
format关键字设置每个值写入文件时的数字格式,所有值都是浮点数,默认格式为" %g"。需要更高精度时可指定如" %20.16g"。
版本变更(2Sep2026):格式字符串在设置时会立即被校验,若其转换格式不匹配浮点值,LAMMPS 会直接报错停止;此前不匹配的格式字符串不会被检测到,只会静默产生错误输出。包含非转换的普通文本仍然是合法的。
源码中的校验通过utils::check_format(arg[iarg+1], utils::FmtArg::FLOAT)完成(src/fix_ave_time.cpp),不合格的格式在解析阶段即报Invalid fix ave/time format argument错误。
默认标题行
使用file关键字时,title1、title2、title3分别指定输出文件的前 2 或 3 行字符串,均有默认值,通常无需指定。默认标题随 LAMMPS 版本演进,当前默认如下:
scalar 模式:
# Time-averaged data for fix ID mode scalar ave AVE version VERSION # TimeStep value1 value2 ...vector 模式:
# Time-averaged data for fix ID mode vector ave AVE version VERSION # TimeStep Number-of-rows # Row value1 value2 ...第一行中 ID 替换为 fix-ID,AVE 替换为ave设置(one/running/window),VERSION 替换为 LAMMPS 版本号数字(例如 20260930 对应 2026 年 9 月 30 日版本);后两行中的 value 字段替换为fix ave/time命令中的相应输入。scalar 模式文件只有两行标题,title3设置会被忽略。这些默认行正是由源码构造输出的(src/fix_ave_time.cpp)。
该 fix 的输出量、重启与 minimize 行为
- 不写入二进制重启文件(4May2022 版本起明确说明),重启后需要重新定义本 fix 才能恢复时间平均。
- 本 fix 产生一个全局标量、全局向量或全局数组,可被各种输出命令访问;且只能在
Nfreq的倍数时间步访问,因为只有那时才执行平均。 - 产生规则(与源码中
scalar_flag/vector_flag/array_flag的设置逻辑对应,src/fix_ave_time.cpp):- scalar 模式下平均单个输入值 → 全局标量;
- scalar 模式下平均多个输入值 → 全局向量(长度为输入个数);
- vector 模式下单个输入值 → 全局向量(长度等于输入向量长度);
- vector 模式下多个输入值 → 全局数组(行数 = 输入向量长度,列数 = 输入个数)。
- intensive/extensive 属性:产生标量或向量时,每个元素按其来源(compute/fix)自身的 intensive/extensive 属性决定;产生数组时,所有元素必须一致。变量产生的值一律视为 intensive。
- 本 fix 的任何参数都不能与
run命令的start/stop关键字搭配使用;本 fix 在能量最小化(minimize)过程中不会被调用。
源码级实现要点
类结构与关键成员
FixAveTime继承自基类Fix(src/fix_ave_time.h),核心成员包括:
value_t结构体:记录每个输入值的来源类型(COMPUTE/FIX/VARIABLE)、1 基索引、原始参数位置、是否为变长、off 标记、ID 与输出列关键字;nvalues / nrepeat / nfreq / irepeat:输入个数、采样周期、输出周期、当前周期内已采样次数;nvalid / nvalid_last:下一次触发时间步;ave / nwindow / startstep / mode / noff / overwrite:各关键字设置;- 平均缓冲:
vector / vector_total / vector_list(scalar 模式)与array / array_total / array_list(vector 模式,array_list仅 window 模式使用); norm:归一化因子,iwindow / window_limit:窗口状态。
执行流程
- 解析阶段:先扫描统计输入值个数(第 6 个参数之后连续的
c_/f_/v_前缀参数),再解析可选关键字(options(),src/fix_ave_time.cpp),因为需要先知道mode才能展开通配符,然后对每个输入值校验 compute/fix/variable 的存在性与类型匹配,最后完成各项合法性检查。 - 时间步执行:
setmask()只注册END_OF_STEP回调(src/fix_ave_time.cpp);end_of_step()仅在ntimestep == nvalid时按模式调用invoke_scalar()或invoke_vector()。 - 采样与平均:每个触发步把当前输入值累加进缓冲;采满
nrepeat次后除以采样数得到本周期均值;再按ave模式与历史合并,norm记录参与合并的周期数;最后按需写文件。compute_scalar()/compute_vector()/compute_array()(src/fix_ave_time.cpp)供其他输出命令以f_ID形式读取,返回值即vector_total/array_total除以norm。
变长输入的处理
对产生变长向量/数组的 compute(如compute rdf、compute chunk/atom系列)以及所有 vector-style variable,源码引入了"长度锁定"机制:当nrepeat > 1或ave = running/window时,在周期内对变长 compute 调用lock(),禁止行数在Nfreq周期中途改变(src/fix_ave_time.cpp),周期结束后或析构函数中再unlock()。所有输入列长度必须一致(column_length()校验,src/fix_ave_time.cpp),否则报columns have inconsistent lengths错误。
变长输入的注意点
off M值必须在 1 到输入个数之间。vector 模式下,所有输入向量/数组行数必须相同;vector-style variable 若在运行中改变长度会报错(src/fix_ave_time.cpp)。这些限制都来自文档的 Restrictions 一节与源码校验。
相关命令与默认值速查
相关命令:compute、fix ave/atom、fix ave/chunk、fix ave/histo、fix ave/correlate(时间相关函数平均)、variable。其中fix ave/correlate专门用于计算时间相关函数(如 VACF),与fix ave/time的简单平均互补。
默认值(与源码options()中初始化一致):mode = scalar、ave = one、start = 0、默认不写文件、format = %g、标题 1/2/3 为上述默认字符串、所有输入值均不设置 off。
单元测试佐证:仓库的 unittest/force-styles/tests/fix-output-ave_time.yaml 用四分子体系(in.fourmol)与compute gyration组合,执行fix test all ave/time 1 10 10 c_gyr mode scalar,验证平均结果的全局标量值与参考值(3.8528674535190732,epsilon 1e-08)一致;另有fix-output-ave_time_vector_varlen.yaml与fix-output-ave_time_array_varlen.yaml覆盖变长向量/数组场景。这些测试文件同时展示了fix ave/time可与compute gyration这类全局向量 compute 直接组合的典型用法。
常见使用场景小结
- 温度/压力等热力学量的时间平均:
fix 1 all ave/time 100 5 1000 c_thermo_temp c_thermo_press[*] file thermo.avg,每 1000 步输出一次基于 5 次采样的平均值。 - 滑动平均监测演化趋势:
fix 1 all ave/time 100 5 1000 c_thermo_press[2] ave window 20,输出最近 20 个周期(共 20000 步)的压力滑动均值。 - RDF 等全局数组的多列平均:
compute myRDF all rdf 50 1 2+fix 1 all ave/time 100 1 100 c_myRDF[*] file tmp.rdf mode vector。 - 只输出不做平均:
fix 1 all ave/time 1 1 100 c_thermo_temp file temp.out,等价于每 100 步把当前值写入文件。 - 混合输出"当前值 + 平均值":用
off标记保持当前值输出的列,其余列做时间平均,形成规整的多列文件。 - 与 compute reduce 组合:先
compute 1 all reduce sum c_ke之类把 per-atom 量归约为全局量,再交给fix ave/time平均。
编写输入脚本时请注意:所有引用的 compute/fix/variable 必须在使用前定义,compute 与 fix 产生的必须是全局量,Nfreq必须能被Nevery整除且Nrepeat*Nevery <= Nfreq,vector 模式下列长必须一致。把握住这些要点,fix ave/time就能成为你 LAMMPS 输出管线中可靠的时间平均引擎。
- 科研
- 科学计算
- 高性能计算
【免费下载链接】lammps
Public development project of the LAMMPS MD software package
相关推荐
LAMMPS fix ave/chunk 完全指南:基于 compute chunk/atom 的分块时间平均输出详解
LAMMPS fix ave/chunk 完全指南:基于 compute chunk/atom 的分块时间平均输出详解 fix ave/chunk 是 LAMM
科研科学计算高性能计算LAMMPS fix ave/grid 命令完全指南:分布式网格上的逐原子与逐网格量时间平均
LAMMPS fix ave/grid 命令完全指南:分布式网格上的逐原子与逐网格量时间平均 fix ave/grid 是 LAMMPS 中面向 分布式网格(d
科研科学计算高性能计算fix ave/atom 详解:LAMMPS 逐原子时间平均的完整指南
fix ave/atom 详解:LAMMPS 逐原子时间平均的完整指南 摘要 本文以 LAMMPS 官方文档 fix_ave_atom.rst https://
科研科学计算高性能计算
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考