Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 46 additions & 37 deletions doc/src/Developer_code_design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,10 @@ I/O and output formatting
C-style stdio versus C++ style iostreams
========================================

LAMMPS uses the `stdio <https://en.cppreference.com/w/cpp/io/c.html>`
LAMMPS uses the `stdio <https://cppreference.com/w/cpp/io/c.html>`
library of the standard C library for reading from and writing to files
and console instead of C++ `iostreams
<https://en.cppreference.com/w/cpp/io.html>`_. This is mainly motivated
<https://cppreference.com/w/cpp/io.html>`_. This is mainly motivated
by better performance, better control over formatting, and less effort
to achieve specific formatting.

Expand All @@ -294,36 +294,43 @@ Furthermore, output should generally only be done by MPI rank 0
``logfile`` should use the :cpp:func:`utils::logmesg() convenience
function <LAMMPS_NS::utils::logmesg>`.

We discourage the use of `stringstreams
<https://en.cppreference.com/w/cpp/io/basic_stringstream.html>`_ because
the bundled {fmt} library and the customized tokenizer classes provide
the same functionality in a cleaner way with better performance. This
also helps maintain a consistent programming syntax with code from many
different contributors.

Formatting with the {fmt} library
===================================

The LAMMPS source code includes a copy of the `{fmt} library
<https://fmt.dev>`_, which is preferred over formatting with the
"printf()" family of functions. The primary reason is that it allows a
typesafe default format for any type of supported data. This is
particularly useful for formatting integers of a given size (32-bit or
64-bit) which may require different format strings depending on compile
time settings or compilers/operating systems. Furthermore, {fmt} gives
better performance, has more functionality, a familiar formatting syntax
that has similarities to ``format()`` in Python, and provides a facility
that can be used to integrate format strings and a variable number of
We strongly discourage the use of `stringstreams
<https://cppreference.com/w/cpp/io/basic_stringstream.html>`_ because
the bundled `{fmt} library <https://fmt.dev>`_ or the `C++ format
library <https://cppreference.com/w/cpp/utility/format.html>`_ (for
C++20 and later) and the customized tokenizer classes provide the same
functionality in a cleaner way with better performance. This also helps
maintain a consistent programming syntax with code from many different
contributors.

Formatting with the {fmt} library and std::format
=================================================

The LAMMPS source code currently includes a slightly modified copy of
the `{fmt} library <https://fmt.dev>`_, which is preferred over
formatting with the "printf()" family of functions. When compiling for
C++20 and later we switch to using the `C++ format library
<https://cppreference.com/w/cpp/utility/format.html>`_. The namespace
prefix currently remains ``fmt::`` through a small wrapper. In the
future, this will be switched to ``std::`` when LAMMPS requires the
C++20 standard as the minimum C++ standard. Thus only functionality
compatible with the C++ format library for C++20 is accepted. Using
``std::format`` requires a fully C++20 compatible compiler (e.g. GCC 13
and later, Clang 14 and later, or MSVC 16.10 and later) and we `use the
__cpp_lib_format feature test macro
<https://cppreference.com/w/cpp/utility/feature_test.html>`_ to confirm
the availability of ``std::format``.

The primary reason for this choice is that it allows a typesafe default
format for any type of supported data. This is particularly useful for
formatting integers of a given size (32-bit or 64-bit) which may require
different format strings depending on compile time settings or
compilers/operating systems. Furthermore, {fmt} gives better
performance, has more functionality, a familiar formatting syntax that
has similarities to ``format()`` in Python, and provides a facility that
can be used to integrate format strings and a variable number of
arguments into custom functions in a much simpler way than the varargs
mechanism of the C library. Finally, {fmt} has been included into the
C++20 language standard as ``std::format()``, so changes to adopt it are
future-proof, for as long as they are not using any extensions that are
not (yet) included into C++.

The long-term plan is to switch to using ``std::format()`` instead of
``fmt::format()`` when the minimum C++ standard required for LAMMPS will
be set to C++20. See the :ref:`basic build instructions <compile>` for
more details.
mechanism of the C library.

Formatted strings are frequently created by calling the
``fmt::format()`` function, which will return a string as a
Expand All @@ -334,15 +341,15 @@ choose the default format based on the data type of the argument.
Otherwise, the :cpp:func:`utils::print() <LAMMPS_NS::utils::print>`
function may be used instead of ``printf()`` or ``fprintf()``. The
equivalent `std::print() function
<https://en.cppreference.com/w/cpp/io/print.html>`_ will become
<https://cppreference.com/w/cpp/io/print.html>`_ will become
available in C++ 23. In addition, several LAMMPS output functions, that
originally accepted a single string as argument have been overloaded to
accept a format string with optional arguments as well (e.g.,
``Error::all()``, ``Error::one()``, :cpp:func:`utils::logmesg()
<LAMMPS_NS::utils::logmesg>`).

Summary of the {fmt} format syntax
==================================
Summary of the {fmt} format and std::format syntax
==================================================

The syntax of the format string is "{[<argument id>][:<format spec>]}",
where either the argument id or the format spec (separated by a colon
Expand Down Expand Up @@ -404,11 +411,13 @@ value, for example "{:{}d}" will consume two integer arguments, the
first will be the value shown and the second the minimum width.

For more details and examples, please consult the `{fmt} syntax
documentation <https://fmt.dev/latest/syntax/>`_ website. Since we
plan to eventually transition from {fmt} to using ``std::format()``
documentation <https://fmt.dev/latest/syntax/>`_ website or the
`corresponding C++ syntax reference
<https://cppreference.com/w/cpp/utility/format/spec.html>`_. Since
we plan to eventually transition from {fmt} to using ``std::format()``
of the C++ standard library, it is advisable to avoid using any
extensions beyond what the `C++20 standard offers
<https://en.cppreference.com/w/cpp/utility/format/format.html>`_.
<https://cppreference.com/w/cpp/utility/format/format.html>`_.

JSON format input and output
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
6 changes: 4 additions & 2 deletions doc/src/Developer_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,10 @@ all three signatures, the single string "Error message" may be replaced
with a format string using '{}' placeholders and followed by a variable
number of arguments, one for each placeholder. This format string and
the arguments are then handed for formatting to the `{fmt} library
<https://fmt.dev>`_ (which is bundled with LAMMPS) and thus allow
processing similar to the "format()" functionality in Python.
<https://fmt.dev>`_ (which is bundled with LAMMPS) or the `C++ format
library <https://cppreference.com/w/cpp/utility/format.html>`_ (for
C++20 and later) and thus allow processing similar to the "format()"
functionality in Python.

.. note::

Expand Down
4 changes: 2 additions & 2 deletions doc/src/Developer_platform.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ File and path functions and global constants

Since we are requiring C++17 to compile LAMMPS, you can also make use of
the functionality of the `C++ filesystem library
<https://en.cppreference.com/w/cpp/filesystem.html>`_. The following
<https://cppreference.com/w/cpp/filesystem.html>`_. The following
functions are in part convenience functions or emulate the behavior of
similar Python functions or Unix shell commands. Please note that the
you need to use the ``string()`` member function of the
`std::filesystem::path class
<https://en.cppreference.com/w/cpp/filesystem/path.html>`_ to get access
<https://cppreference.com/w/cpp/filesystem/path.html>`_ to get access
to the path as a C++ string class instance.

.. doxygenvariable:: filepathsep
Expand Down
2 changes: 1 addition & 1 deletion doc/src/Developer_unittest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ available:
- Tests for ``ArgInfo`` class used by LAMMPS
* - ``test_fmtlib.cpp``
- FmtLib
- Tests for ``fmtlib::`` functions used by LAMMPS
- Tests for ``{fmt}`` or ``std::format`` functions used by LAMMPS
* - ``test_math_eigen_impl.cpp``
- MathEigen
- Tests for ``MathEigen::`` classes and functions
Expand Down
3 changes: 3 additions & 0 deletions doc/src/Developer_utils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ and parsing files or arguments.
.. doxygenfunction:: trim_and_count_words
:project: progguide

.. doxygenfunction:: join
:project: progguide

.. doxygenfunction:: join_words
:project: progguide

Expand Down
13 changes: 9 additions & 4 deletions doc/src/Modify_requirements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,15 @@ so that one could look up the cause by reading the source code.

The new policy encourages more specific error messages that ideally
indicate the cause directly, and requiring no further lookup. This is
aided by the `{fmt} library <https://fmt.dev>`_ enabling Error class
methods that take a variable number of arguments and an error text that
will be treated like a {fmt} syntax format string. Error messages should
still preferably be kept to a single line or two lines at most.
aided by either the `{fmt} library <https://fmt.dev>`_ or the `C++
format library
<https://cppreference.com/w/cpp/utility/format.html>`_ (for C++20
and later) enabling :cpp:class:`LAMMPS_NS::Error` class methods that
take a variable number of arguments and an error text that will be
treated like a `C++ format string
<https://cppreference.com/w/cpp/utility/format/spec.html>`_. Error
messages should still preferably be kept to a single line or two lines
at most.

For more complex explanations or errors that have multiple possible
reasons, a paragraph should be added to the `Error_details` page with an
Expand Down
5 changes: 3 additions & 2 deletions doc/src/Modify_style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ Include files (varied)
derived from it), certain headers will *always* be included and thus
do not need to be explicitly specified. These are: `mpi.h`,
`cstddef`, `cstdio`, `cstdlib`, `string`, `utils.h`, `vector`,
`fmt/format.h`, `climits`, `cinttypes`. This also means any such file
can assume that `FILE`, `NULL`, and `INT_MAX` are defined.
`fmt/format.h` (or `format` when using C++20 and later), `climits`,
`cinttypes`. This also means any such file can assume that `FILE`,
`NULL`, and `INT_MAX` are defined.

- Class members variables should not be initialized in the header file,
but instead should be initialized either in the initializer list of
Expand Down
22 changes: 7 additions & 15 deletions src/APIP/pair_eam_fs_apip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "memory.h"
#include "potential_file_reader.h"

#include <cstring>

using namespace LAMMPS_NS;

/* ---------------------------------------------------------------------- */
Expand All @@ -46,12 +48,8 @@ void PairEAMFSAPIP::coeff(int narg, char **arg)

if (!allocated) allocate();

if (narg != 3 + atom->ntypes) error->all(FLERR, "Incorrect args for pair coefficients");

// insure I,J args are * *

if (strcmp(arg[0], "*") != 0 || strcmp(arg[1], "*") != 0)
error->all(FLERR, "Incorrect args for pair coefficients");
if (narg != 3 + atom->ntypes)
error->all(FLERR, "Number of element to type mappings does not match number of atom types");

// read EAM Finnis-Sinclair file

Expand Down Expand Up @@ -104,7 +102,7 @@ void PairEAMFSAPIP::coeff(int narg, char **arg)
}
}

if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients");
if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients" + utils::errorurl(21));
}

/* ----------------------------------------------------------------------
Expand Down Expand Up @@ -136,14 +134,8 @@ void PairEAMFSAPIP::read_file(char *filename)
error->one(FLERR, "Incorrect element names in EAM potential file");

file->elements = new char *[file->nelements];
for (int i = 0; i < file->nelements; i++) {
const std::string word = values.next_string();
const int n = word.length() + 1;
file->elements[i] = new char[n];
strcpy(file->elements[i], word.c_str());
}

//
for (int i = 0; i < file->nelements; i++)
file->elements[i] = utils::strdup(values.next_string());

if (he_flag)
values = reader.next_values(6);
Expand Down
2 changes: 2 additions & 0 deletions src/EFF/pair_eff_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
Contributing authors: Andres Jaramillo-Botero, Hai Xiao, Julius Su (Caltech)
------------------------------------------------------------------------- */

#include <cmath>

namespace LAMMPS_NS {

#define PAULI_RE 0.9
Expand Down
20 changes: 12 additions & 8 deletions src/EXTRA-DUMP/dump_dcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include "atom.h"
#include "domain.h"
#include "error.h"
#include "fmt/chrono.h"
#include "group.h"
#include "memory.h"
#include "output.h"
Expand Down Expand Up @@ -318,7 +317,7 @@ void DumpDCD::write_dcd_header(const char *remarks)
float out_float;
char title_string[200];
time_t t;
std::tm current_time;
struct tm *current_time;

int ntimestep = update->ntimestep;

Expand Down Expand Up @@ -350,14 +349,19 @@ void DumpDCD::write_dcd_header(const char *remarks)
fwrite_int32(fp,84);
fwrite_int32(fp,164);
fwrite_int32(fp,2);
strncpy(title_string,remarks,80);
title_string[79] = '\0';
// pad string with blanks and truncate at 80 chars
snprintf(title_string, sizeof(title_string),
"%s "
" ", remarks);
fwrite(title_string,80,1,fp);
t = time(nullptr);
current_time = fmt::localtime(t);
std::string s = fmt::format("REMARKS Created {:%d %B,%Y at %H:%M}", current_time);
memset(title_string,' ',81);
memcpy(title_string, s.c_str(), s.size());
current_time = localtime(&t);
// pad string with blanks and truncate at 80 chars
strftime(title_string, sizeof(title_string),
"REMARKS Created %d %B,%Y at %H:%M"
" "
" ",
current_time);
fwrite(title_string,80,1,fp);
fwrite_int32(fp,164);
fwrite_int32(fp,4);
Expand Down
2 changes: 2 additions & 0 deletions src/EXTRA-FIX/fix_addtorque_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "update.h"
#include "variable.h"

#include <cstring>

using namespace LAMMPS_NS;
using namespace FixConst;

Expand Down
1 change: 1 addition & 0 deletions src/GPU/pair_amoeba_gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "suffix.h"

#include <cmath>
#include <cstring>

using namespace LAMMPS_NS;
using namespace MathConst;
Expand Down
2 changes: 2 additions & 0 deletions src/INTEL/intel_preprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#include "lmptype.h"

#include <cmath>

#ifdef __INTEL_LLVM_COMPILER
#define USE_OMP_SIMD
#define __INTEL_COMPILER_BUILD_DATE __INTEL_LLVM_COMPILER
Expand Down
2 changes: 2 additions & 0 deletions src/INTEL/math_extra_intel.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#ifndef LMP_MATH_EXTRA_INTEL_H
#define LMP_MATH_EXTRA_INTEL_H

#include <cmath>

#define ME_quat_to_mat_trans(quat, mat) \
{ \
flt_t quat_w = quat.w; \
Expand Down
1 change: 1 addition & 0 deletions src/INTEL/pair_dpd_intel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "suffix.h"

#include <cmath>
#include <cstring>

#if defined(_OPENMP)
#include <omp.h>
Expand Down
1 change: 1 addition & 0 deletions src/INTEL/pppm_intel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "suffix.h"

#include <cmath>
#include <cstring>

#include "omp_compat.h"

Expand Down
9 changes: 3 additions & 6 deletions src/KIM/kim_interactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@
#include "modify.h"
#include "update.h"

#include "fmt/ranges.h"

#include <cstring>
#include <vector>

Expand Down Expand Up @@ -130,8 +128,7 @@ void KimInteractions::do_setup(int narg, char **arg)
if (simulatorModel) {
auto first_visit = input->variable->find("kim_update");
if (!fixed_types) {
std::string atom_type_sym_list =
fmt::format("{}", fmt::join(arg, arg + narg, " "));
std::string atom_type_sym_list = utils::join(std::vector(arg, arg + narg), " ");

std::string atom_type_num_list =
fmt::format("{}", species_to_atomic_no(arg[0]));
Expand Down Expand Up @@ -250,7 +247,7 @@ void KimInteractions::do_setup(int narg, char **arg)

auto cmd1 = fmt::format("pair_style kim {}", model_name);
auto cmd2 =
fmt::format("pair_coeff * * {}", fmt::join(arg, arg + narg, " "));
fmt::format("pair_coeff * * {}", utils::join(std::vector(arg, arg + narg), " "));

input->one(cmd1);
input->one(cmd2);
Expand Down Expand Up @@ -308,7 +305,7 @@ void KimInteractions::KIM_SET_TYPE_PARAMETERS(const std::string &input_line) con
if (((species[ia] == words[0]) && (species[ib] == words[1]))
|| ((species[ib] == words[0]) && (species[ia] == words[1])))
input->one(fmt::format("pair_coeff {} {} {}", ia + 1, ib + 1,
fmt::join(words.begin() + 2, words.end(), " ")));
utils::join(std::vector(words.begin() + 2, words.end()), " ")));
}
} else {
for (int ia = 0; ia < atom->ntypes; ++ia)
Expand Down
Loading