LAMMPS插件的编写

LAMMPS 的插件真有趣,可以让我们在 LAMMPS 的程序中使用自己的函数。(后半句是 Github copilot 说的,我不信 ×

在 LAMPPS 中使用 Plugin 的基础条件

需要在编译 LAMMPS 时包括 PLUGIN PACKAGE,通常可能会使用 most.cmake,most.cmake进行配置,如使用 intel 编译器编译时:

1
2
cd ${YOUR LAMMPS REPO DIR}/build
cmake -C ../cmake/presets/intel.cmake -C ../cmake/presets/most.cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=${YOUR LAMMPS INTSTALL TARGET DIR} -D LAMMPS_MACHINE=mpi -D LAMMPS_EXCEPTIONS=on -D BUILD_TOOLS=on -D BUILD_SHARED_LIBS=on -D Python_EXECUTABLE=/usr/bin/python3 ../cmake

在编译写好的 PLUGIN 时则需要链接到上述的 LAMMPS lib,如:

1
2
cd ${YOUR PLUGIN DIR}/build
cmake -C ${YOUR LAMMPS REPO DIR}/cmake/presets/intel.cmake -DLAMMPS_SOURCE_ROOT=${YOUR LAMMPS REPO DIR} -DLAMMPS_DIR=${YOUR LAMMPS INTSTALL TARGET DIR}/lib/cmake/LAMMPS ..

上述命令中涉及的目录:

  • ${YOUR LAMMPS REPO DIR}:LAMMPS 的源码目录,包括子目录src等;
  • ${YOUR LAMMPS INTSTALL TARGET DIR} :LAMMPS 的安装目录,包括子目录lib等;
  • ${YOUR PLUGIN DIR}:编写的 PLUGIN 的源码目录,包括核心的 CMakeLists.txt 等;

此时 CMakeLists.txt 大概这样:

参考了 deepmd-kit 的 lammps plugin 的CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
cmake_minimum_required(VERSION 3.0.0)
project(lammpsPluginTest VERSION 0.1.0)

if (DEFINED LAMMPS_SOURCE_ROOT OR DEFINED LAMMPS_VERSION)
message(STATUS "enable LAMMPS plugin mode")
add_library(lammpsPluginTest INTERFACE)
set(LAMMPS_HEADER_DIR ${LAMMPS_SOURCE_ROOT}/src)
#message(STATUS "LAMMPS_HEADER_DIR is ${LAMMPS_HEADER_DIR}")
target_include_directories(lammpsPluginTest PUBLIC ${LAMMPS_HEADER_DIR})
find_package(LAMMPS)
target_link_libraries(lammpsPluginTest PRIVATE LAMMPS::lammps)

find_package(MPI)
if(MPI_FOUND)
set(LAMMPS_MPI_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS})
message(STATUS "LAMMPS_MPI_INCLUDE_DIRS is ${LAMMPS_MPI_INCLUDE_DIRS}")
message(STATUS "MPI_CXX_LIBRARIES
is ${MPI_CXX_LIBRARIES}")
message(STATUS "MPI_LIBRARIES
is ${MPI_LIBRARIES}")
target_link_libraries(lammpsPluginTest PRIVATE MPI::MPI_CXX)
else()
# Use LAMMPS serial mpi.h header
target_include_directories(lammpsPluginTest PRIVATE "${LAMMPS_HEADER_DIR}/STUBS")
endif()

set(LAMMPS_VERSION_NUMBER ${LAMMPS_VERSION_NUMBER} PARENT_SCOPE)
endif()

LAMMPS plugin 的原理

主要参考文档

LAMMPS 的程序流

lammps 执行时会根据输入文件的定义内容进行初始化、时间步迭代、结束三个主要执行阶段。

假如输入脚本没有问题,就会执行以下的流程:

初始化

初始化部分主要包括以下工作:

  • 初始化 LAMMPS 的环境,包括设置环境变量,加载库文件,加载编译器等;
  • 根据用户的输入文件,设置一些内部标志,即一些全局性的开关等;

时间步迭代

时间步迭代主要包括以下工作:

  1. 判断是否进行迭代,如果不进行迭代,则直接退出;迭代的条件可以包括:

    • 迭代次数;
    • 时间步长;
    • 时间步长是否达到最大值;
    • 是否达到终止条件;
    • 是否达到输出条件;
    • 是否达到输出文件大小上限;
    • 是否达到输出文件个数上限;
    • 是否达到时间上限;
  2. 迭代

    迭代环节由以下几个步骤组成:

    1. 每个时间步的初始化定义,例如更新一些速度、坐标等;
    2. 按照配置决定是否进行原子邻域列表的更新;
    3. 按照目前的原子邻域列表,重置原子受力为零,必要时调用有关的 fix;
    4. 调用 pair::compute()计算原子受力、必要时纳入对 bond、angle、dihedral、improper 的计算;以及长程库仑相互作用 kspace 等;
    5. 由于 LAMMPS 是并行的,因此实际计算原子受力时有部分原子的受力由其他 CPU 计算(ghost),因此需要将这部分力加和回来;(力的作用是相互的)
    6. 原子间的力计算完成后,还可以引入其他的力,例如由其他的 fix 计算的力(外力、SHAKE 等);并同时完成系综定义的最终速度更新;
    7. 此时完成了一个时间步,程序将进行必要的诊断和输出操作,输出也包括创建检查点文件;

退出

这个环节主要涉及内存释放和最终的输出操作。

基本概念

Pair

Pair 在 LAMMPS 中计算两个原子之间的力,也包括各类多体势能的计算。其关键且必须的方法有:

  • compute():计算力;
  • settings():读取输入脚本的参数;
  • coeff():设置 i,j pair 参数;
  • init_one():初始化 pair;
  • init_style():初始化 pair_style;
  • write_restart():写入 restart 文件;
  • read_restart():读取 restart 文件;
  • write_restart_settings():写入设置到 restart;
  • read_restart_settings():读取 restart 中的全局设置;
  • single():计算单个原子 pair 的 force/r 和 energy;
    等。具体可以参考文档

Fix

Fix 是 LAMMPS 中主要的操作粒子属性的类,可用于:

  • 修改粒子的位置、速度、力等属性;
  • 读取和写数据;
  • 添加和修改一些结构限制;
  • 调用外场和其他子系统的相互作用;
  • 保存用于后续分析的一些数据,例如有记忆的模拟等;
    如编写一个 Fix,可实现的方法参考文档

Bond, angle, dihedral, improper

是采用bond_style <> <>等形式调用的,其关键且必须的方法有:

  • compute():计算相互作用;
  • coeff():设置 i,j 相互作用参数;
  • write_restart():写入 restart 文件;
  • read_restart():读取 restart 文件;

对于 bond 还需要定义 equilibrium_distance();对于 angle 还需要 equilibrium_angle(),分别对应 SHAKE 的平衡位置。

bond 和 angle 均需要 single();用于单个键或键角的力或能量。具体可以参考文档

Compute

Compute 是 LAMMPS 中计算命令类,多用于各种标量和向量的计算,包括原子的动能等。

如编写一个 Compute,可以参考文档

Dump

Dump 用于保存数据,包括原子的位置、速度、力等。
如要自定义 Dump,应当参考文档实现:

  • write_header():写入文件头;
  • count():计算一个 processor 需要输出的行数;
  • pack():将一个 processor的数据写入缓冲区;
  • write_data():将缓冲区中的数据写入文件;

Kspace

计算长程库伦相互作用的类,参考文档

Minimization

进行能量最小化的类,参考文档

Region

定义几何区域的类,参考文档

Body

定义体粒子的类,参考文档

其他

命令

LAMMPS 的命令是由两个部分组成,第一部分是命令的名称,第二部分是参数,参数是由一个或多个字符串组成,每个字符串都是一个参数。

插件可以将命令注册到 LAMMPS,从而在 LAMMPS 中使用。此类命令主要有:

  • Fix