- 科研
- 科学计算
- 高性能计算
【免费下载链接】lammps
Public development project of the LAMMPS MD software package
本文以 LAMMPS 的fix ave/histo与fix ave/histo/weight命令为核心,完整覆盖其语法、输入值种类、时间参数、全部可选关键词、输出文件格式与默认值,并结合 fix_ave_histo.cpp 与 fix_ave_histo_weight.cpp 的实现源码以及 单元测试用例 深入剖析直方图的累加、并行归约与窗口平均机制。读完后你可以熟练使用该 fix 对原子属性、compute/fix 输出或变量值做长期统计,并理解其底层数据流与常见报错原因。
命令语法与参数总览
fix ave/histo与fix ave/histo/weight共用同一语法(详见 doc/src/fix_ave_histo.rst):
fix ID group-ID style Nevery Nrepeat Nfreq lo hi Nbin value1 value2 ... keyword args ...ID、group-ID:含义同 fix 通用语法;style:ave/histo或ave/histo/weight;Nevery:每隔多少个时间步采样一次输入值;Nrepeat:用多少个采样值参与本次直方图统计(即在Nfreq窗口内重复采样的次数);Nfreq:每隔多少个时间步生成一次最终直方图;lo、hi:直方图的分箱上下界;Nbin:直方图 bin 数;value1 value2 ...:一个或多个输入值,可以是x、y、z、vx、vy、vz、fx、fy、fz、c_ID、c_ID[N]、f_ID、f_ID[N]、v_name、v_name[I]:x,y,z,vx,vy,vz,fx,fy,fz:原子属性(位置、速度、力的分量);c_ID:compute 的标量或向量;c_ID[I]:向量第 I 个分量或数组第 I 列,I 可含通配符;f_ID:fix 的标量或向量;f_ID[I]:同理;v_name:equal 型、vector 型或 atom 型变量;v_name[I]:vector 型变量的第 I 个值。
官方文档给出的示例(可直接复制):
fix 1 all ave/histo 100 5 1000 0.5 1.5 50 c_myTemp file temp.histo ave running fix 1 all ave/histo 100 5 1000 -5 5 100 c_thermo_press[2] c_thermo_press[3] title1 "My output values" fix 1 all ave/histo 100 5 1000 -5 5 100 c_thermo_press[*] fix 1 all ave/histo 1 100 1000 -2.0 2.0 18 vx vy vz mode vector ave running beyond extra fix 1 all ave/histo/weight 1 1 1 10 100 2000 c_XRD[1] c_XRD[2]从源码构造器 FixAveHisto::FixAveHisto 可以看到,该 fix 声明了global_freq = nfreq、size_vector = 4、size_array_cols = 3,即它对外暴露一个 4 分量的全局向量和一个 Nbin 行 × 3 列的全局数组(见后文“输出与可访问数据”一节);同时设置time_dependend = 1、dynamic_group_allow = 1,意味着允许在运行中改变原子分组,也意味着其计算结果依赖时间步。
输入值的种类、分组与 mode/kind 语义
直方图本质上是对落入每个 bin 的值做计数。Nbin个 bin 在lo到hi之间等间距排布,bin 中心坐标由 源码初始化逻辑 计算为lo + (i+0.5)*binsize(binsize = (hi-lo)/Nbin)。超出lo/hi的值如何处理由beyond关键词决定。
每个输入值可以是:
- 原子属性(
x/v/f分量)——属于 per-atom 向量值; - compute 结果(
c_前缀)——可以是全局标量/向量/数组,也可以是 per-atom 或 local 数据; - fix 结果(
f_前缀)——同上; - 变量(
v_前缀)——equal/vector 型产生全局值,atom 型产生 per-atom 向量。
输入值集合必须全部属于同一 kind:global、per-atom 或 local,不允许混合。若某个 compute 或 fix 能产生多种 kind 的数据而 LAMMPS 无法无歧义地判断,就必须用kind关键词强制指定。注意:该命令的group-ID只在 per-atom 输入时才有意义——只有分组内的原子贡献计数;global 与 local 输入时 group 被忽略。bin_atoms 实现 正是通过mask[i] & groupbit过滤分组外的原子。
mode关键词决定输入值形态:
mode scalar(默认):输入值必须是标量,或向量加分量下标c_ID[I]形式;mode vector:输入值必须是向量,或数组加列下标c_ID[I]形式。
从源码可看到严格的校验链(FixAveHisto 构造函数中的类型检查):
- scalar 模式下出现 per-atom 或 local 输入会直接报错:“cannot process per-atom values in scalar mode”;
- scalar 模式下
c_ID不带下标时该 compute 必须计算全局标量,带下标时必须计算全局向量且下标不越界; - vector 模式下
c_ID不带下标时该 compute 必须计算全局向量,带下标时必须计算全局数组且列号不越界; - 对
f_输入还额外检查nevery % fix->global_freq == 0,即引用的 fix 只在部分时间步产生值时,其频率必须与Nevery兼容,否则报错 “Fix ... not computed at compatible time”。
时间参数 Nevery / Nrepeat / Nfreq 的工作机制
Nfreq必须为Nevery的整数倍,且Nrepeat × Nevery ≤ Nfreq;即使Nrepeat = 1,Nevery也必须非零。这些约束在 源码中直接报错(“Inconsistent ... nevery/nrepeat/nfreq values”)。
以Nevery=2、Nrepeat=6、Nfreq=100为例:在时间步 100 生成最终直方图时,实际使用的是 90、92、94、96、98、100 这 6 个时间步的采样值;200 步时则使用 190~200 的采样。若Nrepeat=1、Nfreq=100,则不做时间平均,仅在 100、200、… 步各生成一个直方图。
从 end_of_step 与 nextvalid 的实现 可以推断出精确的调度逻辑:fix 通过setmask()注册END_OF_STEP回调,nextvalid()从当前时间步的下一个Nfreq整数倍向前回退(Nrepeat-1)*Nevery步,得到“本轮统计的第一次采样点”;之后每次采样后nvalid += Nevery推进,直到完成Nrepeat次采样才合并输出。start关键词会抬高首个Nfreq整数倍下界(默认 0),用于跳过初始阶段取值全为 0.0 的采样。
通配符下标与等价展开
compute/fix/variable 的方括号下标支持通配符*,形式为*、*n、m*、m*n:
*单独出现:取 1 到 N 的全部下标(scalar 模式 N 为向量长度,vector 模式 N 为数组列数);*n:取 1 到 n(含);m*:取 m 到 N(含);m*n:取 m 到 n(含)。
使用通配符与逐个列出分量等价。例如 compute com/chunk 产生 3 列全局数组,下面两条命令等价:
compute myCOM all com/chunk fix 1 all ave/histo 100 1 100 -10.0 10.0 100 c_myCOM[*] file tmp1.com mode vector fix 2 all ave/histo 100 1 100 -10.0 10.0 100 c_myCOM[1] c_myCOM[2] c_myCOM[3] file tmp2.com mode vector源码中这一展开由 utils::expand_args 在解析阶段完成,展开后的下标再逐个映射到value_t记录(ArgInfo解析类型与下标,见 值解析循环)。
注意:对 vector 型变量只允许*n或m*n两种形式——因为 vector 型变量的长度只有在求值时才确定,必须显式给出上界;若 n 大于实际长度,缺失位置按 0.0 输出(源码注释 明确说明“if index exceeds vector length, use a zero value”)。
输入值前缀详解:c_ / f_ / v_
c_前缀:c_ID必须引用输入脚本中已定义的 compute。scalar 模式下不带下标取全局标量,带下标取全局向量第 I 个元素;vector 模式下不带下标取全局/per-atom/local 向量,带下标取对应数组第 I 列。除输入脚本显式定义外,thermo 输出、fix nvt(见 fix_nh)或fix temp/rescale(见 fix_temp_rescale)等也会隐式创建 compute,其 ID 可在对应文档页查到;per-atom 量还可以先经 compute reduce 归约为全局标量/向量再被本 fix 访问。f_前缀:f_ID必须引用已定义的 fix。取值规则与c_相同,但 fix 的值可能只在特定时间步产生,必须与Nevery兼容(源码中每 4 类输入都做了nevery % global_freq检查,见 fix 频率校验)。v_前缀:变量名。scalar 模式只允许 equal 型或 vector 型(均为全局值),vector 型需加下标;vector 模式只允许 vector 型(全局向量,不加下标)或 atom 型(per-atom 向量,不加下标)。变量公式可引用原子属性、热力学关键词,或在求值时调用其他 compute/fix/变量,是表达待统计量最灵活的方式。
关键词详解
mode 与 kind
mode = scalar/vector,如上所述。kind = global/peratom/local仅在引用对象可产生多类输出时才需要显式指定;否则 LAMMPS 自动推断并校验所有输入 kind 一致,不一致即报错。从 源码校验逻辑 可见:kind默认值为DEFAULT,由第一个输入值确定,后续值必须与之匹配,否则抛出 “input kind is ambiguous” 或 “input kind is not global” 等错误。
beyond:越界值的三种处理
设lo ≤ value ≤ hi的值落入某个 bin;恰好位于 bin 边界的值归属靠下的那个 bin(源码 bin_one 中(value-lo)*bininv取整且截断到nbins-1实现了这一点)。
beyond ignore(默认):value < lo或value > hi的值不计入任何 bin,但会计入“未统计计数”(missing counts),且计入 min/max 统计;beyond end:越界值分别计入第一个和最后一个 bin;beyond extra:额外增加 2 个 bin,总 bin 数变为Nbin+2。value < lo计入第 1 个 bin,value > hi计入第Nbin+2个 bin,lo到hi之间的值计入第 2 到Nbin+1个 bin。两个额外 bin 的“坐标”分别打印为lo与hi(源码分配与坐标设置:if (beyond == EXTRA) nbins += 2,且coord[0]=lo、coord[nbins-1]=hi)。
ave:one / running / window
ave决定每次在Nfreq整数步生成的直方图如何与历史直方图合并后再对外输出:
ave one(默认):各直方图彼此独立,原样输出;ave running:对 fix 定义以来的所有Nfreq步直方图做累积平均。每个 bin 值是该步 bin 值与此前所有步同 bin 值的平均。运行平均从 fix 定义时开始,只能靠unfix删除后重新定义来重启(源码 RUNNING 分支 对bin_total逐 bin 累加,min 取MIN、max 取MAX);ave window M:在最近 M 个直方图的滑动窗口内求和。例如M=3、Nfreq=1000时,10000 步的输出是 8000、9000、10000 三步直方图的合并;早期步可用直方图不足 M 个,则对已有部分求和。
从 WINDOW 分支实现 可见,源码用一个容量为nwindow的循环缓冲bin_list/stats_list保存最近 M 份直方图:写入当前槽位前若窗口已满(window_limit)就先扣掉最旧一份,min/max 则在窗口内逐份扫描取极值。
file / append / overwrite / title1~3
file filename:指定输出文件,若已存在则覆盖;append filename:若已存在则追加,不存在则创建(该关键词于 17Apr2024 版新增);- 每
Nfreq步写一份直方图。源码中仅 rank 0 写文件(文件输出段),每份数据以一行头部开始:时间步、bin 数、参与统计的总计数、未统计计数、遇到的最小值、遇到的最大值——其中 min/max 包含未统计进直方图的值。随后每个 bin 一行:bin 编号、bin 中心坐标、计数、归一化计数(bin 计数 ÷ 总计数;不含 missing 值,因此归一化值跨 bin 求和为 1.0)。 overwrite:持续用最新输出覆盖文件,使文件只保留一个时间步的数据;只能与ave running联用(源码强制检查)。实现上先记录写完三行标题后的文件位置filepos,每次输出前fseek回该位置,写完后用ftruncate截断文件尾部。title1、title2、title3:自定义输出文件前三行标题,仅在用了file时生效。默认标题为:
# Histogrammed data for fix ID mode MODE ave AVE version VERSION # TimeStep Number-of-bins Total-counts Missing-counts Min-value Max-value # Bin Coord Count Count/Total其中ID替换为 fix-ID,MODE为scalar/vector,AVE为one/running/window,VERSION为 LAMMPS 版本号(如 20260930 表示 2026 年 9 月 30 日版)。这些默认串在 源码写文件头逻辑 中可直接对照。
start
start Nstart:从该时间步开始直方图统计,默认 0。由于很多输入值在 0 步时为 0.0,设置较大的start可避免 running/window 平均里混入这个 0.0。
fix ave/histo/weight:加权直方图
fix ave/histo/weight语法与fix ave/histo完全相同,但必须且只能指定恰好两个输入值:第一个值按通常方式分箱,第二个值作为“权重”——每个值不再是向所属 bin 累加 1,而是累加对应的权重;若两者是向量,则第二个向量的第 N 项作为权重累加到第一个向量第 N 项对应的 bin。典型用途如 XRD 计算中按各贡献加权统计(文档示例fix 1 all ave/histo/weight 1 1 1 10 100 2000 c_XRD[1] c_XRD[2])。
从 FixAveHistoWeight 构造函数 可确认两个硬性检查:nvalues != 2直接报错 “must have two data arguments”;随后按 kind/mode 分别推算两个输入的长度(per-atom 输入取atom->nlocal,global 向量取size_vector,local 取size_local_rows等),长度不一致则报错 “value and weight vector lengths do not match”。
计数逻辑的差异集中在 bin_one_weights:与基类bin_one逐行对应,只是所有+= 1.0变为+= weight——包括越界值在ignore模式下的 missing 计数、extra额外 bin 的坐标处理规则完全一致。因此前文所述beyond、ave、文件输出等机制对该变体全部适用。
并行环境下的归约机制
这是理解 per-atom/local 输入正确性的关键:per-atom 数据被 MPI 切分到各进程,因此每个进程先统计本地原子的直方图,再在 end_of_step 的归约段 做MPI_Allreduce:
- 总计数与 missing 计数用
MPI_SUM; - min 值用
MPI_MIN、max 值用MPI_MAX; - 每个 bin 的计数用
MPI_SUM。
global 与 local 输入则不需要跨进程归约(local 数据已包含本进程负责的全部区域,且统计量在全局一致)。weight 变体在 其 end_of_step 中复用相同的归约方式。
输出与可访问数据
该 fix 产生一个全局向量和一个全局数组,可被其他输出命令(如thermo、variable、dump等,见 Howto_output)访问,且只能在Nfreq整数步访问(因为此时才有直方图)。
- 全局向量共 4 个值:1) 直方图总计数;2) 未统计进直方图的值数(与
beyond相关);3) 所有输入值的最小值(含未统计的);4) 所有输入值的最大值(含未统计的)。对应 compute_vector 返回stats_total[i]; - 全局数组共
Nbin行(beyond extra时为Nbin+2)3 列:第 1 列 bin 坐标、第 2 列该 bin 计数、第 3 列 bin 计数除以总计数(不含 missing),因此第 3 列跨行求和为 1.0。对应 compute_array。
单元测试 验证了这一点:对 29 个原子、20 个 bin 的vx分量做mode vector统计后,global_vector的第一个值 145 = 29 原子 × 5 次采样,第二值为 0(无 missing),第三、四值为速度 min/max;global_array恰好 20 行、每行 3 列,且只有 -0.1 与 0.1 两个 bin 有计数(62 + 83 = 145),归一化值 0.4276 + 0.5724 = 1.0,与实现严格一致。
注意:该 fix 的向量与数组值均被视为“强度量”(intensive)。若你统计的是 per-atom 输入(如每原子速度),实际计数会随原子数变化,解释结果时必须自行考虑这一放大效应。
Restart、fix_modify、run start/stop 与 minimize
- 无 restart 信息:该 fix 不向二进制 restart 文件写入任何状态(restart 文档),从 restart 恢复后统计从头累积;
- fix_modify 无关:任何 fix_modify 选项均不适用于该 fix;
- run 的 start/stop 关键词:该 fix 的任何参数都不能与 run 的 start/stop 联用;
- 能量最小化期间不会被调用(见 minimize)。
默认值与限制
| 选项 | 默认值 |
|---|---|
| mode | scalar |
| kind | 由输入参数自动推断 |
| ave | one |
| start | 0 |
| file/append | 无文件输出 |
| beyond | ignore |
| title1/2/3 | 上述三行默认标题 |
| overwrite | 关闭 |
文档中 Restrictions 一节明确写着 “none”,即无额外限制;但实际使用中需牢记前文所述的 kind 一致性、mode 与输入类别匹配、fix 频率与Nevery兼容等由源码强制执行的约束。
相关命令
与 compute、fix ave/atom、fix ave/chunk、fix ave/time、variable、fix ave/correlate 同属时间统计类命令:fix ave/time对标量/向量做时间平均,fix ave/histo则回答“值落在哪个区间、占多大比例”这一分布问题,二者常配合使用;对单个直方图文件后处理时,建议用beyond extra或检查 missing 计数以确认统计范围是否覆盖了关心的值域。
- 科研
- 科学计算
- 高性能计算
【免费下载链接】lammps
Public development project of the LAMMPS MD software package
相关推荐
LAMMPS 中 fix ave/correlate 命令详解:时间关联函数的计算原理、参数配置与源码实现
LAMMPS 中 fix ave/correlate 命令详解:时间关联函数的计算原理、参数配置与源码实现 fix ave/correlate 是 LAMMPS
科研科学计算高性能计算Go Web 开发数据库实战:从 database/sql 驱动接口到 SQL/NoSQL 全栈方案(Build Web Application with Golang 第 5 章)
Go Web 开发数据库实战:从 database/sql 驱动接口到 SQL/NoSQL 全栈方案(Build Web Application with Go
科研科学计算高性能计算LAMMPS 磁自旋 GNEB 计算:fix neb/spin 命令详解与源码级原理剖析
LAMMPS 磁自旋 GNEB 计算:fix neb/spin 命令详解与源码级原理剖析 导读 fix neb/spin 是 LAMMPS SPIN 包中专用于
科研科学计算高性能计算
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考