3. 构建 LAMMPS
3.11.开发构建选项
LAMMPS 中的构建过程提供了一些在开发、测试或调试期间有用的额外选项。
3.11.1.监视编译标志(仅限 CMake)
有时需要验证 CMake 构建生成的编译标志的完整序列。要在编译期间启用更详细的输出,可以使用以下选项。
-D CMAKE_VERBOSE_MAKEFILE=value # value = no (default) or yes
无需重新配置即可执行此操作的另一种方法是调用 make,并将变量 VERBOSE 设置为 1:
make VERBOSE=1
3.11.2.使用 clang-tidy 启用静态代码分析(仅限 CMake)
clang-tidy 工具是一种静态代码分析工具,用于诊断(并可能修复)典型的编程错误或编码风格违规。它有一个模块化的测试框架,可以进行调整,以帮助在问题变成错误之前识别问题,并帮助实现大型代码库(如 LAMMPS)的现代化。可以使用以下 CMake 标志为所有 C++ 代码启用它
-D ENABLE_CLANG_TIDY=value # value = no (default) or yes
启用此标志后,所有源文件将被处理两次,首先进行编译,然后进行分析。请注意,分析可能比编译本身更耗时。
3.11.3.报告缺失和不需要的“#include”语句(仅限 CMake)
LAMMPS 编程风格中记录了 LAMMPS 中如何、何时使用和排序 include 语句的约定。为了帮助遵循这些约定,可以使用“包括您使用的内容”工具。该工具仍在开发中,对于像 LAMMPS 这样的大型复杂项目,存在一些误报,因此建议的更改需要手动验证。建议至少使用0.16版本,该版本的错误报告比早期版本要少得多。要安装IWYU工具包,您需要安装clang编译器及其开发包。下载与 clang 编译器版本匹配的 IWYU 版本,配置、构建并安装它。
生成报告的必要步骤可以在 CMake 配置期间通过 CMake 变量启用。
-D ENABLE_IWYU=value # value = no (default) or yes
这将检查是否可以在路径中找到所需的二进制文件(include-what-you-use 或 iwyu)和 python 脚本脚本(iwyu-tool 或 iwyu_tool 或 iwyu_tool.py)。然后可以开始分析:
make iwyu
这可能首先运行一些编译,因为分析依赖于记录进行编译所需的所有命令。
3.11.4.地址、未定义行为和线程清理程序支持(仅限 CMake)
GCC 和 Clang 等编译器支持生成检测二进制文件,这些二进制文件使用不同的清理程序库来检测运行时代码中的问题。他们可以检测到以下问题:
内存泄漏
未定义的行为
数据竞赛
请注意,这种仪器通常会带来性能影响(但比使用 Valgrind 等具有更低级别方法的工具要少得多)。为了启用这些功能,需要将额外的编译器标志添加到编译和链接阶段。这是通过在配置期间设置 ENABLE_SANITIZER
变量来完成的。例子:
-D ENABLE_SANITIZER=none # no sanitizer active (default)
-D ENABLE_SANITIZER=address # enable address sanitizer / memory leak checker
-D ENABLE_SANITIZER=leak # enable memory leak checker (only)
-D ENABLE_SANITIZER=undefined # enable undefined behavior sanitizer
-D ENABLE_SANITIZER=thread # enable thread sanitizer
3.11.5.代码覆盖率和单元测试(仅限 CMake)
LAMMPS 代码在开发过程中要经过多个级别的自动化测试:
- 集成测试(即代码是否可以在各种平台上以及使用各种编译器和设置进行编译),
- 单元测试(即代码的某些函数或类是否针对给定输入产生预期结果),
- 运行测试(即所选输入卡组是否可以运行完成而不会因多种配置而崩溃),
- 回归测试(即选定的输入示例是否在给定误差范围内通过给定数量的步骤和操作重现相同的结果)。
可以在 https://ci.lammps.org 上查看此自动化测试的状态。
用于集成、运行和回归测试的脚本和输入保存在 GitHub 上 LAMMPS 项目的单独存储库中。一些测试也作为 GitHub Actions 运行,它们的配置文件位于 LAMMPS git 树的 .github/workflows/
文件夹中。
单元测试工具集成到 LAMMPS 源代码分发本身的 CMake 构建过程中。可以通过在 CMake 配置步骤中设置 -D ENABLE_TESTING=on
来启用它。它需要 YAML 库和匹配的开发标头进行编译(如果在本地找不到这些库,则将下载该库的最新版本并与 LAMMPS 和测试程序一起编译),并将下载并编译特定版本的 GoogleTest C++ 测试用于实施测试的框架。
软件版本和 LAMMPS 配置要求
测试框架的编译器和库版本要求比LAMMPS的主要部分更严格。例如,RHEL/CentOS 7.x(版本 4.8.x)的默认 GNU C++ 和 Fortran 编译器是不够的。 CMake 配置将尝试检测不兼容的版本,并跳过不兼容的测试或因错误而停止。此外,可用测试的数量将取决于已安装的 LAMMPS 软件包、开发环境、操作系统和配置设置。
编译完成后,使用 ctest
命令在 build 文件夹中启动单元测试,该命令是 CMake 软件的一部分。该命令的输出将如下所示:
$ ctest
Test project /home/akohlmey/compile/lammps/build-testing
Start 1: RunLammps
1/563 Test #1: RunLammps .......................................... Passed 0.28 sec
Start 2: HelpMessage
2/563 Test #2: HelpMessage ........................................ Passed 0.06 sec
Start 3: InvalidFlag
3/563 Test #3: InvalidFlag ........................................ Passed 0.06 sec
Start 4: Tokenizer
4/563 Test #4: Tokenizer .......................................... Passed 0.05 sec
Start 5: MemPool
5/563 Test #5: MemPool ............................................ Passed 0.05 sec
Start 6: ArgUtils
6/563 Test #6: ArgUtils ........................................... Passed 0.05 sec
[...]
Start 561: ImproperStyle:zero
561/563 Test #561: ImproperStyle:zero ................................. Passed 0.07 sec
Start 562: TestMliapPyUnified
562/563 Test #562: TestMliapPyUnified ................................. Passed 0.16 sec
Start 563: TestPairList
563/563 Test #563: TestPairList ....................................... Passed 0.06 sec
100% tests passed, 0 tests failed out of 563
Label Time Summary:
generated = 0.85 sec*proc (3 tests)
noWindows = 4.16 sec*proc (2 tests)
slow = 78.33 sec*proc (67 tests)
unstable = 28.23 sec*proc (34 tests)
Total Test time (real) = 132.34 sec
ctest
命令有很多选项,最重要的是:
Option | Function |
-V | verbose output: display output of individual test runs |
-j <num> | parallel run: run <num> tests in parallel |
-R <regex> | run subset of tests matching the regular expression <regex> |
-E <regex> | exclude subset of tests matching the regular expression <regex> |
-L <regex> | run subset of tests with a label matching the regular expression <regex> |
-LE <regex> | exclude subset of tests with a label matching the regular expression <regex> |
-N | dry-run: display list of tests without running them |
-T memcheck | run tests with valgrind memory checker (if available) |
在其完整实施过程中,单元测试框架将包括以不同编程语言(C++、C、Python、Fortran)实施的多种测试,并测试 LAMMPS 软件及其功能的不同方面。测试将适应 LAMMPS 的编译设置,因此,如果先决条件功能在 LAMMPS 中不可用,则将跳过测试。
ctest
程序所示的测试是 unittest
目录树中的 CMakeLists.txt
文件中定义的命令行。一些测试只是使用特定的命令行标志执行 LAMMPS 并检查屏幕上的输出是否有预期的内容。大量单元测试是使用 GoogleTest 框架并链接到 LAMMPS 库的特殊测试程序,用于测试单个函数或创建 LAMMPS 类实例、执行一个或多个命令并检查 LAMMPS 类层次结构内的数据。还有针对 LAMMPS 的 C 库、Fortran 和 Python 模块接口的测试。 Python 测试使用 Python“unittest”模块的方式与其他测试使用 GoogleTest 的方式类似。这些特殊的测试程序被构造为在内部执行多个单独的测试,并且每个测试都包含对内部数据按预期更改的多项检查(也称为断言)。
强制计算或修改样式(例如,非绑定和绑定交互的样式以及选定的修复程序)的测试是通过使用更通用的测试程序来运行的,该程序从 YAML 格式的文件中读取其输入。 YAML 文件提供了有关如何自定义测试程序以测试特定样式以及(如果需要)特定设置的信息。要添加另一种类似样式(例如新的配对样式)的测试,通常添加合适的 YAML 文件就足够了。手册的程序员指南部分提供了添加测试的详细说明。下面给出了测试期间发生的情况的描述。
力类型的单元测试
LAMMPS 的很大一部分是通过pair_style 命令、bond_style 命令、angle_style 命令、dihedral_style 命令、improperty_style 命令和 kspace_style 命令选择的用于计算非键和键相互作用的不同“样式”。由于这些都共享通用接口,因此可以编写通用测试程序,为少于 100 个原子的小型测试系统调用这些通用接口,并将结果与预先记录的参考结果进行比较。测试运行是多个单独测试运行的集合,每个测试运行与基于模板输入文件、单独命令设置、相对误差范围和存储在带有 .yaml
后缀的 YAML 格式文件中的参考数据的参考结果进行多次比较。目前已实现程序 test_pair_style
、 test_bond_style
、 test_angle_style
、 test_dihedral_style
和 test_improper_style
。他们将在 run 0
计算之后以及在使用修复 nve 进行 MD 的几个步骤之后比较所有原子的力、能量和(全局)应力,每个步骤都有不同设置的多个变体以及多个加速样式。如果缺少先决条件样式或包,则会跳过各个测试。所有强制样式测试都将在单个 MPI 进程上执行,因此使用 CMake 选项 -D BUILD_MPI=off
可以显着加快测试速度,因为这将跳过每次测试运行的 MPI 初始化。下面是一个示例命令和输出:
$ test_pair_style mol-pair-lj_cut.yaml
[==========] Running 6 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 6 tests from PairStyle
[ RUN ] PairStyle.plain
[ OK ] PairStyle.plain (24 ms)
[ RUN ] PairStyle.omp
[ OK ] PairStyle.omp (18 ms)
[ RUN ] PairStyle.intel
[ OK ] PairStyle.intel (6 ms)
[ RUN ] PairStyle.opt
[ SKIPPED ] PairStyle.opt (0 ms)
[ RUN ] PairStyle.single
[ OK ] PairStyle.single (7 ms)
[ RUN ] PairStyle.extract
[ OK ] PairStyle.extract (6 ms)
[----------] 6 tests from PairStyle (62 ms total)
[----------] Global test environment tear-down
[==========] 6 tests from 1 test suite ran. (63 ms total)
[ PASSED ] 5 tests.
[ SKIPPED ] 1 test, listed below:
[ SKIPPED ] PairStyle.opt
在这种特殊情况下,进行了 6 组测试中的 5 组,跳过 lj/cut/opt
对样式的测试,因为测试可执行文件不包含它。要了解执行哪些单独的测试,您(当前)需要阅读源代码。您可以使用代码覆盖率记录(请参阅下一节)来确认测试覆盖各个源文件中的代码路径的程度。
Option | Function |
-g <newfile> | regenerate reference data in new YAML file |
-u | update reference data in the original YAML file |
-s | print error statistics for each group of comparisons |
-v | verbose output: also print the executed LAMMPS commands |
ctest
工具没有直接将标志传递给各个测试程序的机制,但已经实现了一种解决方法,可以在环境变量
TEST_ARGS
中设置这些标志。例子:
env TEST_ARGS=-s ctest -V -R BondStyle
要添加尚未涵盖的样式的测试,通常最好将类似样式的 YAML 文件复制到新文件,编辑样式的详细信息(如何调用它,如何设置其系数)并然后使用 -g 运行测试命令,并使用重新生成的文件或 -u 选项替换初始测试文件。如果生成运行未完成,-u 选项将破坏原始文件,因此建议使用 -g,除非 YAML 文件经过充分测试并正常工作。
-LE
标志选择性地排除这些测试,或者使用
-L
标志选择这些测试。
- 应在未启用任何代码优化或相关编译器标志的情况下记录参考结果。
epsilon
参数定义参考结果必须满足的相对精度。测试几何结构通常具有高能和低能部分,因此浮点数学截断误差会产生重大影响。某些函数形式和势比其他函数形式和势的噪声更大,因此需要调整此参数。通常可以使用 1.0e-13 左右的值,但在某些情况下可能需要大至 1.0e-8。- OPT、OPENMP 和 INTEL 对类型的测试是使用自动重新调整的 epsilon 执行的,以考虑代码优化和不同求和顺序带来的额外精度损失。
- 当使用(积极的)编译器优化进行编译时,某些测试可能会失败。建议详细检查各个测试,以确定特定属性的特定错误是否可以接受(通常是),或者这可能表明代码编译错误(或由于显着地重新排序操作,从而减少错误取消)。
时间步长相关修复的单元测试
在 MD 时间步长期间定期调用修复样式的重要子集,并操纵每个原子的属性,例如位置、速度和力。对于这些修复样式,测试可以以与力场非常相似的方式完成,因此有一个测试程序 test_fix_timestep 与上一节中描述的力场样式测试器共享大量代码、属性和命令行标志。
该测试仪将设置一个小分子系统,以 verlet 运行方式运行 4 个 MD 步骤,然后编写二进制重新启动并继续执行另外 4 个 MD 步骤。此时,坐标和速度被记录并与参考数据进行比较。然后系统被清除、重新启动并再次运行第二个 4 MD 步骤,并将数据与相同的参考进行比较。随后再次重新启动,之后将每原子类型质量替换为每原子质量,并再次重复第二个 4 MD 步骤并与相同的参考进行比较。还记录并比较了修复的全局标量和矢量数据。如果修复是恒温器,因此可以提取内部属性 t_target
,则将其与参考数据进行比较。使用 respa 运行方式重复测试。
如果修复程序在 OPENMP 包中具有多线程版本,则也会针对该版本重复整套测试。
为此,YAML 格式测试输入必须满足一些附加条件。
- 要测试的修复(并且仅此修复)应在
prerequisites:
部分中列出 - 要测试的修复必须在
post_commands:
部分中使用修复 IDtest
指定。本节可能包含其他命令和其他修复(例如,用于测试恒温器或力操纵修复的修复 nve 实例) - 对于可以统计对全局维里贡献的修复,行
fix_modify test virial yes
应包含在测试输入的post_commands:
部分中。 - 对于恒温器修复,目标温度应从任意值(例如 50K)渐变到输入为
${t_target}
的预定义目标温度。 - 对于包含恒温支持但未在输入中启用的修复(例如,使用默认设置修复刚性),
post_commands:
部分应包含行variable t_target delete
来禁用目标温度斜坡检查以避免误报。
当 ENABLE_TESTING 处于活动状态时,使用自定义链接器可缩短链接时间
当编译启用测试的 LAMMPS 时,大多数测试可执行文件将需要链接到 LAMMPS 库。由于当启用许多包时,这可能是一个包含许多 C++ 对象的非常大的库,因此在使用 GNU BFD 链接器(例如 Linux 系统)的计算机上,链接时间可能会变得非常长。诸如 mold
链接器、LLVM 项目的 lld
链接器或 GNU binutils 提供的 gold
链接器等替代方案可以大大加快此步骤(按此顺序)。默认情况下,CMake 将测试是否可以启用这三个中的任何一个,并在 ENABLE_TESTING
处于活动状态时使用它。也可以通过 CMAKE_CUSTOM_LINKER
CMake 变量手动选择。允许的值为 mold
、 lld
、 gold
、 bfd
或 default
。 default
选项将使用系统默认链接器,否则将显式选择链接器。此选项仅适用于 GNU 或 Clang C++ 编译器。
其他组件和实用功能的测试
验证实用功能或 LAMMPS 特定组件的其他测试作为独立可执行文件实现,可能需要也可能不需要创建合适的 LAMMPS 实例。这些测试更加具体,不需要 YAML 格式的输入文件。要添加测试,需要扩展现有源文件或添加新文件,这又需要向源文件夹中的 CMakeLists.txt
文件添加内容。
收集并可视化代码覆盖率指标
您还可以在运行 LAMMPS 或测试时收集代码覆盖率指标,方法是在 CMake 配置期间启用代码覆盖率支持:
-D ENABLE_COVERAGE=on # enable coverage measurements (off by default)
这将检测所有目标文件,以将有关在执行期间访问哪些代码行的信息写入相应目标文件旁边的文件中。可以对它们进行后处理,以直观地显示覆盖程度以及访问哪些代码路径和未采用哪些代码路径。在进行单元测试时(见上文),这对于确定代码的哪些部分未执行以及仍然缺少哪种测试非常有帮助。覆盖率数据是累积的,即每次新运行都会添加新数据。
启用代码覆盖率还将添加以下构建目标,以在运行 LAMMPS 可执行文件或单元测试后生成覆盖率报告:
make gen_coverage_html # generate coverage report in HTML format
make gen_coverage_xml # generate coverage report in XML format
make clean_coverage_html # delete folder with HTML format coverage report
make reset_coverage # delete all collected coverage data and HTML output
这些报告需要安装 GCOVR。最简单的方法是通过 pip 安装它:
pip install git+https://github.com/gcovr/gcovr.git
使用 gen_coverage_html
进行后处理后,结果位于文件夹 coverage_html
中,可以使用网络浏览器查看。下图说明了数据的呈现方式。
Top of the overview page | Styles with good coverage | Top of individual source page | Source page with branches |
3.11.6.编码风格实用程序
为了帮助在 LAMMPS 中实施一些编码风格约定,添加了一些额外的构建目标。这些需要 Python 3.5 或更高版本,并且只能在类 Unix 操作系统和文件系统上正常工作。
可以使用以下选项。
make check-whitespace # search for files with whitespace issues
make fix-whitespace # correct whitespace issues in files
make check-homepage # search for files with old LAMMPS homepage URLs
make fix-homepage # correct LAMMPS homepage URLs in files
make check-errordocs # search for deprecated error docs in header files
make fix-errordocs # remove error docs in header files
make check-permissions # search for files with permissions issues
make fix-permissions # correct permissions issues in files
make check-docs # search for several issues in the manual
make check-version # list files with pending release version tags
make check # run all check targets from above
这些应该有助于使源文件和文档文件符合 LAMMPS 开发人员的某些编码风格偏好。
3.11.7. Clang 格式支持
对于 unittest
和 src
树中的代码,我们正在转换为使用 clang-format 工具来帮助保持一致的源代码格式样式。需要与 Clang 版本 8.0 或更高版本捆绑在一起的 clang-format 命令。配置位于相应文件夹中名为 .clang-format
的文件中。由于 clang-format 的修改可能很重要,而且 - 特别是对于“遗留样式代码” - 它们并不总是提高可读性,因此目前大量文件的顶部有一个 // clang-format off
,这将禁用加工。截至 2021 年秋季,所有文件都已通过这种方式“受到保护”,或者启用了全部或部分 clang 格式处理。随着时间的推移,“受保护”的文件将被重构和更新,以便 clang-format 也可以应用于它们。
建议所有新贡献的文件在编写代码时使用clang-format处理或者进行编码风格处理(包括上一段提到的脚本)
如果 clang-format 可用,则可以使用如下命令单独更新文件:
clang-format -i some_file.cpp
以下目标可用于 GNU make 和 CMake:
make format-src # apply clang-format to all files in src and the package folders
make format-tests # apply clang-format to all files in the unittest tree
3.11.8. GitHub 命令行界面
GitHub 正在开发一个命令行工具,通过名为 gh
的命令与 GitHub 网站进行交互。当使用 GitHub 上托管的 Git 存储库(如 LAMMPS)时,这非常方便。因此强烈建议在进行 LAMMPS 开发时安装它。
gh
命令的功能正在不断扩展,请参阅 https://cli.github.com/manual/ 上的文档