Development build options
=========================

The build procedures in LAMMPS offers a few extra options which are
useful during development, testing or debugging.

----------

.. _compilation:

Monitor compilation flags (CMake only)
--------------------------------------

Sometimes it is necessary to verify the complete sequence of compilation flags
generated by the CMake build. To enable a more verbose output during
compilation you can use the following option.

.. code-block:: bash

   -D CMAKE_VERBOSE_MAKEFILE=value    # value = no (default) or yes

Another way of doing this without reconfiguration is calling make with
variable VERBOSE set to 1:

.. code-block:: bash

   make VERBOSE=1

----------

.. _clang-tidy:

Enable static code analysis with clang-tidy (CMake only)
--------------------------------------------------------

The `clang-tidy tool <https://clang.llvm.org/extra/clang-tidy/>`_ is a
static code analysis tool to diagnose (and potentially fix) typical
programming errors or coding style violations.  It has a modular framework
of tests that can be adjusted to help identifying problems before they
become bugs and also assist in modernizing large code bases (like LAMMPS).
It can be enabled for all C++ code with the following CMake flag

.. code-block:: bash

   -D ENABLE_CLANG_TIDY=value    # value = no (default) or yes

With this flag enabled all source files will be processed twice, first to
be compiled and then to be analyzed. Please note that the analysis can be
significantly more time consuming than the compilation itself.

----------

.. _iwyu_processing:

Report missing and unneeded '#include' statements (CMake only)
--------------------------------------------------------------

The conventions for how and when to use and order include statements in
LAMMPS are documented in :doc:`Modify_style`.  To assist with following
these conventions one can use the `Include What You Use tool <https://include-what-you-use.org/>`_.
This tool is still under development and for large and complex projects like LAMMPS
there are some false positives, so suggested changes need to be verified manually.
It is recommended to use at least version 0.16, which has much fewer incorrect
reports than earlier versions.  To install the IWYU toolkit, you need to have
the clang compiler **and** its development package installed.  Download the IWYU
version that matches the version of the clang compiler, configure, build, and
install it.

The necessary steps to generate the report can be enabled via a CMake variable
during CMake configuration.

.. code-block:: bash

   -D ENABLE_IWYU=value    # value = no (default) or yes

This will check if the required binary (include-what-you-use or iwyu)
and python script script (iwyu-tool or iwyu_tool or iwyu_tool.py) can
be found in the path.  The analysis can then be started with:

.. code-block:: bash

   make iwyu

This may first run some compilation, as the analysis is dependent
on recording all commands required to do the compilation.

----------

.. _sanitizer:

Address, Undefined Behavior, and Thread Sanitizer Support (CMake only)
----------------------------------------------------------------------

Compilers such as GCC and Clang support generating instrumented binaries
which use different sanitizer libraries to detect problems in the code
during run-time. They can detect issues like:

 - `memory leaks <https://clang.llvm.org/docs/AddressSanitizer.html#memory-leak-detection>`_
 - `undefined behavior <https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html>`_
 - `data races <https://clang.llvm.org/docs/ThreadSanitizer.html>`_

Please note that this kind of instrumentation usually comes with a
performance hit (but much less than using tools like `Valgrind
<https://valgrind.org>`_ with a more low level approach).  To enable
these features, additional compiler flags need to be added to the
compilation and linking stages.  This is done through setting the
``ENABLE_SANITIZER`` variable during configuration. Examples:

.. code-block:: bash

   -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

----------

.. _testing:

Code Coverage and Unit Testing (CMake only)
-------------------------------------------

The LAMMPS code is subject to multiple levels of automated testing
during development: integration testing (i.e. whether the code compiles
on various platforms and with a variety of settings), unit testing
(i.e. whether certain individual parts of the code produce the expected
results for given inputs), run testing (whether selected complete input
decks run without crashing for multiple configurations), and regression
testing (i.e. whether selected input examples reproduce the same
results over a given number of steps and operations within a given
error margin).  The status of this automated testing can be viewed on
`https://ci.lammps.org <https://ci.lammps.org>`_.

The scripts and inputs for integration, run, and regression testing
are maintained in a
`separate repository <https://github.com/lammps/lammps-testing>`_
of the LAMMPS project on GitHub.

The unit testing facility is integrated into the CMake build process
of the LAMMPS source code distribution itself.  It can be enabled by
setting ``-D ENABLE_TESTING=on`` during the CMake configuration step.
It requires the `YAML <http://pyyaml.org/>`_ library and development
headers (if those are not found locally a recent version will be
downloaded and compiled along with LAMMPS and the test program) to
compile and will download and compile a specific recent version of the
`Googletest <https://github.com/google/googletest/>`_ C++ test framework
for implementing the tests.

After compilation is complete, the unit testing is started in the build
folder using the ``ctest`` command, which is part of the CMake software.
The output of this command will be looking something like this::

   [...]$ ctest
   Test project /home/akohlmey/compile/lammps/build-testing
         Start  1: MolPairStyle:hybrid-overlay
   1/109 Test  #1: MolPairStyle:hybrid-overlay .........   Passed    0.02 sec
         Start  2: MolPairStyle:hybrid
   2/109 Test  #2: MolPairStyle:hybrid .................   Passed    0.01 sec
         Start  3: MolPairStyle:lj_class2
    [...]
         Start 107: PotentialFileReader
 107/109 Test #107: PotentialFileReader ................   Passed    0.04 sec
         Start 108: EIMPotentialFileReader
 108/109 Test #108: EIMPotentialFileReader .............   Passed    0.03 sec
         Start 109: TestSimpleCommands
 109/109 Test #109: TestSimpleCommands .................   Passed    0.02 sec

   100% tests passed, 0 tests failed out of 26

   Total Test time (real) =  25.57 sec


The ``ctest`` command has many options, the most important ones are:

.. list-table::

   * - 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>
   * - -N
     - dry-run: display list of tests without running them
   * - -T memcheck
     - run tests with valgrind memory checker (if available)

In its full implementation, the unit test framework will consist of multiple
kinds of tests implemented in different programming languages (C++, C, Python,
Fortran) and testing different aspects of the LAMMPS software and its features.
The tests will adapt to the compilation settings of LAMMPS, so that tests
will be skipped if prerequisite features are not available in LAMMPS.

.. note::

   The unit test framework was added in spring 2020 and is under active
   development.  The coverage is not complete and will be expanded over
   time.

Tests for styles of the same kind of style (e.g. pair styles or bond
styles) are performed with the same test executable using different
input files in YAML format.  So to add a test for another style of the
same kind it may be sufficient to add a suitable YAML file.
:doc:`Detailed instructions for adding tests <Developer_unittest>` are
provided in the Programmer Guide part of the manual.

Unit tests for force styles
^^^^^^^^^^^^^^^^^^^^^^^^^^^

A large part of LAMMPS are different "styles" for computing non-bonded
and bonded interactions selected through the :doc:`pair_style`,
:doc:`bond_style`, :doc:`angle_style`, :doc:`dihedral_style`,
:doc:`improper_style`, and :doc:`kspace_style`.  Since these all share
common interfaces, it is possible to write generic test programs that
will call those common interfaces for small test systems with less than
100 atoms and compare the results with pre-recorded reference results.
A test run is then a a collection multiple individual test runs each
with many comparisons to reference results based on template input
files, individual command settings, relative error margins, and
reference data stored in a YAML format file with ``.yaml``
suffix. Currently the programs ``test_pair_style``, ``test_bond_style``, and
``test_angle_style`` are implemented.  They will compare forces, energies and
(global) stress for all atoms after a ``run 0`` calculation and after a
few steps of MD with :doc:`fix nve <fix_nve>`, each in multiple variants
with different settings and also for multiple accelerated styles. If a
prerequisite style or package is missing, the individual tests are
skipped.  All tests will be executed on a single MPI process, so using
the CMake option ``-D BUILD_MPI=off`` can significantly speed up testing,
since this will skip the MPI initialization for each test run.
Below is an example command and output:

.. parsed-literal::

   [tests]$ 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

In this particular case, 5 out of 6 sets of tests were conducted, the
tests for the ``lj/cut/opt`` pair style was skipped, since the tests
executable did not include it.  To learn what individual tests are performed,
you (currently) need to read the source code.  You can use code coverage
recording (see next section) to confirm how well the tests cover the code
paths in the individual source files.

The force style test programs have a common set of options:

.. list-table::

   * - 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

The ``ctest`` tool has no mechanism to directly pass flags to the individual
test programs, but a workaround has been implemented where these flags can be
set in an environment variable ``TEST_ARGS``. Example:

.. code-block:: bash

   env TEST_ARGS=-s ctest -V -R BondStyle

To add a test for a style that is not yet covered, it is usually best
to copy a YAML file for a similar style to a new file, edit the details
of the style (how to call it, how to set its coefficients) and then
run test command with either the *-g* and the replace the initial
test file with the regenerated one or the *-u* option.  The *-u* option
will destroy the original file, if the generation run does not complete,
so using *-g* is recommended unless the YAML file is fully tested
and working.

.. admonition:: Recommendations and notes for YAML files
   :class: note

   - The reference results should be recorded without any code
     optimization or related compiler flags enabled.
   - The ``epsilon`` parameter defines the relative precision with which
     the reference results must be met.  The test geometries often have
     high and low energy parts and thus a significant impact from
     floating-point math truncation errors is to be expected. Some
     functional forms and potentials are more noisy than others, so this
     parameter needs to be adjusted. Typically a value around 1.0e-13
     can be used, but it may need to be as large as 1.0e-8 in some
     cases.
   - The tests for pair styles from OPT, OPENMP and INTEL are
     performed with automatically rescaled epsilon to account for
     additional loss of precision from code optimizations and different
     summation orders.
   - When compiling with (aggressive) compiler optimization, some tests
     are likely to fail.  It is recommended to inspect the individual
     tests in detail to decide, whether the specific error for a specific
     property is acceptable (it often is), or this may be an indication
     of mis-compiled code (or an undesired large loss of precision due
     to significant reordering of operations and thus less error cancellation).

Unit tests for timestepping related fixes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A substantial subset of :doc:`fix styles <fix>` are invoked regularly
during MD timestepping and manipulate per-atom properties like
positions, velocities, and forces.  For those fix styles, testing can be
done in a very similar fashion as for force fields and thus there is a
test program `test_fix_timestep` that shares a lot of code, properties,
and command line flags with the force field style testers described in
the previous section.

This tester will set up a small molecular system run with verlet run
style for 4 MD steps, then write a binary restart and continue for
another 4 MD steps. At this point coordinates and velocities are
recorded and compared to reference data. Then the system is cleared,
restarted and running the second 4 MD steps again and the data is
compared to the same reference. That is followed by another restart
after which per atom type masses are replaced with per-atom masses and
the second 4 MD steps are repeated again and compared to the same
reference.  Also global scalar and vector data of the fix is recorded
and compared.  If the fix is a thermostat and thus the internal property
``t_target`` can be extracted, then this is compared to the reference
data.  The tests are repeated with the respa run style.

If the fix has a multi-threaded version in the OPENMP package, then
the entire set of tests is repeated for that version as well.

For this to work, some additional conditions have to be met by the
YAML format test inputs.

- The fix to be tested (and only this fix), should be listed in the
  ``prerequisites:`` section
- The fix to be tested must be specified in the ``post_commands:``
  section with the fix-ID ``test``.  This section may contain other
  commands and other fixes (e.g. an instance of fix nve for testing
  a thermostat or force manipulation fix)
- For fixes that can tally contributions to the global virial, the
  line ``fix_modify test virial yes`` should be included in the
  ``post_commands:`` section of the test input.
- For thermostat fixes the target temperature should be ramped from
  an arbitrary value (e.g. 50K) to a pre-defined target temperature
  entered as ``${t_target}``.
- For fixes that have thermostatting support included, but do not
  have it enabled in the input (e.g. fix rigid with default settings),
  the ``post_commands:`` section should contain the line
  ``variable t_target delete`` to disable the target temperature ramp
  check to avoid false positives.

Use custom linker for faster link times when ENABLE_TESTING is active
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When compiling LAMMPS with enabled tests, most test executables will
need to be linked against the LAMMPS library.  Since this can be a very
large library with many C++ objects when many packages are enabled, link
times can become very long on machines that use the GNU BFD linker (e.g.
Linux systems).  Alternatives like the ``lld`` linker of the LLVM project
or the ``gold`` linker available with GNU binutils can speed up this step
substantially. CMake will by default test if any of the two can be
enabled and use it when ``ENABLE_TESTING`` is active.  It can also be
selected manually through the ``CMAKE_CUSTOM_LINKER`` CMake variable.
Allowed values are ``lld``, ``gold``, ``bfd``, or ``default``.  The
``default`` option will use the system default linker otherwise, the
linker is chosen explicitly.  This option is only available for the
GNU or Clang C++ compiler.

Tests for other components and utility functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Additional tests that validate utility functions or specific components
of LAMMPS are implemented as standalone executable which may, or may not
require creating a suitable LAMMPS instance.  These tests are more specific
and do not require YAML format input files.  To add a test, either an
existing source file needs to be extended or a new file added, which in turn
requires additions to the ``CMakeLists.txt`` file in the source folder.

Collect and visualize code coverage metrics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You can also collect code coverage metrics while running LAMMPS or the
tests by enabling code coverage support during the CMake configuration:

.. code-block:: bash

   -D ENABLE_COVERAGE=on  # enable coverage measurements (off by default)

This will instrument all object files to write information about which
lines of code were accessed during execution in files next to the
corresponding object files.  These can be post-processed to visually
show the degree of coverage and which code paths are accessed and which
are not taken.  When working on unit tests (see above), this can be
extremely helpful to determine which parts of the code are not executed
and thus what kind of tests are still missing. The coverage data is
cumulative, i.e. new data is added with each new run.

Enabling code coverage will also add the following build targets to
generate coverage reports after running the LAMMPS executable or the
unit tests:

.. code-block:: bash

   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

These reports require `GCOVR <https://gcovr.com/>`_ to be installed. The easiest way
to do this to install it via pip:

.. code-block:: bash

   pip install git+https://github.com/gcovr/gcovr.git

After post-processing with ``gen_coverage_html`` the results are in
a folder ``coverage_html`` and can be viewed with a web browser.
The images below illustrate how the data is presented.

.. list-table::

      * - .. figure:: JPG/coverage-overview-top.png
             :scale: 25%

          Top of the overview page

        - .. figure:: JPG/coverage-overview-manybody.png
             :scale: 25%

          Styles with good coverage

        - .. figure:: JPG/coverage-file-top.png
             :scale: 25%

          Top of individual source page

        - .. figure:: JPG/coverage-file-branches.png
             :scale: 25%

          Source page with branches

Coding style utilities
----------------------

To aid with enforcing some of the coding style conventions in LAMMPS
some additional build targets have been added. These require Python 3.5
or later and will only work properly on Unix-like operating and file systems.

The following options are available.

.. code-block:: bash

   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-permissions   # search for files with permissions issues
   make fix-permissions     # correct permissions issues in files

These should help to replace all TAB characters with blanks and remove
any trailing whitespace.  Also all LAMMPS homepage URL references can be
updated to the location change from Sandia to the lammps.org domain.
And the permission check can remove executable permissions from non-executable
files (like source code).

Clang-format support
--------------------

For the code in the ``unittest`` and ``src`` trees we are transitioning
to use the `clang-format` tool to assist with having a consistent source
code formatting style.  The `clang-format` command bundled with Clang
version 8.0 or later is required.  The configuration is in files called
``.clang-format`` in the respective folders.  Since the modifications
from `clang-format` can be significant and - especially for "legacy
style code" - they are not always improving readability, a large number
of files currently have a ``// clang-format off`` at the top, which will
disable the processing.  As of fall 2021 all files have been either
"protected" this way or are enabled for full or partial `clang-format`
processing.  Over time, the "protected" files will be refactored and
updated so that `clang-format` may be applied to them as well.

It is recommended for all newly contributed files to use the clang-format
processing while writing the code or do the coding style processing
(including the scripts mentioned in the previous paragraph)

If `clang-format` is available, files can be updated individually with
commands like the following:

.. code-block:: bash

   $ clang-format -i some_file.cpp


The following target are available for both, GNU make and CMake:

.. code-block:: bash

   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
