Merge pull request #3179 from akohlmey/thermo-refactor-plus-yaml

Refactoring of Thermo class and new thermo style yaml
This commit is contained in:
Axel Kohlmeyer
2022-03-22 20:17:25 -04:00
committed by GitHub
19 changed files with 1096 additions and 1096 deletions

View File

@ -21,7 +21,8 @@ YAML
print """--- print """---
timestep: $(step) timestep: $(step)
pe: $(pe) pe: $(pe)
ke: $(ke)""" file current_state.yaml screen no ke: $(ke)
...""" file current_state.yaml screen no
.. code-block:: yaml .. code-block:: yaml
:caption: current_state.yaml :caption: current_state.yaml
@ -51,6 +52,58 @@ JSON
"ke": 2.4962152903997174569 "ke": 2.4962152903997174569
} }
YAML format thermo_style output
===============================
.. versionadded:: 24Mar2022
LAMMPS supports the thermo style "yaml" and for "custom" style
thermodynamic output the format can be changed to YAML with
:doc:`thermo_modify line yaml <thermo_modify>`. This will produce a
block of output in a compact YAML format - one "document" per run - of
the following style:
.. code-block:: yaml
---
keywords: [Step, Temp, E_pair, E_mol, TotEng, Press, ]
data:
- [100, 0.757453103239935, -5.7585054860159, 0, -4.62236133677021, 0.207261053624721, ]
- [110, 0.759322359337036, -5.7614668389562, 0, -4.62251889318624, 0.194314975399602, ]
- [120, 0.759372342462676, -5.76149365656489, 0, -4.62247073844943, 0.191600048851267, ]
- [130, 0.756833027516501, -5.75777334823494, 0, -4.62255928350835, 0.208792327853067, ]
...
This data can be extracted and parsed from a log file using python with:
.. code-block:: python
import re, yaml
docs = ""
with open("log.lammps") as f:
for line in f:
m = re.search(r"^(keywords:.*$|data:$|---$|\.\.\.$| - \[.*\]$)", line)
if m: docs += m.group(0) + '\n'
thermo = list(yaml.load_all(docs, Loader=yaml.SafeLoader))
print("Number of runs: ", len(thermo))
print(thermo[1]['keywords'][4], ' = ', thermo[1]['data'][2][4])
After loading the YAML data, `thermo` is a list containing a dictionary
for each "run" where the tag "keywords" maps to the list of thermo
header strings and the tag "data" has a list of lists where the outer
list represents the lines of output and the inner list the values of the
columns matching the header keywords for that step. The second print()
command for example will print the header string for the fifth keyword
of the second run and the corresponding value for the third output line
of that run:
.. parsed-literal::
Number of runs: 2
TotEng = -4.62140097780047
Writing continuous data during a simulation Writing continuous data during a simulation
=========================================== ===========================================

View File

@ -1,27 +1,54 @@
Thermodynamic output options Thermodynamic output options
============================ ============================
There is one class that computes and prints thermodynamic information The ``Thermo`` class computes and prints thermodynamic information to
to the screen and log file; see the file thermo.cpp. the screen and log file; see the files ``thermo.cpp`` and ``thermo.h``.
There are two styles defined in thermo.cpp: "one" and "multi". There There are four styles defined in ``thermo.cpp``: "one", "multi", "yaml",
is also a flexible "custom" style which allows the user to explicitly and "custom". The "custom" style allows the user to explicitly list
list keywords for quantities to print when thermodynamic info is keywords for individual quantities to print when thermodynamic output is
output. See the :doc:`thermo_style <thermo_style>` command for a list generated. The others have a fixed list of keywords. See the
of defined quantities. :doc:`thermo_style <thermo_style>` command for a list of available
quantities. The formatting of the "custom" style defaults to the "one"
style, but can be adapted using :doc:`thermo_modify line <thermo_modify>`.
The thermo styles (one, multi, etc) are simply lists of keywords. The thermo styles (one, multi, etc) are defined by lists of keywords
Adding a new style thus only requires defining a new list of keywords. with associated formats for integer and floating point numbers and
Search for the word "customize" with references to "thermo style" in identified but an enumerator constant. Adding a new style thus mostly
thermo.cpp to see the two locations where code will need to be added. requires defining a new list of keywords and the associated formats and
then inserting the required output processing where the enumerators are
identified. Search for the word "CUSTOMIZATION" with references to
"thermo style" in the ``thermo.cpp`` file to see the locations where
code will need to be added. The member function ``Thermo::header()``
prints output at the very beginning of a thermodynamic output block and
can be used to print column headers or other front matter. The member
function ``Thermo::footer()`` prints output at the end of a
thermodynamic output block. The formatting of the output is done by
assembling a "line" (which may span multiple lines if the style inserts
newline characters ("\n" as in the "multi" style).
New keywords can also be added to thermo.cpp to compute new quantities New thermodynamic keywords can also be added to ``thermo.cpp`` to
for output. Search for the word "customize" with references to compute new quantities for output. Search for the word "CUSTOMIZATION"
"keyword" in thermo.cpp to see the several locations where code will with references to "keyword" in ``thermo.cpp`` to see the several
need to be added. locations where code will need to be added. Effectively, you need to
define a member function that computes the property, add an if statement
in ``Thermo::parse_fields()`` where the corresponding header string for
the keyword and the function pointer is registered by calling the
``Thermo::addfield()`` method, and add an if statement in
``Thermo::evaluate_keyword()`` which is called from the ``Variable``
class when a thermo keyword is encountered.
Note that the :doc:`thermo_style custom <thermo_style>` command already allows .. note::
for thermo output of quantities calculated by :doc:`fixes <fix>`,
:doc:`computes <compute>`, and :doc:`variables <variable>`. Thus, it may The third argument to ``Thermo::addfield()`` is a flag indicating
be simpler to compute what you wish via one of those constructs, than whether the function for the keyword computes a floating point
by adding a new keyword to the thermo command. (FLOAT), regular integer (INT), or big integer (BIGINT) value. This
information is used for formatting the thermodynamic output. Inside
the function the result must then be stored either in the ``dvalue``,
``ivalue`` or ``bivalue`` member variable, respectively.
Since the :doc:`thermo_style custom <thermo_style>` command allows to
use output of quantities calculated by :doc:`fixes <fix>`,
:doc:`computes <compute>`, and :doc:`variables <variable>`, it may often
be simpler to compute what you wish via one of those constructs, rather
than by adding a new keyword to the thermo_style command.

View File

@ -1,8 +1,8 @@
Variable options Variable options
================ ================
There is one class that computes and stores :doc:`variable <variable>` The ``Variable`` class computes and stores :doc:`variable <variable>`
information in LAMMPS; see the file variable.cpp. The value information in LAMMPS; see the file ``variable.cpp``. The value
associated with a variable can be periodically printed to the screen associated with a variable can be periodically printed to the screen
via the :doc:`print <print>`, :doc:`fix print <fix_print>`, or via the :doc:`print <print>`, :doc:`fix print <fix_print>`, or
:doc:`thermo_style custom <thermo_style>` commands. Variables of style :doc:`thermo_style custom <thermo_style>` commands. Variables of style
@ -19,21 +19,22 @@ of arguments:
compute values = c_mytemp[0], c_thermo_press[3], ... compute values = c_mytemp[0], c_thermo_press[3], ...
Adding keywords for the :doc:`thermo_style custom <thermo_style>` Adding keywords for the :doc:`thermo_style custom <thermo_style>`
command (which can then be accessed by variables) is discussed on the command (which can then be accessed by variables) is discussed in the
:doc:`Modify thermo <Modify_thermo>` doc page. :doc:`Modify thermo <Modify_thermo>` documentation.
Adding a new math function of one or two arguments can be done by Adding a new math function of one or two arguments can be done by
editing one section of the Variable::evaluate() method. Search for editing one section of the ``Variable::evaluate()`` method. Search for
the word "customize" to find the appropriate location. the word "customize" to find the appropriate location.
Adding a new group function can be done by editing one section of the Adding a new group function can be done by editing one section of the
Variable::evaluate() method. Search for the word "customize" to find ``Variable::evaluate()`` method. Search for the word "customize" to
the appropriate location. You may need to add a new method to the find the appropriate location. You may need to add a new method to the
Group class as well (see the group.cpp file). Group class as well (see the ``group.cpp`` file).
Accessing a new atom-based vector can be done by editing one section Accessing a new atom-based vector can be done by editing one section
of the Variable::evaluate() method. Search for the word "customize" of the Variable::evaluate() method. Search for the word "customize"
to find the appropriate location. to find the appropriate location.
Adding new :doc:`compute styles <compute>` (whose calculated values can Adding new :doc:`compute styles <compute>` (whose calculated values can
then be accessed by variables) is discussed on the :doc:`Modify compute <Modify_compute>` doc page. then be accessed by variables) is discussed in the :doc:`Modify compute
<Modify_compute>` documentation.

View File

@ -187,7 +187,7 @@ folder that the dynamic loader searches or inside of the installed
folders are searched by default by Python or the LAMMPS Python folders are searched by default by Python or the LAMMPS Python
package. package.
.. versionchanged:: TBD .. versionchanged:: 24Mar2022
.. note:: .. note::

View File

@ -63,8 +63,10 @@ Examples
Description Description
""""""""""" """""""""""
.. versionchanged:: 24Mar2022
Implement a lattice-Boltzmann fluid on a uniform mesh covering the Implement a lattice-Boltzmann fluid on a uniform mesh covering the
LAMMPS simulation domain. Note that this fix was updated in 2021 and is LAMMPS simulation domain. Note that this fix was updated in 2022 and is
not backward compatible with the previous version. If you need the not backward compatible with the previous version. If you need the
previous version, please download an older version of LAMMPS. The MD previous version, please download an older version of LAMMPS. The MD
particles described by *group-ID* apply a velocity dependent force to particles described by *group-ID* apply a velocity dependent force to

View File

@ -32,18 +32,20 @@ The content and format of what is printed is controlled by the
:doc:`thermo_style <thermo_style>` and :doc:`thermo_style <thermo_style>` and
:doc:`thermo_modify <thermo_modify>` commands. :doc:`thermo_modify <thermo_modify>` commands.
Instead of a numeric value, N can be specified as an :doc:`equal-style variable <variable>`, which should be specified as v_name, where Instead of a numeric value, N can be specified as an :doc:`equal-style
name is the variable name. In this case, the variable is evaluated at variable <variable>`, which should be specified as v_name, where name is
the beginning of a run to determine the next timestep at which the variable name. In this case, the variable is evaluated at the
thermodynamic info will be written out. On that timestep, the beginning of a run to determine the next timestep at which thermodynamic
variable will be evaluated again to determine the next timestep, etc. info will be written out. On that timestep, the variable will be
Thus the variable should return timestep values. See the stagger() evaluated again to determine the next timestep, etc. Thus the variable
and logfreq() and stride() math functions for :doc:`equal-style variables <variable>`, as examples of useful functions to use in should return timestep values. See the stagger() and logfreq() and
this context. Other similar math functions could easily be added as stride() math functions for :doc:`equal-style variables <variable>`, as
options for :doc:`equal-style variables <variable>`. examples of useful functions to use in this context. Other similar math
functions could easily be added as options for :doc:`equal-style
variables <variable>`.
For example, the following commands will output thermodynamic info at For example, the following commands will output thermodynamic info at
timesteps 0,10,20,30,100,200,300,1000,2000,etc: timesteps 0, 10, 20, 30, 100, 200, 300, 1000, 2000, *etc*:
.. code-block:: LAMMPS .. code-block:: LAMMPS

View File

@ -20,7 +20,7 @@ Syntax
*warn* value = *ignore* or *reset* or *default* or a number *warn* value = *ignore* or *reset* or *default* or a number
*norm* value = *yes* or *no* *norm* value = *yes* or *no*
*flush* value = *yes* or *no* *flush* value = *yes* or *no*
*line* value = *one* or *multi* *line* value = *one* or *multi* or *yaml*
*format* values = *line* string, *int* string, *float* string, M string, or *none* *format* values = *line* string, *int* string, *float* string, M string, or *none*
string = C-style format string string = C-style format string
M = integer from 1 to N, where N = # of quantities being output M = integer from 1 to N, where N = # of quantities being output
@ -36,35 +36,35 @@ Examples
thermo_modify temp myTemp format 3 %15.8g thermo_modify temp myTemp format 3 %15.8g
thermo_modify temp myTemp format line "%ld %g %g %15.8g" thermo_modify temp myTemp format line "%ld %g %g %15.8g"
thermo_modify line multi format float %g thermo_modify line multi format float %g
themos_modify line yaml format none
Description Description
""""""""""" """""""""""
Set options for how thermodynamic information is computed and printed Set options for how thermodynamic information is computed and printed by
by LAMMPS. LAMMPS.
.. note:: .. note::
These options apply to the currently defined thermo style. When These options apply to the *currently defined* thermo style. When
you specify a :doc:`thermo_style <thermo_style>` command, all you specify a :doc:`thermo_style <thermo_style>` command, all
thermodynamic settings are restored to their default values, including thermodynamic settings are restored to their default values,
those previously reset by a thermo_modify command. Thus if your input including those previously reset by a thermo_modify command. Thus if
script specifies a thermo_style command, you should use the your input script specifies a thermo_style command, you should use
thermo_modify command after it. the thermo_modify command **after** it.
The *lost* keyword determines whether LAMMPS checks for lost atoms The *lost* keyword determines whether LAMMPS checks for lost atoms each
each time it computes thermodynamics and what it does if atoms are time it computes thermodynamics and what it does if atoms are lost. An
lost. An atom can be "lost" if it moves across a non-periodic atom can be "lost" if it moves across a non-periodic simulation box
simulation box :doc:`boundary <boundary>` or if it moves more than a box :doc:`boundary <boundary>` or if it moves more than a box length outside
length outside the simulation domain (or more than a processor the simulation domain (or more than a processor sub-domain length)
sub-domain length) before reneighboring occurs. The latter case is before reneighboring occurs. The latter case is typically due to bad
typically due to bad dynamics, e.g. too large a timestep or huge dynamics, e.g. too large a timestep or huge forces and velocities. If
forces and velocities. If the value is *ignore*, LAMMPS does not the value is *ignore*, LAMMPS does not check for lost atoms. If the
check for lost atoms. If the value is *error* or *warn*, LAMMPS value is *error* or *warn*, LAMMPS checks and either issues an error or
checks and either issues an error or warning. The code will exit with warning. The code will exit with an error and continue with a warning.
an error and continue with a warning. A warning will only be issued A warning will only be issued once, the first time an atom is lost.
once, the first time an atom is lost. This can be a useful debugging This can be a useful debugging option.
option.
The *lost/bond* keyword determines whether LAMMPS throws an error or The *lost/bond* keyword determines whether LAMMPS throws an error or
not if an atom in a bonded interaction (bond, angle, etc) cannot be not if an atom in a bonded interaction (bond, angle, etc) cannot be
@ -109,55 +109,55 @@ will be reset to zero, and with the value *default*, the counter is
reset and the limit set to 100. An example usage of either *reset* or reset and the limit set to 100. An example usage of either *reset* or
*default* would be to re-enable warnings that were disabled or have *default* would be to re-enable warnings that were disabled or have
reached the limit during equilibration, where the warnings would be reached the limit during equilibration, where the warnings would be
acceptable while the system is still adjusting, but then change acceptable while the system is still adjusting, but then change to all
to all warnings for the production run, where they would indicate warnings for the production run, where they would indicate problems that
problems that would require a closer look at what is causing them. would require a closer look at what is causing them.
The *norm* keyword determines whether various thermodynamic output The *norm* keyword determines whether various thermodynamic output
values are normalized by the number of atoms or not, depending on values are normalized by the number of atoms or not, depending on
whether it is set to *yes* or *no*\ . Different unit styles have whether it is set to *yes* or *no*\ . Different unit styles have
different defaults for this setting (see below). Even if *norm* is different defaults for this setting (see below). Even if *norm* is set
set to *yes*, a value is only normalized if it is an "extensive" to *yes*, a value is only normalized if it is an "extensive" quantity,
quantity, meaning that it scales with the number of atoms in the meaning that it scales with the number of atoms in the system. For the
system. For the thermo keywords described by the page for the thermo keywords described by the page for the :doc:`thermo_style
:doc:`thermo_style <thermo_style>` command, all energy-related keywords <thermo_style>` command, all energy-related keywords are extensive, such
are extensive, such as *pe* or *ebond* or *enthalpy*\ . Other keywords as *pe* or *ebond* or *enthalpy*\ . Other keywords such as *temp* or
such as *temp* or *press* are "intensive" meaning their value is *press* are "intensive" meaning their value is independent (in a
independent (in a statistical sense) of the number of atoms in the statistical sense) of the number of atoms in the system and thus are
system and thus are never normalized. For thermodynamic output values never normalized. For thermodynamic output values extracted from fixes
extracted from fixes and computes in a :doc:`thermo_style custom <thermo_style>` command, the page for the individual and computes in a :doc:`thermo_style custom <thermo_style>` command, the
:doc:`fix <fix>` or :doc:`compute <compute>` lists whether the value is page for the individual :doc:`fix <fix>` or :doc:`compute <compute>`
"extensive" or "intensive" and thus whether it is normalized. lists whether the value is "extensive" or "intensive" and thus whether
Thermodynamic output values calculated by a variable formula are it is normalized. Thermodynamic output values calculated by a variable
assumed to be "intensive" and thus are never normalized. You can formula are assumed to be "intensive" and thus are never normalized.
always include a divide by the number of atoms in the variable formula You can always include a divide by the number of atoms in the variable
if this is not the case. formula if this is not the case.
The *flush* keyword invokes a flush operation after thermodynamic info The *flush* keyword invokes a flush operation after thermodynamic info
is written to the screen and log file. This insures the output is is written to the screen and log file. This insures the output is
updated and not buffered (by the application) even if LAMMPS halts updated and not buffered (by the application) even if LAMMPS halts
before the simulation completes. Please note that this does not before the simulation completes. Please note that this does not affect
affect buffering by the OS or devices, so you may still lose data buffering by the OS or devices, so you may still lose data in case the
in case the simulation stops due to a hardware failure. simulation stops due to a hardware failure.
The *line* keyword determines whether thermodynamics will be output as The *line* keyword determines whether thermodynamics will be output as a
a series of numeric values on one line or in a multi-line format with series of numeric values on one line ("one"), in a multi-line format
3 quantities with text strings per line and a dashed-line header with 3 quantities with text strings per line and a dashed-line header
containing the timestep and CPU time. This modify option overrides containing the timestep and CPU time ("multi"), or in a YAML format
the *one* and *multi* thermo_style settings. block ("yaml"). This modify option overrides the *one*, *multi*, or
*yaml* thermo_style settings.
The *format* keyword can be used to change the default numeric format The *format* keyword can be used to change the default numeric format of
of any of quantities the :doc:`thermo_style <thermo_style>` command any of quantities the :doc:`thermo_style <thermo_style>` command
outputs. All the specified format strings are C-style formats, outputs. All the specified format strings are C-style formats, e.g. as
e.g. as used by the C/C++ printf() command. The *line* keyword takes used by the C/C++ printf() command. The *line* keyword takes a single
a single argument which is the format string for the entire line of argument which is the format string for the entire line of thermo
thermo output, with N fields, which you must enclose in quotes if it output, with N fields, which you must enclose in quotes if it is more
is more than one field. The *int* and *float* keywords take a single than one field. The *int* and *float* keywords take a single format
format argument and are applied to all integer or floating-point argument and are applied to all integer or floating-point quantities
quantities output. The setting for *M string* also takes a single output. The setting for *M string* also takes a single format argument
format argument which is used for the Mth value output in each line, which is used for the Mth value output in each line, e.g. the fifth
e.g. the fifth column is output in high precision for "format 5 column is output in high precision for "format 5 %20.15g".
%20.15g".
The *format* keyword can be used multiple times. The precedence is The *format* keyword can be used multiple times. The precedence is
that for each value in a line of output, the *M* format (if specified) that for each value in a line of output, the *M* format (if specified)
@ -168,46 +168,46 @@ settings, reverting all values to their default format.
.. note:: .. note::
The thermo output values *step* and *atoms* are stored The thermo output values *step* and *atoms* are stored internally as
internally as 8-byte signed integers, rather than the usual 4-byte 8-byte signed integers, rather than the usual 4-byte signed integers.
signed integers. When specifying the *format int* option you can use When specifying the *format int* option you can use a "%d"-style
a "%d"-style format identifier in the format string and LAMMPS will format identifier in the format string and LAMMPS will convert this
convert this to the corresponding 8-byte form when it is applied to to the corresponding 8-byte form when it is applied to those
those keywords. However, when specifying the *line* option or *format keywords. However, when specifying the *line* option or *format M
M string* option for *step* and *natoms*, you should specify a format string* option for *step* and *natoms*, you should specify a format
string appropriate for an 8-byte signed integer, e.g. one with "%ld". string appropriate for an 8-byte signed integer, e.g. one with "%ld".
The *temp* keyword is used to determine how thermodynamic temperature The *temp* keyword is used to determine how thermodynamic temperature is
is calculated, which is used by all thermo quantities that require a calculated, which is used by all thermo quantities that require a
temperature ("temp", "press", "ke", "etotal", "enthalpy", "pxx", etc). temperature ("temp", "press", "ke", "etotal", "enthalpy", "pxx", etc).
The specified compute ID must have been previously defined by the user The specified compute ID must have been previously defined by the user
via the :doc:`compute <compute>` command and it must be a style of via the :doc:`compute <compute>` command and it must be a style of
compute that calculates a temperature. As described in the compute that calculates a temperature. As described in the
:doc:`thermo_style <thermo_style>` command, thermo output uses a default :doc:`thermo_style <thermo_style>` command, thermo output uses a default
compute for temperature with ID = *thermo_temp*. This option allows compute for temperature with ID = *thermo_temp*. This option allows the
the user to override the default. user to override the default.
The *press* keyword is used to determine how thermodynamic pressure is The *press* keyword is used to determine how thermodynamic pressure is
calculated, which is used by all thermo quantities that require a calculated, which is used by all thermo quantities that require a
pressure ("press", "enthalpy", "pxx", etc). The specified compute ID pressure ("press", "enthalpy", "pxx", etc). The specified compute ID
must have been previously defined by the user via the must have been previously defined by the user via the :doc:`compute
:doc:`compute <compute>` command and it must be a style of compute that <compute>` command and it must be a style of compute that calculates a
calculates a pressure. As described in the pressure. As described in the :doc:`thermo_style <thermo_style>`
:doc:`thermo_style <thermo_style>` command, thermo output uses a default command, thermo output uses a default compute for pressure with ID =
compute for pressure with ID = *thermo_press*. This option allows the *thermo_press*. This option allows the user to override the default.
user to override the default.
.. note:: .. note::
If both the *temp* and *press* keywords are used in a single If both the *temp* and *press* keywords are used in a single
thermo_modify command (or in two separate commands), then the order in thermo_modify command (or in two separate commands), then the order
which the keywords are specified is important. Note that a :doc:`pressure compute <compute_pressure>` defines its own temperature compute as in which the keywords are specified is important. Note that a
an argument when it is specified. The *temp* keyword will override :doc:`pressure compute <compute_pressure>` defines its own
this (for the pressure compute being used by thermodynamics), but only temperature compute as an argument when it is specified. The *temp*
if the *temp* keyword comes after the *press* keyword. If the *temp* keyword will override this (for the pressure compute being used by
keyword comes before the *press* keyword, then the new pressure thermodynamics), but only if the *temp* keyword comes after the
compute specified by the *press* keyword will be unaffected by the *press* keyword. If the *temp* keyword comes before the *press*
*temp* setting. keyword, then the new pressure compute specified by the *press*
keyword will be unaffected by the *temp* setting.
Restrictions Restrictions
"""""""""""" """"""""""""
@ -225,7 +225,8 @@ The option defaults are lost = error, warn = 100, norm = yes for unit
style of *lj*, norm = no for unit style of *real* and *metal*, style of *lj*, norm = no for unit style of *real* and *metal*,
flush = no, and temp/press = compute IDs defined by thermo_style. flush = no, and temp/press = compute IDs defined by thermo_style.
The defaults for the line and format options depend on the thermo The defaults for the line and format options depend on the thermo style.
style. For styles "one" and "custom", the line and format defaults For styles "one" and "custom", the line and format defaults are "one",
are "one", "%8d", and "%12.8g". For style "multi", the line and "%10d", and "%12.8g". For style "multi", the line and format defaults
format defaults are "multi", "%8d", and "%14.4f". are "multi", "%14d", and "%14.4f". For style "yaml", the line and format
defaults are "%d" and "%.15g".

View File

@ -10,13 +10,14 @@ Syntax
thermo_style style args thermo_style style args
* style = *one* or *multi* or *custom* * style = *one* or *multi* *yaml* or *custom*
* args = list of arguments for a particular style * args = list of arguments for a particular style
.. parsed-literal:: .. parsed-literal::
*one* args = none *one* args = none
*multi* args = none *multi* args = none
*yaml* args = none
*custom* args = list of keywords *custom* args = list of keywords
possible keywords = step, elapsed, elaplong, dt, time, possible keywords = step, elapsed, elaplong, dt, time,
cpu, tpcpu, spcpu, cpuremain, part, timeremain, cpu, tpcpu, spcpu, cpuremain, part, timeremain,
@ -92,6 +93,8 @@ Examples
.. code-block:: LAMMPS .. code-block:: LAMMPS
thermo_style multi thermo_style multi
thermo_style yaml
thermo_style one
thermo_style custom step temp pe etotal press vol thermo_style custom step temp pe etotal press vol
thermo_style custom step temp etotal c_myTemp v_abc thermo_style custom step temp etotal c_myTemp v_abc
thermo_style custom step temp etotal c_myTemp[*] v_abc thermo_style custom step temp etotal c_myTemp[*] v_abc
@ -99,18 +102,35 @@ Examples
Description Description
""""""""""" """""""""""
Set the style and content for printing thermodynamic data to the Set the style and content for printing thermodynamic data to the screen
screen and log file. and log files.
Style *one* prints a one-line summary of thermodynamic info that is Style *one* prints a single line of thermodynamic info that is the
the equivalent of "thermo_style custom step temp epair emol etotal equivalent of "thermo_style custom step temp epair emol etotal press".
press". The line contains only numeric values. The line contains only numeric values.
Style *multi* prints a multiple-line listing of thermodynamic info Style *multi* prints a multiple-line listing of thermodynamic info
that is the equivalent of "thermo_style custom etotal ke temp pe ebond that is the equivalent of "thermo_style custom etotal ke temp pe ebond
eangle edihed eimp evdwl ecoul elong press". The listing contains eangle edihed eimp evdwl ecoul elong press". The listing contains
numeric values and a string ID for each quantity. numeric values and a string ID for each quantity.
.. versionadded:: 24Mar2022
Style *yaml* is similar to style *one* but prints the output in `YAML
<https://yaml.org/>`_ format which can be easily read by a variety of
script languages and data handling packages. Since LAMMPS may print
other output before, after, or in between thermodynamic output, the
YAML format content needs to be separated from the rest. All YAML
format thermodynamic output can be matched with a regular expression
and can thus be extracted with commands like ``egrep`` as follows:
.. code-block:: sh
egrep '^(keywords:|data:$|---$|\.\.\.$| - \[)' log.lammps > log.yaml
Information about processing such YAML files is in the :doc:`structured
data output howto <Howto_structured_data>`.
Style *custom* is the most general setting and allows you to specify Style *custom* is the most general setting and allows you to specify
which of the keywords listed above you want printed on each which of the keywords listed above you want printed on each
thermodynamic timestep. Note that the keywords c_ID, f_ID, v_name are thermodynamic timestep. Note that the keywords c_ID, f_ID, v_name are

View File

@ -46,10 +46,10 @@ void BondFENENM::compute(int eflag, int vflag)
{ {
int i1, i2, n, type; int i1, i2, n, type;
double delx, dely, delz, ebond, fbond; double delx, dely, delz, ebond, fbond;
double rsq, r0sq, rlogarg, sr6; double rsq, r0sq, rlogarg;
double r; double r;
ebond = sr6 = 0.0; ebond = 0.0;
ev_init(eflag, vflag); ev_init(eflag, vflag);
double **x = atom->x; double **x = atom->x;

View File

@ -115,9 +115,8 @@ void PairDPDfdtEnergyKokkos<LMPDeviceSpace>::init_style()
neighflag = lmp->kokkos->neighflag; neighflag = lmp->kokkos->neighflag;
auto request = neighbor->find_request(this); auto request = neighbor->find_request(this);
request->set_kokkos_host(std::is_same<DeviceType,LMPHostType>::value && request->set_kokkos_host(0);
!std::is_same<DeviceType,LMPDeviceType>::value); request->set_kokkos_device(1);
request->set_kokkos_device(std::is_same<DeviceType,LMPDeviceType>::value);
if (neighflag == FULL) request->enable_full(); if (neighflag == FULL) request->enable_full();
#ifdef DPD_USE_RAN_MARS #ifdef DPD_USE_RAN_MARS

View File

@ -335,7 +335,7 @@ void DumpNetCDF::openfile()
if (thermo) { if (thermo) {
Thermo *th = output->thermo; Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) { for (int i = 0; i < th->nfield; i++) {
NCERRX( nc_inq_varid(ncid, th->keyword[i], &thermovar[i]), th->keyword[i] ); NCERRX( nc_inq_varid(ncid, th->keyword[i].c_str(), &thermovar[i]), th->keyword[i].c_str() );
} }
} }
@ -448,18 +448,18 @@ void DumpNetCDF::openfile()
Thermo *th = output->thermo; Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) { for (int i = 0; i < th->nfield; i++) {
if (th->vtype[i] == Thermo::FLOAT) { if (th->vtype[i] == Thermo::FLOAT) {
NCERRX( nc_def_var(ncid, th->keyword[i], type_nc_real, 1, dims, NCERRX( nc_def_var(ncid, th->keyword[i].c_str(), type_nc_real, 1, dims,
&thermovar[i]), th->keyword[i] ); &thermovar[i]), th->keyword[i].c_str() );
} else if (th->vtype[i] == Thermo::INT) { } else if (th->vtype[i] == Thermo::INT) {
NCERRX( nc_def_var(ncid, th->keyword[i], NC_INT, 1, dims, NCERRX( nc_def_var(ncid, th->keyword[i].c_str(), NC_INT, 1, dims,
&thermovar[i]), th->keyword[i] ); &thermovar[i]), th->keyword[i].c_str() );
} else if (th->vtype[i] == Thermo::BIGINT) { } else if (th->vtype[i] == Thermo::BIGINT) {
#if defined(LAMMPS_SMALLBIG) || defined(LAMMPS_BIGBIG) #if defined(LAMMPS_SMALLBIG) || defined(LAMMPS_BIGBIG)
NCERRX( nc_def_var(ncid, th->keyword[i], NC_INT64, 1, dims, NCERRX( nc_def_var(ncid, th->keyword[i].c_str(), NC_INT64, 1, dims,
&thermovar[i]), th->keyword[i] ); &thermovar[i]), th->keyword[i].c_str() );
#else #else
NCERRX( nc_def_var(ncid, th->keyword[i], NC_LONG, 1, dims, NCERRX( nc_def_var(ncid, th->keyword[i].c_str(), NC_LONG, 1, dims,
&thermovar[i]), th->keyword[i] ); &thermovar[i]), th->keyword[i].c_str() );
#endif #endif
} }
} }
@ -625,13 +625,13 @@ void DumpNetCDF::write()
if (th->vtype[i] == Thermo::FLOAT) { if (th->vtype[i] == Thermo::FLOAT) {
NCERRX( nc_put_var1_double(ncid, thermovar[i], start, NCERRX( nc_put_var1_double(ncid, thermovar[i], start,
&th->dvalue), &th->dvalue),
th->keyword[i] ); th->keyword[i].c_str() );
} else if (th->vtype[i] == Thermo::INT) { } else if (th->vtype[i] == Thermo::INT) {
NCERRX( nc_put_var1_int(ncid, thermovar[i], start, &th->ivalue), NCERRX( nc_put_var1_int(ncid, thermovar[i], start, &th->ivalue),
th->keyword[i] ); th->keyword[i].c_str() );
} else if (th->vtype[i] == Thermo::BIGINT) { } else if (th->vtype[i] == Thermo::BIGINT) {
NCERRX( nc_put_var1_bigint(ncid, thermovar[i], start, &th->bivalue), NCERRX( nc_put_var1_bigint(ncid, thermovar[i], start, &th->bivalue),
th->keyword[i] ); th->keyword[i].c_str() );
} }
} }
} }

View File

@ -332,7 +332,7 @@ void DumpNetCDFMPIIO::openfile()
if (thermo) { if (thermo) {
Thermo *th = output->thermo; Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) { for (int i = 0; i < th->nfield; i++) {
NCERRX( ncmpi_inq_varid(ncid, th->keyword[i], &thermovar[i]), th->keyword[i] ); NCERRX( ncmpi_inq_varid(ncid, th->keyword[i].c_str(), &thermovar[i]), th->keyword[i].c_str() );
} }
} }
@ -436,14 +436,14 @@ void DumpNetCDFMPIIO::openfile()
Thermo *th = output->thermo; Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) { for (int i = 0; i < th->nfield; i++) {
if (th->vtype[i] == Thermo::FLOAT) { if (th->vtype[i] == Thermo::FLOAT) {
NCERRX( ncmpi_def_var(ncid, th->keyword[i], type_nc_real, 1, dims, &thermovar[i]), th->keyword[i] ); NCERRX( ncmpi_def_var(ncid, th->keyword[i].c_str(), type_nc_real, 1, dims, &thermovar[i]), th->keyword[i].c_str() );
} else if (th->vtype[i] == Thermo::INT) { } else if (th->vtype[i] == Thermo::INT) {
NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_INT, 1, dims, &thermovar[i]), th->keyword[i] ); NCERRX( ncmpi_def_var(ncid, th->keyword[i].c_str(), NC_INT, 1, dims, &thermovar[i]), th->keyword[i].c_str() );
} else if (th->vtype[i] == Thermo::BIGINT) { } else if (th->vtype[i] == Thermo::BIGINT) {
#if defined(LAMMPS_SMALLBIG) || defined(LAMMPS_BIGBIG) #if defined(LAMMPS_SMALLBIG) || defined(LAMMPS_BIGBIG)
NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_INT64, 1, dims, &thermovar[i]), th->keyword[i] ); NCERRX( ncmpi_def_var(ncid, th->keyword[i].c_str(), NC_INT64, 1, dims, &thermovar[i]), th->keyword[i].c_str() );
#else #else
NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_LONG, 1, dims, &thermovar[i]), th->keyword[i] ); NCERRX( ncmpi_def_var(ncid, th->keyword[i].c_str(), NC_LONG, 1, dims, &thermovar[i]), th->keyword[i].c_str() );
#endif #endif
} }
} }
@ -612,13 +612,13 @@ void DumpNetCDFMPIIO::write()
if (th->vtype[i] == Thermo::FLOAT) { if (th->vtype[i] == Thermo::FLOAT) {
NCERRX( ncmpi_put_var1_double(ncid, thermovar[i], start, NCERRX( ncmpi_put_var1_double(ncid, thermovar[i], start,
&th->dvalue), &th->dvalue),
th->keyword[i] ); th->keyword[i].c_str() );
} else if (th->vtype[i] == Thermo::INT) { } else if (th->vtype[i] == Thermo::INT) {
NCERRX( ncmpi_put_var1_int(ncid, thermovar[i], start, &th->ivalue), NCERRX( ncmpi_put_var1_int(ncid, thermovar[i], start, &th->ivalue),
th->keyword[i] ); th->keyword[i].c_str() );
} else if (th->vtype[i] == Thermo::BIGINT) { } else if (th->vtype[i] == Thermo::BIGINT) {
NCERRX( ncmpi_put_var1_bigint(ncid, thermovar[i], start, &th->bivalue), NCERRX( ncmpi_put_var1_bigint(ncid, thermovar[i], start, &th->bivalue),
th->keyword[i] ); th->keyword[i].c_str() );
} }
} }
} }

View File

@ -79,6 +79,8 @@ reaxc_multi_body_omp.cpp
reaxc_nonbonded_omp.cpp reaxc_nonbonded_omp.cpp
reaxc_torsion_angles_omp.cpp reaxc_torsion_angles_omp.cpp
reaxc_valence_angles_omp.cpp reaxc_valence_angles_omp.cpp
fix_qeq_reax.cpp
fix_qeq_reax.h
fix_reaxc.cpp fix_reaxc.cpp
fix_reaxc.h fix_reaxc.h
fix_reaxc_bonds.cpp fix_reaxc_bonds.cpp

View File

@ -27,6 +27,8 @@
#include "neigh_list.h" #include "neigh_list.h"
#include "neigh_request.h" #include "neigh_request.h"
#include "neighbor.h" // IWYU pragma: keep #include "neighbor.h" // IWYU pragma: keep
#include "output.h"
#include "thermo.h"
#include "timer.h" // IWYU pragma: keep #include "timer.h" // IWYU pragma: keep
#include "universe.h" #include "universe.h"
#include "update.h" #include "update.h"
@ -121,10 +123,10 @@ void Finish::end(int flag)
if (time_loop > 0.0) cpu_loop = cpu_loop/time_loop*100.0; if (time_loop > 0.0) cpu_loop = cpu_loop/time_loop*100.0;
if (me == 0) { if (me == 0) {
output->thermo->footer();
int ntasks = nprocs * nthreads; int ntasks = nprocs * nthreads;
utils::logmesg(lmp,"Loop time of {:.6g} on {} procs for " utils::logmesg(lmp,"Loop time of {:.6g} on {} procs for {} steps with {} atoms\n\n",
"{} steps with {} atoms\n\n",time_loop, time_loop,ntasks,update->nsteps,atom->natoms);
ntasks,update->nsteps,atom->natoms);
// Gromacs/NAMD-style performance metric for suitable unit settings // Gromacs/NAMD-style performance metric for suitable unit settings
@ -142,8 +144,7 @@ void Finish::end(int flag)
if (strcmp(update->unit_style,"lj") == 0) { if (strcmp(update->unit_style,"lj") == 0) {
double tau_day = 24.0*3600.0 / t_step * update->dt / one_fs; double tau_day = 24.0*3600.0 / t_step * update->dt / one_fs;
utils::logmesg(lmp,"Performance: {:.3f} tau/day, {:.3f} " utils::logmesg(lmp,"Performance: {:.3f} tau/day, {:.3f} timesteps/s\n",tau_day,step_t);
"timesteps/s\n",tau_day,step_t);
} else if (strcmp(update->unit_style,"electron") == 0) { } else if (strcmp(update->unit_style,"electron") == 0) {
double hrs_fs = t_step / update->dt * one_fs / 3600.0; double hrs_fs = t_step / update->dt * one_fs / 3600.0;
double fs_day = 24.0*3600.0 / t_step * update->dt / one_fs; double fs_day = 24.0*3600.0 / t_step * update->dt / one_fs;
@ -161,15 +162,15 @@ void Finish::end(int flag)
if (timeflag) { if (timeflag) {
if (lmp->kokkos) { if (lmp->kokkos) {
utils::logmesg(lmp,"{:.1f}% CPU use with {} MPI tasks x {} OpenMP " utils::logmesg(lmp,"{:.1f}% CPU use with {} MPI tasks x {} OpenMP threads\n",
"threads\n",cpu_loop,nprocs,lmp->kokkos->nthreads); cpu_loop,nprocs,lmp->kokkos->nthreads);
} else { } else {
#if defined(_OPENMP) #if defined(_OPENMP)
utils::logmesg(lmp,"{:.1f}% CPU use with {} MPI tasks x {} OpenMP " utils::logmesg(lmp,"{:.1f}% CPU use with {} MPI tasks x {} OpenMP threads\n",
"threads\n",cpu_loop,nprocs,nthreads); cpu_loop,nprocs,nthreads);
#else #else
utils::logmesg(lmp,"{:.1f}% CPU use with {} MPI tasks " utils::logmesg(lmp,"{:.1f}% CPU use with {} MPI tasks x no OpenMP threads\n",
"x no OpenMP threads\n",cpu_loop,nprocs); cpu_loop,nprocs);
#endif #endif
} }
} }
@ -192,8 +193,7 @@ void Finish::end(int flag)
if (me == 0) { if (me == 0) {
std::string mesg = "\nMinimization stats:\n"; std::string mesg = "\nMinimization stats:\n";
mesg += fmt::format(" Stopping criterion = {}\n", mesg += fmt::format(" Stopping criterion = {}\n",update->minimize->stopstr);
update->minimize->stopstr);
mesg += fmt::format(" Energy initial, next-to-last, final = \n" mesg += fmt::format(" Energy initial, next-to-last, final = \n"
" {:18.15g} {:18.15g} {:18.15g}\n", " {:18.15g} {:18.15g} {:18.15g}\n",
update->minimize->einitial, update->minimize->einitial,
@ -222,33 +222,27 @@ void Finish::end(int flag)
time = timer->get_wall(Timer::DEPHASE); time = timer->get_wall(Timer::DEPHASE);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Dephase time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Dephase time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::DYNAMICS); time = timer->get_wall(Timer::DYNAMICS);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Dynamics time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Dynamics time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::QUENCH); time = timer->get_wall(Timer::QUENCH);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Quench time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Quench time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::REPCOMM); time = timer->get_wall(Timer::REPCOMM);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Comm time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Comm time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::REPOUT); time = timer->get_wall(Timer::REPOUT);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Output time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Output time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = time_other; time = time_other;
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Other time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Other time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
} }
// TAD stats // TAD stats
@ -259,33 +253,27 @@ void Finish::end(int flag)
time = timer->get_wall(Timer::NEB); time = timer->get_wall(Timer::NEB);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," NEB time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," NEB time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::DYNAMICS); time = timer->get_wall(Timer::DYNAMICS);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Dynamics time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Dynamics time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::QUENCH); time = timer->get_wall(Timer::QUENCH);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Quench time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Quench time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::REPCOMM); time = timer->get_wall(Timer::REPCOMM);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Comm time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Comm time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::REPOUT); time = timer->get_wall(Timer::REPOUT);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Output time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Output time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = time_other; time = time_other;
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Other time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Other time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
} }
// HYPER stats // HYPER stats
@ -296,18 +284,15 @@ void Finish::end(int flag)
time = timer->get_wall(Timer::DYNAMICS); time = timer->get_wall(Timer::DYNAMICS);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Dynamics time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Dynamics time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = timer->get_wall(Timer::QUENCH); time = timer->get_wall(Timer::QUENCH);
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Quench time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Quench time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
time = time_other; time = time_other;
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs; time = tmp/nprocs;
if (me == 0) utils::logmesg(lmp," Other time (%) = {} ({})\n", if (me == 0) utils::logmesg(lmp," Other time (%) = {} ({})\n",time,time/time_loop*100.0);
time,time/time_loop*100.0);
} }
// further timing breakdowns // further timing breakdowns
@ -326,28 +311,20 @@ void Finish::end(int flag)
"------------------------------------------------------\n"); "------------------------------------------------------\n");
} }
mpi_timings("Pair",timer,Timer::PAIR, world,nprocs, mpi_timings("Pair",timer,Timer::PAIR, world,nprocs,nthreads,me,time_loop,screen,logfile);
nthreads,me,time_loop,screen,logfile);
if (atom->molecular != Atom::ATOMIC) if (atom->molecular != Atom::ATOMIC)
mpi_timings("Bond",timer,Timer::BOND,world,nprocs, mpi_timings("Bond",timer,Timer::BOND,world,nprocs,nthreads,me,time_loop,screen,logfile);
nthreads,me,time_loop,screen,logfile);
if (force->kspace) if (force->kspace)
mpi_timings("Kspace",timer,Timer::KSPACE,world,nprocs, mpi_timings("Kspace",timer,Timer::KSPACE,world,nprocs,nthreads,me,time_loop,screen,logfile);
nthreads,me,time_loop,screen,logfile);
mpi_timings("Neigh",timer,Timer::NEIGH,world,nprocs, mpi_timings("Neigh",timer,Timer::NEIGH,world,nprocs,nthreads,me,time_loop,screen,logfile);
nthreads,me,time_loop,screen,logfile); mpi_timings("Comm",timer,Timer::COMM,world,nprocs,nthreads,me,time_loop,screen,logfile);
mpi_timings("Comm",timer,Timer::COMM,world,nprocs, mpi_timings("Output",timer,Timer::OUTPUT,world,nprocs,nthreads,me,time_loop,screen,logfile);
nthreads,me,time_loop,screen,logfile); mpi_timings("Modify",timer,Timer::MODIFY,world,nprocs,nthreads,me,time_loop,screen,logfile);
mpi_timings("Output",timer,Timer::OUTPUT,world,nprocs,
nthreads,me,time_loop,screen,logfile);
mpi_timings("Modify",timer,Timer::MODIFY,world,nprocs,
nthreads,me,time_loop,screen,logfile);
if (timer->has_sync()) if (timer->has_sync())
mpi_timings("Sync",timer,Timer::SYNC,world,nprocs, mpi_timings("Sync",timer,Timer::SYNC,world,nprocs,nthreads,me,time_loop,screen,logfile);
nthreads,me,time_loop,screen,logfile);
time = time_other; time = time_other;
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
@ -543,8 +520,7 @@ void Finish::end(int flag)
if (atom->natoms > 0) if (atom->natoms > 0)
mesg += fmt::format("Ave neighs/atom = {:.8}\n",nall/atom->natoms); mesg += fmt::format("Ave neighs/atom = {:.8}\n",nall/atom->natoms);
if ((atom->molecular != Atom::ATOMIC) && (atom->natoms > 0)) if ((atom->molecular != Atom::ATOMIC) && (atom->natoms > 0))
mesg += fmt::format("Ave special neighs/atom = {:.8}\n", mesg += fmt::format("Ave special neighs/atom = {:.8}\n",nspec_all/atom->natoms);
nspec_all/atom->natoms);
mesg += fmt::format("Neighbor list builds = {}\n",neighbor->ncalls); mesg += fmt::format("Neighbor list builds = {}\n",neighbor->ncalls);
if (neighbor->dist_check) if (neighbor->dist_check)
mesg += fmt::format("Dangerous builds = {}\n",neighbor->ndanger); mesg += fmt::format("Dangerous builds = {}\n",neighbor->ndanger);

View File

@ -93,8 +93,6 @@ FixNH::FixNH(LAMMPS *lmp, int narg, char **arg) :
tcomputeflag = 0; tcomputeflag = 0;
pcomputeflag = 0; pcomputeflag = 0;
id_temp = nullptr;
id_press = nullptr;
// turn on tilt factor scaling, whenever applicable // turn on tilt factor scaling, whenever applicable

View File

@ -405,7 +405,7 @@ after calling Py_Finalize().
This function can be called to explicitly clear the Python This function can be called to explicitly clear the Python
environment in case it is safe to do so. environment in case it is safe to do so.
.. versionadded:: TBD .. versionadded:: 20Sep2021
*See also* *See also*
:cpp:func:`lammps_mpi_finalize`, :cpp:func:`lammps_kokkos_finalize` :cpp:func:`lammps_mpi_finalize`, :cpp:func:`lammps_kokkos_finalize`

View File

@ -69,7 +69,7 @@ Output::Output(LAMMPS *lmp) : Pointers(lmp)
char **newarg = new char*[1]; char **newarg = new char*[1];
newarg[0] = (char *) "one"; newarg[0] = (char *) "one";
thermo = new Thermo(lmp,1,newarg); thermo = new Thermo(lmp,1,newarg);
delete [] newarg; delete[] newarg;
thermo_every = 0; thermo_every = 0;
var_thermo = nullptr; var_thermo = nullptr;
@ -110,7 +110,7 @@ Output::Output(LAMMPS *lmp) : Pointers(lmp)
Output::~Output() Output::~Output()
{ {
if (thermo) delete thermo; if (thermo) delete thermo;
delete [] var_thermo; delete[] var_thermo;
memory->destroy(mode_dump); memory->destroy(mode_dump);
memory->destroy(every_dump); memory->destroy(every_dump);
@ -118,17 +118,17 @@ Output::~Output()
memory->destroy(next_dump); memory->destroy(next_dump);
memory->destroy(next_time_dump); memory->destroy(next_time_dump);
memory->destroy(last_dump); memory->destroy(last_dump);
for (int i = 0; i < ndump; i++) delete [] var_dump[i]; for (int i = 0; i < ndump; i++) delete[] var_dump[i];
memory->sfree(var_dump); memory->sfree(var_dump);
memory->destroy(ivar_dump); memory->destroy(ivar_dump);
for (int i = 0; i < ndump; i++) delete dump[i]; for (int i = 0; i < ndump; i++) delete dump[i];
memory->sfree(dump); memory->sfree(dump);
delete [] restart1; delete[] restart1;
delete [] restart2a; delete[] restart2a;
delete [] restart2b; delete[] restart2b;
delete [] var_restart_single; delete[] var_restart_single;
delete [] var_restart_double; delete[] var_restart_double;
delete restart; delete restart;
delete dump_map; delete dump_map;
@ -545,8 +545,7 @@ void Output::calculate_next_dump(int which, int idump, bigint ntimestep)
} }
nextdump = ntimestep + nextdump = ntimestep +
static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) / static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) / update->dt) + 1;
update->dt) + 1;
// if delta is too small to reach next timestep, use multiple of delta // if delta is too small to reach next timestep, use multiple of delta
@ -557,8 +556,7 @@ void Output::calculate_next_dump(int which, int idump, bigint ntimestep)
((tnext - nexttime) / every_time_dump[idump]); ((tnext - nexttime) / every_time_dump[idump]);
nexttime = nexttime + (multiple+1)*every_time_dump[idump]; nexttime = nexttime + (multiple+1)*every_time_dump[idump];
nextdump = ntimestep + nextdump = ntimestep +
static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) / static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) / update->dt) + 1;
update->dt) + 1;
} }
} else { } else {
@ -575,8 +573,7 @@ void Output::calculate_next_dump(int which, int idump, bigint ntimestep)
error->all(FLERR,"Dump every/time variable returned a bad time"); error->all(FLERR,"Dump every/time variable returned a bad time");
nextdump = ntimestep + nextdump = ntimestep +
static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) / static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) / update->dt) + 1;
update->dt) + 1;
if (nextdump <= ntimestep) if (nextdump <= ntimestep)
error->all(FLERR,"Dump every/time variable too small for next timestep"); error->all(FLERR,"Dump every/time variable too small for next timestep");
} }
@ -825,7 +822,7 @@ void Output::delete_dump(char *id)
if (idump == ndump) error->all(FLERR,"Could not find undump ID"); if (idump == ndump) error->all(FLERR,"Could not find undump ID");
delete dump[idump]; delete dump[idump];
delete [] var_dump[idump]; delete[] var_dump[idump];
// move other dumps down in list one slot // move other dumps down in list one slot
@ -869,7 +866,7 @@ void Output::set_thermo(int narg, char **arg)
// always reset var_thermo, so it is possible to switch back from // always reset var_thermo, so it is possible to switch back from
// variable spaced thermo outputs to constant spaced ones. // variable spaced thermo outputs to constant spaced ones.
delete [] var_thermo; delete[] var_thermo;
var_thermo = nullptr; var_thermo = nullptr;
if (utils::strmatch(arg[0],"^v_")) { if (utils::strmatch(arg[0],"^v_")) {
@ -929,12 +926,12 @@ void Output::create_restart(int narg, char **arg)
delete restart; delete restart;
restart = nullptr; restart = nullptr;
delete [] restart1; delete[] restart1;
delete [] restart2a; delete[] restart2a;
delete [] restart2b; delete[] restart2b;
restart1 = restart2a = restart2b = nullptr; restart1 = restart2a = restart2b = nullptr;
delete [] var_restart_single; delete[] var_restart_single;
delete [] var_restart_double; delete[] var_restart_double;
var_restart_single = var_restart_double = nullptr; var_restart_single = var_restart_double = nullptr;
return; return;
@ -950,13 +947,13 @@ void Output::create_restart(int narg, char **arg)
restart_flag = restart_flag_single = 1; restart_flag = restart_flag_single = 1;
if (varflag) { if (varflag) {
delete [] var_restart_single; delete[] var_restart_single;
var_restart_single = utils::strdup(arg[0]+2); var_restart_single = utils::strdup(arg[0]+2);
restart_every_single = 0; restart_every_single = 0;
} else restart_every_single = every; } else restart_every_single = every;
int n = strlen(arg[1]) + 3; int n = strlen(arg[1]) + 3;
delete [] restart1; delete[] restart1;
restart1 = new char[n]; restart1 = new char[n];
strcpy(restart1,arg[1]); strcpy(restart1,arg[1]);
if (strchr(restart1,'*') == nullptr) strcat(restart1,".*"); if (strchr(restart1,'*') == nullptr) strcat(restart1,".*");
@ -966,13 +963,13 @@ void Output::create_restart(int narg, char **arg)
restart_flag = restart_flag_double = 1; restart_flag = restart_flag_double = 1;
if (varflag) { if (varflag) {
delete [] var_restart_double; delete[] var_restart_double;
var_restart_double = utils::strdup(arg[0]+2); var_restart_double = utils::strdup(arg[0]+2);
restart_every_double = 0; restart_every_double = 0;
} else restart_every_double = every; } else restart_every_double = every;
delete [] restart2a; delete[] restart2a;
delete [] restart2b; delete[] restart2b;
restart_toggle = 0; restart_toggle = 0;
restart2a = utils::strdup(arg[1]); restart2a = utils::strdup(arg[1]);
restart2b = utils::strdup(arg[2]); restart2b = utils::strdup(arg[2]);

File diff suppressed because it is too large Load Diff

View File

@ -39,26 +39,16 @@ class Thermo : protected Pointers {
bigint lost_check(); bigint lost_check();
void modify_params(int, char **); void modify_params(int, char **);
void header(); void header();
void footer();
void compute(int); void compute(int);
int evaluate_keyword(const char *, double *); int evaluate_keyword(const std::string &, double *);
private: private:
char *line;
char **keyword;
int *vtype;
int nfield, nfield_initial; int nfield, nfield_initial;
int me; int *vtype;
std::string line;
char **format; std::vector<std::string> keyword, format, format_column_user;
char *format_line_user; std::string format_line_user, format_float_user, format_int_user, format_bigint_user;
char *format_float_user, *format_int_user, *format_bigint_user;
char **format_column_user;
char *format_float_one_def, *format_float_multi_def;
char *format_int_one_def, *format_int_multi_def;
char format_multi[128];
char format_bigint_one_def[8], format_bigint_multi_def[8];
int normvalue; // use this for normflag unless natoms = 0 int normvalue; // use this for normflag unless natoms = 0
int normuserflag; // 0 if user has not set, 1 if has int normuserflag; // 0 if user has not set, 1 if has
@ -88,7 +78,6 @@ class Thermo : protected Pointers {
// id = ID of Compute objects // id = ID of Compute objects
// Compute * = ptrs to the Compute objects // Compute * = ptrs to the Compute objects
int index_temp, index_press_scalar, index_press_vector, index_pe; int index_temp, index_press_scalar, index_press_vector, index_pe;
char *id_temp, *id_press, *id_pe;
class Compute *temperature, *pressure, *pe; class Compute *temperature, *pressure, *pe;
int ncompute; // # of Compute objects called by thermo int ncompute; // # of Compute objects called by thermo
@ -109,11 +98,16 @@ class Thermo : protected Pointers {
void allocate(); void allocate();
void deallocate(); void deallocate();
void parse_fields(char *); void parse_fields(const std::string &);
int add_compute(const char *, int); int add_compute(const char *, int);
int add_fix(const char *); int add_fix(const char *);
int add_variable(const char *); int add_variable(const char *);
void check_temp(const std::string &);
void check_pe(const std::string &);
void check_press_scalar(const std::string &);
void check_press_vector(const std::string &);
typedef void (Thermo::*FnPtr)(); typedef void (Thermo::*FnPtr)();
void addfield(const char *, FnPtr, int); void addfield(const char *, FnPtr, int);
FnPtr *vfunc; // list of ptrs to functions FnPtr *vfunc; // list of ptrs to functions