Merge branch 'develop' into kk_bug_fixes

This commit is contained in:
Stan Moore
2025-01-21 14:50:34 -07:00
committed by GitHub
52 changed files with 925 additions and 344 deletions

View File

@ -72,6 +72,10 @@ if(INTEL_ARCH STREQUAL "KNL")
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
message(FATAL_ERROR "Must use Intel compiler with INTEL for KNL architecture")
endif()
message(WARNING, "Support for Intel Xeon Phi accelerators and Knight's Landing CPUs "
"will be removed from LAMMPS in Summer 2025 due to lack of available machines "
"in labs and HPC centers and removed support in recent compilers "
"Please contact developers@lammps.org if you have any concerns about this step.")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -xHost -qopenmp -qoffload")
set(MIC_OPTIONS "-qoffload-option,mic,compiler,\"-fp-model fast=2 -mGLOB_default_function_attrs=\\\"gather_scatter_loop_unroll=4\\\"\"")
target_compile_options(lammps PRIVATE -xMIC-AVX512 -qoffload -fno-alias -ansi-alias -restrict -qoverride-limits ${MIC_OPTIONS})

View File

@ -7,13 +7,7 @@ typically document what a variable stores, what a small section of
code does, or what a function does and its input/outputs. The topics
on this page are intended to document code functionality at a higher level.
Available topics are:
- `Reading and parsing of text and text files`_
- `Requesting and accessing neighbor lists`_
- `Choosing between a custom atom style, fix property/atom, and fix STORE/ATOM`_
- `Fix contributions to instantaneous energy, virial, and cumulative energy`_
- `KSpace PPPM FFT grids`_
.. contents::
----
@ -218,6 +212,146 @@ command:
neighbor->add_request(this, "delete_atoms", NeighConst::REQ_FULL);
Errors, warnings, and informational messages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LAMMPS has specialized functionality to handle errors (which should
terminate LAMMPS), warning messages (which should indicate possible
problems *without* terminating LAMMPS), and informational text for
messages about the progress and chosen settings. We *strongly*
encourage using these facilities and to *stay away* from using
``printf()`` or ``fprintf()`` or ``std::cout`` or ``std::cerr`` and
calling ``MPI_Abort()`` or ``exit()`` directly. Warnings and
informational messages should be printed only on MPI rank 0 to avoid
flooding the output when running in parallel with many MPI processes.
**Errors**
When LAMMPS encounters an error, for example a syntax error in the
input, then a suitable error message should be printed giving a brief,
one line remark about the reason and then call either ``Error::all()``
or ``Error::one()``. ``Error::all()`` must be called when the failing
code path is executed by *all* MPI processes and the error condition
will appear for *all* MPI processes the same. If desired, each MPI
process may set a flag to either 0 or 1 and then MPI_Allreduce()
searching for the maximum can be used to determine if there was an error
on *any* of the MPI processes and make this information available to
*all*. ``Error::one()`` in contrast needs to be called when only one or
a few MPI processes execute the code path or can have the error
condition. ``Error::all()`` is generally the preferred option.
Calling these functions does not abort LAMMPS directly, but rather
throws either a ``LAMMPSException`` (from ``Error::all()``) or a
``LAMMPSAbortException`` (from ``Error::one()``). These exceptions are
caught by the LAMMPS ``main()`` program and then handled accordingly.
The reason for this approach is to support applications, especially
graphical applications like :ref:`LAMMPS-GUI <lammps_gui>`, that are
linked to the LAMMPS library and have a mechanism to avoid that an error
in LAMMPS terminates the application. By catching the exceptions, the
application can delete the failing LAMMPS class instance and create a
new one to try again. In a similar fashion, the :doc:`LAMMPS Python
module <Python_module>` checks for this and then re-throws corresponding
Python exception, which in turn can be caught by the calling Python
code.
There are multiple "signatures" that can be called:
- ``Error::all(FLERR, "Error message")``: this will abort LAMMPS with
the error message "Error message", followed by the last line of input
that was read and processed before the error condition happened.
- ``Error::all(FLERR, Error::NOLASTLINE, "Error message")``: this is the
same as before but without the last line of input. This is preferred
for errors that would happen *during* a :doc:`run <run>` or
:doc:`minimization <minimize>`, since showing the "run" or "minimize"
command would be the last line, but is unrelated to the error.
- ``Error::all(FLERR, idx, "Error message")``: this is for argument
parsing where "idx" is the index (starting at 0) of the argument for a
LAMMPS command that is causing the failure (use -1 for the command
itself). The output may also include the last input line *before* and
*after*, if they differ due to substituting variables. A textual
indicator is pointing to the specific word that failed. Using the
constant ``Error::NOPOINTER`` in place of the *idx* argument will
suppress the marker and then the behavior is like the *idx* argument
is not provided.
FLERR is a macro containing the filename and line where the Error class
is called and that information is appended to the error message. This
allows to quickly find the relevant source code causing the error. For
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.
.. note::
For commands like :doc:`fix ave/time <fix_ave_time>` that accept
wildcard arguments, the :cpp:func:`utils::expand_args` function
may be passed as an optional argument where the function will provide
a map to the original arguments from the expanded argument indices.
For complex errors, that can have multiple causes and which cannot be
explained in a single line, you can append to the error message, the
string created by :cpp:func:`utils::errorurl`, which then provides a
URL pointing to a paragraph of the :doc:`Errors_details` that
corresponds to the number provided. Example:
.. code-block:: c++
error->all(FLERR, "Unknown identifier in data file: {}{}", keyword, utils::errorurl(1));
This will output something like this:
.. parsed-literal::
ERROR: Unknown identifier in data file: Massess
For more information see https://docs.lammps.org/err0001 (src/read_data.cpp:1482)
Last input line: read_data data.peptide
Where the URL points to the first paragraph with explanations on
the :doc:`Errors_details` page in the manual.
**Warnings**
To print warnings, the ``Errors::warning()`` function should be used.
It also requires the FLERR macros as first argument to easily identify
the location of the warning in the source code. Same as with the error
functions above, the function has two variants: one just taking a single
string as final argument and a second that uses the `{fmt} library
<https://fmt.dev>`_ to make it similar to, say, ``fprintf()``. One
motivation to use this function is that it will output warnings with
always the same capitalization of the leading "WARNING" string. A
second is that it has a built in rate limiter. After a given number (by
default 100), that can be set via the :doc:`thermo_modify command
<thermo_modify>` no more warnings are printed. Also, warnings are
written consistently to both screen and logfile or not, depending on the
settings for :ref:`screen <screen>` or :doc:`logfile <log>` output.
.. note::
Unlike ``Error::all()``, the warning function will produce output on
*every* MPI process, so it typically would be prefixed with an if
statement testing for ``comm->me == 0``, i.e. limiting output to MPI
rank 0.
**Informational messages**
Finally, for informational message LAMMPS has the
:cpp:func:`utils::logmesg() convenience function
<LAMMPS_NS::utils::logmesg>`. It also uses the `{fmt} library
<https://fmt.dev>`_ to support using a format string followed by a
matching number of arguments. It will output the resulting formatted
text to both, the screen and the logfile and will honor the
corresponding settings about whether this output is active and to which
file it should be send. Same as for ``Error::warning()``, it would
produce output for every MPI process and thus should usually be called
only on MPI rank 0 to avoid flooding the output when running with many
parallel processes.
Choosing between a custom atom style, fix property/atom, and fix STORE/ATOM
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -133,6 +133,9 @@ and parsing files or arguments.
.. doxygenfunction:: trim_comment
:project: progguide
.. doxygenfunction:: strcompress
:project: progguide
.. doxygenfunction:: strip_style_suffix
:project: progguide
@ -166,6 +169,9 @@ and parsing files or arguments.
.. doxygenfunction:: split_lines
:project: progguide
.. doxygenfunction:: strsame
:project: progguide
.. doxygenfunction:: strmatch
:project: progguide
@ -238,6 +244,9 @@ Convenience functions
.. doxygenfunction:: missing_cmd_args
:project: progguide
.. doxygenfunction:: point_to_error
:project: progguide
.. doxygenfunction:: flush_buffers(LAMMPS *lmp)
:project: progguide

View File

@ -178,3 +178,64 @@ with and without the communication and a Gflop rate is computed. The
3d rate is with communication; the 1d rate is without (just the 1d
FFTs). Thus you can estimate what fraction of your FFT time was spent
in communication, roughly 75% in the example above.
Error message output
====================
Depending on the error function arguments when it is called in the
source code, there will be one to four lines of error output.
A single line
^^^^^^^^^^^^^
The line starts with "ERROR: ", followed by the error message and
information about the location in the source where the error function
was called in parenthesis on the right (here: line 131 of the file
src/fix_print.cpp). Example:
.. parsed-literal::
ERROR: Fix print timestep variable nevery returned a bad timestep: 9900 (src/fix_print.cpp:131)
Two lines
^^^^^^^^^
In addition to the single line output, also the last line of the input
will be repeated. If a command is spread over multiple lines in the
input using the continuation character '&', then the error will print
the entire concatenated line. For readability all whitespace is
compressed to single blanks. Example:
.. parsed-literal::
ERROR: Unrecognized fix style 'printf' (src/modify.cpp:924)
Last input line: fix 0 all printf v_nevery "Step: $(step) ${step}"
Three lines
^^^^^^^^^^^
In addition to the two line output from above, a third line is added
that uses caret character markers '^' to indicate which "word" in the
input failed. Example:
.. parsed-literal::
ERROR: Illegal fix print nevery value -100; must be > 0 (src/fix_print.cpp:41)
Last input line: fix 0 all print -100 "Step: $(step) ${stepx}"
^^^^
Four lines
^^^^^^^^^^
The three line output is expanded to four lines, if the the input is
modified through input pre-processing, e.g. when substituting
variables. Now the last command is printed once in the original form and
a second time after substitutions are applied. The caret character
markers '^' are applied to the second version. Example:
.. parsed-literal::
ERROR: Illegal fix print nevery value -100; must be > 0 (src/fix_print.cpp:41)
Last input line: fix 0 all print ${nevery} 'Step: $(step) ${step}'
--> parsed line: fix 0 all print -100 "Step: $(step) ${step}"
^^^^

View File

@ -67,6 +67,14 @@ version 23 November 2023 and Kokkos version 4.2.
To build with Kokkos support for AMD GPUs, the AMD ROCm toolkit
software version 5.2.0 or later must be installed on your system.
.. admonition:: Intel Data Center GPU support
:class: note
Support for Kokkos with Intel Data Center GPU accelerators (formerly
known under the code name "Ponte Vecchio") in LAMMPS is still a work
in progress. Only a subset of the functionality works correctly.
Please contact the LAMMPS developers if you run into problems.
.. admonition:: CUDA and MPI library compatibility
:class: note
@ -80,13 +88,15 @@ version 23 November 2023 and Kokkos version 4.2.
LAMMPS command-line or by using the command :doc:`package kokkos
gpu/aware off <package>` in the input file.
.. admonition:: Intel Data Center GPU support
.. admonition:: Using multiple MPI ranks per GPU
:class: note
Support for Kokkos with Intel Data Center GPU accelerators (formerly
known under the code name "Ponte Vecchio") in LAMMPS is still a work
in progress. Only a subset of the functionality works correctly.
Please contact the LAMMPS developers if you run into problems.
Unlike with the GPU package, there are limited benefits from using
multiple MPI processes per GPU with KOKKOS. But when doing this it
is **required** to enable CUDA MPS (`Multi-Process Service :: GPU
Deployment and Management Documentation
<https://docs.nvidia.com/deploy/mps/index.html>`_ ) to get acceptable
performance.
Building LAMMPS with the KOKKOS package
"""""""""""""""""""""""""""""""""""""""
@ -365,13 +375,13 @@ one or more nodes, each with two GPUs:
.. note::
When using a GPU, you will achieve the best performance if your
input script does not use fix or compute styles which are not yet
When using a GPU, you will achieve the best performance if your input
script does not use fix or compute styles which are not yet
Kokkos-enabled. This allows data to stay on the GPU for multiple
timesteps, without being copied back to the host CPU. Invoking a
non-Kokkos fix or compute, or performing I/O for
:doc:`thermo <thermo_style>` or :doc:`dump <dump>` output will cause data
to be copied back to the CPU incurring a performance penalty.
non-Kokkos fix or compute, or performing I/O for :doc:`thermo
<thermo_style>` or :doc:`dump <dump>` output will cause data to be
copied back to the CPU incurring a performance penalty.
.. note::
@ -379,6 +389,56 @@ one or more nodes, each with two GPUs:
kspace, etc., you must set the environment variable ``CUDA_LAUNCH_BLOCKING=1``.
However, this will reduce performance and is not recommended for production runs.
Troubleshooting segmentation faults on GPUs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As noted above, KOKKOS by default assumes that the MPI library is
GPU-aware. This is not always the case and can lead to segmentation
faults when using more than one MPI process. Normally, LAMMPS will
print a warning like "*Turning off GPU-aware MPI since it is not
detected*", or an error message like "*Kokkos with GPU-enabled backend
assumes GPU-aware MPI is available*", OR a **segmentation fault**. To
confirm that a segmentation fault is caused by this, you can turn off
the GPU-aware assumption via the :doc:`package kokkos command <package>`
or the corresponding command-line flag.
If you still get a segmentation fault, despite running with only one MPI
process or using the command-line flag to turn off expecting a GPU-aware
MPI library, then using the CMake compile setting
``-DKokkos_ENABLE_DEBUG=on`` or adding ``KOKKOS_DEBUG=yes`` to your
machine makefile for building with traditional make will generate useful
output that can be passed to the LAMMPS developers for further
debugging.
Troubleshooting memory allocation on GPUs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
`Kokkos Tools <https://github.com/kokkos/kokkos-tools/>`_ provides a set
of lightweight profiling and debugging utilities, which interface with
instrumentation hooks (eg. `space-time-stack
<https://github.com/kokkos/kokkos-tools/tree/develop/profiling/space-time-stack>`_)
built directly into the Kokkos runtime. After compiling a dynamic LAMMPS
library, you then have to set the environment variable ``KOKKOS_TOOLS_LIBS``
before executing your LAMMPS Kokkos run. Example:
.. code-block:: bash
export KOKKOS_TOOLS_LIBS=${HOME}/kokkos-tools/src/tools/memory-events/kp_memory_event.so
mpirun -np 4 lmp_kokkos_cuda_openmpi -in in.lj -k on g 4 -sf kk
Starting with the NVIDIA Pascal GPU architecture, CUDA supports
`"Unified Virtual Memory" (UVM)
<https://developer.nvidia.com/blog/unified-memory-cuda-beginners/>`_
which enables allocating more memory than a GPU possesses by also using
memory on the host CPU and then CUDA will transparently move data
between CPU and GPU as needed. The resulting LAMMPS performance depends
on `memory access pattern, data residency, and GPU memory
oversubscription
<https://developer.nvidia.com/blog/improving-gpu-memory-oversubscription-performance/>`_
. The CMake option ``-DKokkos_ENABLE_CUDA_UVM=on`` or the makefile
setting ``KOKKOS_CUDA_OPTIONS=enable_lambda,force_uvm`` enables using
:ref:`UVM with Kokkos <kokkos>` when compiling LAMMPS.
Run with the KOKKOS package by editing an input script
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -62,6 +62,18 @@ For all styles, by default, an interaction is only turned off (or on)
if all the atoms involved are in the specified group. See the *any*
keyword to change the behavior.
.. admonition:: Possible errors caused by using *delete_bonds*
:class: warning
Since this command by default only *turns off* bonded interactions,
their definitions are still present and subject to the limitations
due to LAMMPS' domain decomposition based parallelization. That is,
when a bond is turned off, the two constituent atoms may move apart
and may reach a distance where they can lead to a "bond atoms missing"
error and crash the simulation. Adding the *remove* keyword (see
below) is required to fully remove those interactions and prevent
the error.
Several of the styles (\ *atom*, *bond*, *angle*, *dihedral*, *improper*\ )
take a *type* as an argument. The specified *type* can be a
:doc:`type label <Howto_type_labels>`. Otherwise, the type should be an
@ -98,15 +110,18 @@ of all interactions in the specified group is simply reported. This
is useful for diagnostic purposes if bonds have been turned off by a
bond-breaking potential during a previous run.
The default behavior of the delete_bonds command is to turn off
interactions by toggling their type to a negative value, but not to
permanently remove the interaction. For example, a bond_type of 2 is set to
:math:`-2.` The neighbor list creation routines will not include such an
interaction in their interaction lists. The default is also to not
alter the list of 1--2, 1--3, or 1--4 neighbors computed by the
:doc:`special_bonds <special_bonds>` command and used to weight pairwise
force and energy calculations. This means that pairwise computations
will proceed as if the bond (or angle, etc.) were still turned on.
.. admonition:: Impact on special_bonds processing and exclusions
:class: note
The default behavior of the delete_bonds command is to turn off
interactions by toggling their type to a negative value, but not to
permanently remove the interaction. For example, a bond_type of 2 is set to
:math:`-2.` The neighbor list creation routines will not include such an
interaction in their interaction lists. The default is also to not
alter the list of 1--2, 1--3, or 1--4 neighbors computed by the
:doc:`special_bonds <special_bonds>` command and used to weight pairwise
force and energy calculations. This means that pairwise computations
will proceed as if the bond (or angle, etc.) were still turned on.
Several keywords can be appended to the argument list to alter the
default behaviors.
@ -138,9 +153,11 @@ operation, after (optional) removal. It re-computes the pairwise 1--2,
turned-off bonds the same as turned-on. Thus, turned-off bonds must
be removed if you wish to change the weighting list.
Note that the choice of *remove* and *special* options affects how
1--2, 1--3, 1--4 pairwise interactions will be computed across bonds that
have been modified by the delete_bonds command.
.. note::
The choice of *remove* and *special* options affects how 1--2,
1--3, 1--4 pairwise interactions will be computed across bonds
that have been modified by the delete_bonds command.
Restrictions
""""""""""""

View File

@ -57,6 +57,7 @@ ComputeTempBody::ComputeTempBody(LAMMPS *lmp, int narg, char **arg) :
if (strcmp(arg[iarg],"bias") == 0) {
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "compute temp/body bias", error);
tempbias = 1;
delete[] id_bias;
id_bias = utils::strdup(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"dof") == 0) {

View File

@ -33,8 +33,9 @@ using namespace LAMMPS_NS;
using namespace FixConst;
/* ---------------------------------------------------------------------- */
FixBrownianBase::FixBrownianBase(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
FixBrownianBase::FixBrownianBase(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg), gamma_t_inv(nullptr), gamma_r_inv(nullptr), gamma_t_invsqrt(nullptr),
gamma_r_invsqrt(nullptr), dipole_body(nullptr), rng(nullptr)
{
time_integrate = 1;
@ -47,18 +48,18 @@ FixBrownianBase::FixBrownianBase(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, n
planar_rot_flag = 0;
g2 = 0.0;
if (narg < 5) error->all(FLERR, "Illegal fix brownian command.");
if (narg < 5) utils::missing_cmd_args(FLERR, "fix brownian", error);
temp = utils::numeric(FLERR, arg[3], false, lmp);
if (temp <= 0) error->all(FLERR, "Fix brownian temp must be > 0.");
if (temp <= 0) error->all(FLERR, "Fix brownian temp must be > 0.0");
seed = utils::inumeric(FLERR, arg[4], false, lmp);
if (seed <= 0) error->all(FLERR, "Fix brownian seed must be > 0.");
if (seed <= 0) error->all(FLERR, "Fix brownian seed must be > 0");
int iarg = 5;
while (iarg < narg) {
if (strcmp(arg[iarg], "rng") == 0) {
if (narg == iarg + 1) error->all(FLERR, "Illegal fix brownian command.");
if (narg < iarg + 1) utils::missing_cmd_args(FLERR, "fix brownian rng", error);
if (strcmp(arg[iarg + 1], "uniform") == 0) {
noise_flag = 1;
} else if (strcmp(arg[iarg + 1], "gaussian") == 0) {
@ -67,13 +68,14 @@ FixBrownianBase::FixBrownianBase(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, n
} else if (strcmp(arg[iarg + 1], "none") == 0) {
noise_flag = 0;
} else {
error->all(FLERR, "Illegal fix brownian command.");
error->all(FLERR, "Unknown fix brownian rng keyword {}", arg[iarg + 1]);
}
iarg = iarg + 2;
} else if (strcmp(arg[iarg], "dipole") == 0) {
if (narg == iarg + 3) error->all(FLERR, "Illegal fix brownian command.");
if (narg < iarg + 3) utils::missing_cmd_args(FLERR, "fix brownian dipole", error);
dipole_flag = 1;
delete[] dipole_body;
dipole_body = new double[3];
dipole_body[0] = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
@ -82,9 +84,11 @@ FixBrownianBase::FixBrownianBase(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, n
iarg = iarg + 4;
} else if (strcmp(arg[iarg], "gamma_t_eigen") == 0) {
if (narg == iarg + 3) error->all(FLERR, "Illegal fix brownian command.");
if (narg < iarg + 3) utils::missing_cmd_args(FLERR, "fix brownian gamma_t_eigen", error);
gamma_t_eigen_flag = 1;
delete[] gamma_t_inv;
delete[] gamma_t_invsqrt;
gamma_t_inv = new double[3];
gamma_t_invsqrt = new double[3];
gamma_t_inv[0] = 1. / utils::numeric(FLERR, arg[iarg + 1], false, lmp);
@ -111,6 +115,8 @@ FixBrownianBase::FixBrownianBase(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, n
if (narg == iarg + 3) error->all(FLERR, "Illegal fix brownian command.");
gamma_r_eigen_flag = 1;
delete[] gamma_r_inv;
delete[] gamma_r_invsqrt;
gamma_r_inv = new double[3];
gamma_r_invsqrt = new double[3];

View File

@ -39,6 +39,8 @@ using MathConst::RAD2DEG;
enum { DEGREE, RADIAN, COSINE };
static constexpr double BIG = 1.0e20;
/* ----------------------------------------------------------------------
compute angular distribution functions for I, J, K atoms
---------------------------------------------------------------------- */
@ -133,15 +135,15 @@ ComputeADF::ComputeADF(LAMMPS *lmp, int narg, char **arg) :
utils::bounds(FLERR,arg[iarg+1],1,atom->ntypes,jlo[m],jhi[m],error);
utils::bounds(FLERR,arg[iarg+2],1,atom->ntypes,klo[m],khi[m],error);
if ((ilo[m] > ihi[m]) || (jlo[m] > jhi[m]) || (klo[m] > khi[m]))
error->all(FLERR,"Illegal compute adf command");
error->all(FLERR,"Illegal compute adf command index range");
rcutinnerj[m] = utils::numeric(FLERR,arg[iarg+3],false,lmp);
rcutouterj[m] = utils::numeric(FLERR,arg[iarg+4],false,lmp);
if (rcutinnerj[m] < 0.0 || rcutinnerj[m] >= rcutouterj[m])
error->all(FLERR,"Illegal compute adf command");
error->all(FLERR,"Illegal compute adf command j-cutoff");
rcutinnerk[m] = utils::numeric(FLERR,arg[iarg+5],false,lmp);
rcutouterk[m] = utils::numeric(FLERR,arg[iarg+6],false,lmp);
if (rcutinnerk[m] < 0.0 || rcutinnerk[m] >= rcutouterk[m])
error->all(FLERR,"Illegal compute adf command");
error->all(FLERR,"Illegal compute adf command k-cutoff");
iarg += nargsperadf;
}
}
@ -290,8 +292,8 @@ void ComputeADF::init()
double skin = neighbor->skin;
mycutneigh = maxouter + skin;
if (mycutneigh > comm->cutghostuser)
error->all(FLERR,"Compute adf outer cutoff exceeds ghost atom range - "
"use comm_modify cutoff command");
error->all(FLERR,"Compute adf outer cutoff {} exceeds ghost atom range {} - "
"use comm_modify cutoff command", mycutneigh, comm->cutghostuser);
}
// assign ordinate values to 1st column of output array
@ -328,6 +330,7 @@ void ComputeADF::init()
if (mycutneigh > 0.0) {
if ((neighbor->style == Neighbor::MULTI) || (neighbor->style == Neighbor::MULTI_OLD))
error->all(FLERR, "Compute adf with custom cutoffs requires neighbor style 'bin' or 'nsq'");
req->set_cutoff(mycutneigh);
}
}

View File

@ -74,14 +74,13 @@ static constexpr double SHIFT = 0.0;
/* ---------------------------------------------------------------------- */
FixTTMMod::FixTTMMod(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg),
random(nullptr), gfactor1(nullptr), gfactor2(nullptr), ratio(nullptr), flangevin(nullptr),
T_electron(nullptr), T_electron_old(nullptr), net_energy_transfer(nullptr),
net_energy_transfer_all(nullptr)
Fix(lmp, narg, arg), infile(nullptr), outfile(nullptr), random(nullptr), gfactor1(nullptr),
gfactor2(nullptr), ratio(nullptr), flangevin(nullptr), T_electron(nullptr),
T_electron_old(nullptr), net_energy_transfer(nullptr), net_energy_transfer_all(nullptr)
{
if (lmp->citeme) lmp->citeme->add(cite_fix_ttm_mod);
if (narg < 8) error->all(FLERR,"Illegal fix ttm/mod command");
if (narg < 8) utils::missing_cmd_args(FLERR, "fix ttm/mod", error);
vector_flag = 1;
size_vector = 2;
@ -103,27 +102,29 @@ FixTTMMod::FixTTMMod(LAMMPS *lmp, int narg, char **arg) :
int iarg = 8;
while (iarg < narg) {
if (strcmp(arg[iarg],"set") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix ttm/mod command");
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix ttm/mod set", error);
tinit = utils::numeric(FLERR,arg[iarg+1],false,lmp);
if (tinit <= 0.0)
error->all(FLERR,"Fix ttm/mod initial temperature must be > 0.0");
iarg += 2;
} else if (strcmp(arg[iarg],"infile") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix ttm/mod command");
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix ttm/mod infile", error);
delete[] infile;
infile = utils::strdup(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"outfile") == 0) {
if (iarg+3 > narg) error->all(FLERR,"Illegal fix ttm/mod command");
if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "fix ttm/mod outfile", error);
delete[] outfile;
outevery = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
outfile = utils::strdup(arg[iarg+2]);
iarg += 3;
} else error->all(FLERR,"Illegal fix ttm/mod command");
} else error->all(FLERR,"Unknown fix ttm/mod keyword {}", arg[iarg]);
}
// error check
if (seed <= 0)
error->all(FLERR,"Invalid random number seed in fix ttm/mod command");
error->all(FLERR,"Invalid random number seed {} in fix ttm/mod command", seed);
if (nxgrid <= 0 || nygrid <= 0 || nzgrid <= 0)
error->all(FLERR,"Fix ttm/mod grid sizes must be > 0");
@ -152,7 +153,8 @@ FixTTMMod::FixTTMMod(LAMMPS *lmp, int narg, char **arg) :
if (v_0 < 0.0) error->all(FLERR,"Fix ttm/mod v_0 must be >= 0.0");
if (ionic_density <= 0.0) error->all(FLERR,"Fix ttm/mod ionic_density must be > 0.0");
if (surface_l < 0) error->all(FLERR,"Surface coordinates must be >= 0");
if (surface_l >= surface_r) error->all(FLERR, "Left surface coordinate must be less than right surface coordinate");
if (surface_l >= surface_r)
error->all(FLERR, "Left surface coordinate must be less than right surface coordinate");
// initialize Marsaglia RNG with processor-unique seed
@ -168,10 +170,8 @@ FixTTMMod::FixTTMMod(LAMMPS *lmp, int narg, char **arg) :
memory->create(T_electron_old,nzgrid,nygrid,nxgrid,"ttm/mod:T_electron_old");
memory->create(T_electron_first,nzgrid,nygrid,nxgrid,"ttm/mod:T_electron_first");
memory->create(T_electron,nzgrid,nygrid,nxgrid,"ttm/mod:T_electron");
memory->create(net_energy_transfer,nzgrid,nygrid,nxgrid,
"ttm/mod:net_energy_transfer");
memory->create(net_energy_transfer_all,nzgrid,nygrid,nxgrid,
"ttm/mod:net_energy_transfer_all");
memory->create(net_energy_transfer,nzgrid,nygrid,nxgrid,"ttm/mod:net_energy_transfer");
memory->create(net_energy_transfer_all,nzgrid,nygrid,nxgrid,"ttm/mod:net_energy_transfer_all");
flangevin = nullptr;
grow_arrays(atom->nmax);

View File

@ -29,7 +29,7 @@ using namespace LAMMPS_NS;
using namespace MathConst;
static constexpr double SMALL = 0.001;
static constexpr double SMALLG = 2.0e-308;
static constexpr double SMALLG = 2.3e-308;
/* ---------------------------------------------------------------------- */

View File

@ -27,7 +27,7 @@
using namespace LAMMPS_NS;
using namespace MathConst;
static constexpr double SMALL = 2.0e-308;
static constexpr double SMALL = 2.3e-308;
/* ---------------------------------------------------------------------- */

View File

@ -62,7 +62,9 @@ static constexpr double autoev = 27.21140795; // atomic units (Hartree) to eV
Constructor (Required)
------------------------------------------------------------------------- */
PairDispersionD3::PairDispersionD3(LAMMPS *lmp) : Pair(lmp)
PairDispersionD3::PairDispersionD3(LAMMPS *lmp) :
Pair(lmp), r2r4(nullptr), rcov(nullptr), mxci(nullptr), r0ab(nullptr), c6ab(nullptr),
cn(nullptr), dc6(nullptr)
{
nmax = 0;
comm_forward = 2;
@ -72,6 +74,8 @@ PairDispersionD3::PairDispersionD3(LAMMPS *lmp) : Pair(lmp)
manybody_flag = 1;
one_coeff = 1;
single_enable = 0;
s6 = s8 = s18 = rs6 = rs8 = rs18 = a1 = a2 = alpha = alpha6 = alpha8 = 0.0;
}
/* ----------------------------------------------------------------------
@ -481,8 +485,6 @@ void PairDispersionD3::compute(int eflag, int vflag)
int jnum = numneigh[i];
int *jlist = firstneigh[i];
// fprintf(stderr, "> i, type[i], CN[i], C6[i,i] : %d, %d, %f, %f\n", atom->tag[i], type[i], cn[i], get_dC6(type[i],type[i],cn[i],cn[i])[0]/(autoev*pow(autoang,6)));
for (int jj = 0; jj < jnum; jj++) {
int j = jlist[jj];
@ -513,6 +515,7 @@ void PairDispersionD3::compute(int eflag, int vflag)
double t6, t8, damp6, damp8, e6, e8;
double tmp6, tmp8, fpair1, fpair2, fpair;
t6 = t8 = e6 = e8 = evdwl = fpair = fpair1 = fpair2 = 0.0;
switch (dampingCode) {
case 1: { // zero
@ -1134,8 +1137,8 @@ void PairDispersionD3::set_funcpar(std::string &functional_name)
a1 = 0.3065;
s8 = 0.9147;
a2 = 5.0570;
break;
s6 = 0.64;
break;
case 17:
a1 = 0.0000;
s8 = 0.2130;

View File

@ -27,12 +27,10 @@ namespace LAMMPS_NS {
class PairDispersionD3 : public Pair {
public:
PairDispersionD3(class LAMMPS *);
~PairDispersionD3() override;
void compute(int, int) override;
void settings(int, char **) override;
void coeff(int, char **) override;
void init_style() override;
@ -45,45 +43,39 @@ class PairDispersionD3 : public Pair {
void unpack_reverse_comm(int, int *, double *) override;
protected:
int nmax;
double evdwl;
double rthr; // R^2 distance to cutoff for D3_calculation
double cn_thr; // R^2 distance to cutoff for CN_calculation
double rthr; // R^2 distance to cutoff for D3_calculation
double cn_thr; // R^2 distance to cutoff for CN_calculation
std::string damping_type; // damping function type
double s6, s8, s18, rs6, rs8, rs18; // XC parameters
std::string damping_type; // damping function type
double s6, s8, s18, rs6, rs8, rs18; // XC parameters
double a1, a2, alpha, alpha6, alpha8;
double* r2r4 = nullptr; // scale r4/r2 values of the atoms by sqrt(Z)
double* rcov = nullptr; // covalent radii
int* mxci = nullptr; // How large the grid for c6 interpolation
double *r2r4; // scale r4/r2 values of the atoms by sqrt(Z)
double *rcov; // covalent radii
int *mxci; // How large the grid for c6 interpolation
double **r0ab; // cut-off radii for all element pairs
double *****c6ab; // C6 for all element pairs
double *cn; // Coordination numbers
double *dc6; // dC6i(iat) saves dE_dsp/dCN(iat)
double** r0ab = nullptr; // cut-off radii for all element pairs
double***** c6ab = nullptr; // C6 for all element pairs
double* cn = nullptr; // Coordination numbers
double* dc6 = nullptr; // dC6i(iat) saves dE_dsp/dCN(iat)
int communicationStage; // communication stage
int communicationStage; // communication stage
void allocate();
virtual void set_funcpar(std::string&);
virtual void set_funcpar(std::string &);
void calc_coordination_number();
int find_atomic_number(std::string&);
std::vector<int> is_int_in_array(int*, int, int);
int find_atomic_number(std::string &);
std::vector<int> is_int_in_array(int *, int, int);
void read_r0ab(int*, int);
void set_limit_in_pars_array(int&, int&, int&, int&);
void read_c6ab(int*, int);
void read_r0ab(int *, int);
void set_limit_in_pars_array(int &, int &, int &, int &);
void read_c6ab(int *, int);
double* get_dC6(int, int, double, double);
double *get_dC6(int, int, double, double);
};
} // namespace LAMMPS_NS
#endif
#endif

View File

@ -163,6 +163,7 @@ FixWallGran::FixWallGran(LAMMPS *lmp, int narg, char **arg) :
} else if (strcmp(arg[iarg],"region") == 0) {
if (narg < iarg+2) error->all(FLERR,"Illegal fix wall/gran command");
wallstyle = REGION;
delete[] idregion;
idregion = utils::strdup(arg[iarg+1]);
iarg += 2;
// This option is only compatible with fix wall/gran/region
@ -205,6 +206,7 @@ FixWallGran::FixWallGran(LAMMPS *lmp, int narg, char **arg) :
} else if (strcmp(arg[iarg],"temperature") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix wall/gran command");
if (utils::strmatch(arg[iarg+1], "^v_")) {
delete[] tstr;
tstr = utils::strdup(arg[iarg+1] + 2);
} else {
Twall = utils::numeric(FLERR,arg[iarg+1],false,lmp);

View File

@ -45,7 +45,8 @@ FixEfieldLepton::FixEfieldLepton(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg), idregion(nullptr), region(nullptr)
{
if (domain->xperiodic || domain->yperiodic || domain->zperiodic) {
error->warning(FLERR, "Fix {} uses unwrapped coordinates", style);
if (comm->me == 0)
error->warning(FLERR, "Fix {} uses unwrapped coordinates", style);
}
if (narg < 4) utils::missing_cmd_args(FLERR, std::string("fix ") + style, error);
@ -57,6 +58,9 @@ FixEfieldLepton::FixEfieldLepton(LAMMPS *lmp, int narg, char **arg) :
respa_level_support = 1;
ilevel_respa = 0;
qe2f = force->qe2f;
mue2e = qe2f;
// optional args
int iarg = 4;
while (iarg < narg) {
@ -65,12 +69,13 @@ FixEfieldLepton::FixEfieldLepton(LAMMPS *lmp, int narg, char **arg) :
utils::missing_cmd_args(FLERR, std::string("fix ") + style + " region", error);
region = domain->get_region_by_id(arg[iarg + 1]);
if (!region) error->all(FLERR, "Region {} for fix {} does not exist", arg[iarg + 1], style);
delete[] idregion;
idregion = utils::strdup(arg[iarg + 1]);
iarg += 2;
} else if (strcmp(arg[iarg], "step") == 0) {
if (iarg + 2 > narg)
utils::missing_cmd_args(FLERR, std::string("fix ") + style + "step", error);
h = utils::numeric(FLERR, arg[iarg+1], false, lmp);
h = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
iarg += 2;
} else {
error->all(FLERR, "Unknown keyword for fix {} command: {}", style, arg[iarg]);
@ -126,15 +131,15 @@ void FixEfieldLepton::init()
}
if (utils::strmatch(update->integrate_style, "^respa")) {
ilevel_respa = (dynamic_cast<Respa *>(update->integrate))->nlevels - 1;
auto respa = dynamic_cast<Respa *>(update->integrate);
if (respa) ilevel_respa = respa->nlevels - 1;
if (respa_level >= 0) ilevel_respa = MIN(respa_level, ilevel_respa);
}
// unit conversion factors and restrictions (see issue #1377)
// unit conversion restrictions (see issue #1377)
char *unit_style = update->unit_style;
qe2f = force->qe2f;
mue2e = qe2f;
if (strcmp(unit_style, "electron") == 0 || strcmp(unit_style, "micro") == 0 || strcmp(unit_style, "nano") == 0) {
if (strcmp(unit_style, "electron") == 0 || strcmp(unit_style, "micro") == 0 ||
strcmp(unit_style, "nano") == 0) {
error->all(FLERR, "Fix {} does not support {} units", style, unit_style);
}
}
@ -145,9 +150,11 @@ void FixEfieldLepton::setup(int vflag)
{
if (utils::strmatch(update->integrate_style, "^respa")) {
auto respa = dynamic_cast<Respa *>(update->integrate);
respa->copy_flevel_f(ilevel_respa);
post_force_respa(vflag, ilevel_respa, 0);
respa->copy_f_flevel(ilevel_respa);
if (respa) {
respa->copy_flevel_f(ilevel_respa);
post_force_respa(vflag, ilevel_respa, 0);
respa->copy_f_flevel(ilevel_respa);
}
} else {
post_force(vflag);
}
@ -179,14 +186,14 @@ void FixEfieldLepton::post_force(int vflag)
auto dphi_x = parsed.differentiate("x").createCompiledExpression();
auto dphi_y = parsed.differentiate("y").createCompiledExpression();
auto dphi_z = parsed.differentiate("z").createCompiledExpression();
std::array<Lepton::CompiledExpression*, 3> dphis = {&dphi_x, &dphi_y, &dphi_z};
std::array<Lepton::CompiledExpression *, 3> dphis = {&dphi_x, &dphi_y, &dphi_z};
// array of vectors of ptrs to Lepton variable references
std::array<std::vector<double *>, 3> var_ref_ptrs{};
// fill ptr-vectors with Lepton refs as needed
const char* DIM_NAMES[] = {"x", "y", "z"};
if (atom->q_flag){
const char *DIM_NAMES[] = {"x", "y", "z"};
if (atom->q_flag) {
phi = parsed.createCompiledExpression();
for (size_t d = 0; d < 3; d++) {
try {
@ -205,13 +212,13 @@ void FixEfieldLepton::post_force(int vflag)
double *ptr = &((*dphis[j]).getVariableReference(DIM_NAMES[d]));
var_ref_ptrs[d].push_back(ptr);
e_uniform = false;
}
catch (Lepton::Exception &) {
} catch (Lepton::Exception &) {
// do nothing
}
}
if (!e_uniform && atom->mu_flag && h < 0) {
error->all(FLERR, "Fix {} requires keyword `step' for dipoles in a non-uniform electric field", style);
error->all(FLERR, "Fix {} requires keyword `step' for dipoles in a non-uniform electric field",
style);
}
// virial setup
@ -228,7 +235,6 @@ void FixEfieldLepton::post_force(int vflag)
double ex, ey, ez;
double fx, fy, fz;
double v[6], unwrap[3], dstep[3];
double xf, yf, zf, xb, yb, zb;
double exf, eyf, ezf, exb, eyb, ezb;
double mu_norm, h_mu;
@ -244,9 +250,7 @@ void FixEfieldLepton::post_force(int vflag)
// put unwrapped coords into Lepton variable refs
for (size_t d = 0; d < 3; d++) {
for (auto & var_ref_ptr : var_ref_ptrs[d]) {
*var_ref_ptr = unwrap[d];
}
for (auto &var_ref_ptr : var_ref_ptrs[d]) { *var_ref_ptr = unwrap[d]; }
}
// evaluate e-field, used by q and mu
@ -265,8 +269,8 @@ void FixEfieldLepton::post_force(int vflag)
}
if (atom->mu_flag) {
// dipoles
mu_norm = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]);
// dipoles
mu_norm = sqrt(mu[i][0] * mu[i][0] + mu[i][1] * mu[i][1] + mu[i][2] * mu[i][2]);
if (mu_norm > EPSILON) {
// torque = mu cross E
t[i][0] += mue2e * (ez * mu[i][1] - ey * mu[i][2]);
@ -285,9 +289,7 @@ void FixEfieldLepton::post_force(int vflag)
// one step forwards, two steps back ;)
for (size_t d = 0; d < 3; d++) {
for (auto & var_ref_ptr : var_ref_ptrs[d]) {
*var_ref_ptr += dstep[d];
}
for (auto &var_ref_ptr : var_ref_ptrs[d]) { *var_ref_ptr += dstep[d]; }
}
exf = -dphi_x.evaluate();
@ -295,9 +297,7 @@ void FixEfieldLepton::post_force(int vflag)
ezf = -dphi_z.evaluate();
for (size_t d = 0; d < 3; d++) {
for (auto & var_ref_ptr : var_ref_ptrs[d]) {
*var_ref_ptr -= 2*dstep[d];
}
for (auto &var_ref_ptr : var_ref_ptrs[d]) { *var_ref_ptr -= 2 * dstep[d]; }
}
exb = -dphi_x.evaluate();

View File

@ -44,6 +44,7 @@ double MEAM::G_gam(const double gamma, const int ibar, int &errorflag) const
// e.g. gsmooth_factor is 99, {:
// gsmooth_switchpoint = -0.99
// G = 0.01*(-0.99/gamma)**99
if (gamma == 0.0) return 0.0; // avoid division by zero. For gamma = 0.0 => G = 1 / inf
double G = 1 / (gsmooth_factor + 1) * pow((gsmooth_switchpoint / gamma), gsmooth_factor);
return sqrt(G);
} else {

View File

@ -581,9 +581,8 @@ FixIMD::FixIMD(LAMMPS *lmp, int narg, char **arg) :
msglen += 3*4*num_coords+IMDHEADERSIZE;
}
msgdata = new char[msglen];
}
else {
msglen = 3*sizeof(float)*num_coords+IMDHEADERSIZE;
} else {
msglen = 3*(int)sizeof(float)*num_coords+IMDHEADERSIZE;
msgdata = new char[msglen];
}

View File

@ -982,10 +982,14 @@ double EAPOD::peratom_environment_descriptors(double *cb, double *bd, double *tm
D[j] = 1.0 / sum;
}
double sum = 0;
double sum = 0.0;
for (int j = 0; j < nClusters; j++) sum += D[j];
double sumD = sum;
for (int j = 0; j < nClusters; j++) P[j] = D[j]/sum;
if (sum != 0.0) {
for (int j = 0; j < nClusters; j++) P[j] = D[j]/sum;
} else {
for (int j = 0; j < nClusters; j++) P[j] = 0.0;
}
int nc = nCoeffPerElement*(ti[0]-1);
double ei = coeff[0 + nc];
@ -1008,13 +1012,13 @@ double EAPOD::peratom_environment_descriptors(double *cb, double *bd, double *tm
}
for (int m = 0; m<Mdesc; m++) {
double S1 = 1/sumD;
double S2 = sumD*sumD;
double S1 = 1.0/sumD;
double S2 = S1*S1;
double sum = 0.0;
for (int j=0; j<nClusters; j++) {
double dP_dB = 0.0;
for (int k = 0; k < nClusters; k++) {
double dP_dD = -D[j] / S2;
double dP_dD = -D[j] * S2;
if (k==j) dP_dD += S1;
double dD_dB = 0.0;
double D2 = 2 * D[k] * D[k];
@ -2844,11 +2848,11 @@ void EAPOD::peratomenvironment_descriptors(double *P, double *dP_dR, double *B,
DGEMM(&chn, &chn, &nClusters, &Mdesc, &nComponents, &alpha, dD_dpca, &nClusters, ProjMat, &nComponents, &beta, dD_dB, &nClusters);
// calculate dP_dD
double S1 = 1 / sumD;
double S2 = sumD * sumD;
double S1 = 1.0 / sumD;
double S2 = S1 * S1;
for (int k = 0; k < nClusters; k++) {
for (int j = 0; j < nClusters; j++) {
dP_dD[j + k * nClusters] = -D[j] / S2;
dP_dD[j + k * nClusters] = -D[j] * S2;
}
}
for (int j = 0; j < nClusters; j++) {

View File

@ -204,6 +204,7 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) :
delete[] filedel;
filedel = utils::strdup(arg[iarg + 1]);
if (comm->me == 0) {
if (fdel) fclose(fdel);
fdel = fopen(filedel, "w");
if (!fdel)
error->one(FLERR, "Cannot open fix reaxff/species delete file {}: {}", filedel,

View File

@ -13,14 +13,16 @@
------------------------------------------------------------------------- */
#include "compute_rigid_local.h"
#include <cstring>
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "error.h"
#include "modify.h"
#include "fix_rigid_small.h"
#include "memory.h"
#include "error.h"
#include "update.h"
#include <cstring>
using namespace LAMMPS_NS;
@ -98,8 +100,8 @@ ComputeRigidLocal::~ComputeRigidLocal()
{
memory->destroy(vlocal);
memory->destroy(alocal);
delete [] idrigid;
delete [] rstyle;
delete[] idrigid;
delete[] rstyle;
}
/* ---------------------------------------------------------------------- */
@ -108,16 +110,11 @@ void ComputeRigidLocal::init()
{
// set fixrigid
int ifix = modify->find_fix(idrigid);
if (ifix < 0)
error->all(FLERR,"FixRigidSmall ID for compute rigid/local does not exist");
fixrigid = dynamic_cast<FixRigidSmall *>(modify->fix[ifix]);
int flag = 0;
if (strstr(fixrigid->style,"rigid/") == nullptr) flag = 1;
if (strstr(fixrigid->style,"/small") == nullptr) flag = 1;
if (flag)
error->all(FLERR,"Compute rigid/local does not use fix rigid/small fix");
auto ifix = modify->get_fix_by_id(idrigid);
if (!ifix) error->all(FLERR,"FixRigidSmall ID {} for compute rigid/local does not exist", idrigid);
fixrigid = dynamic_cast<FixRigidSmall *>(ifix);
if (!fixrigid)
error->all(FLERR,"Fix ID {} for compute rigid/local does not point to fix rigid/small", idrigid);
// do initial memory allocation so that memory_usage() is correct

View File

@ -49,7 +49,6 @@ FixAppendAtoms::FixAppendAtoms(LAMMPS *lmp, int narg, char **arg) :
scaleflag = 1;
spatflag=0;
spatialid = nullptr;
size = 0.0;
xloflag = xhiflag = yloflag = yhiflag = zloflag = zhiflag = 0;
@ -60,9 +59,6 @@ FixAppendAtoms::FixAppendAtoms(LAMMPS *lmp, int narg, char **arg) :
rany = 0.0;
ranz = 0.0;
randomx = nullptr;
randomt = nullptr;
if (domain->lattice->nbasis == 0)
error->all(FLERR,"Fix append/atoms requires a lattice be defined");
@ -123,6 +119,7 @@ FixAppendAtoms::FixAppendAtoms(LAMMPS *lmp, int narg, char **arg) :
if (strcmp(arg[iarg+1],"f_") == 0)
error->all(FLERR, "Bad fix ID in fix append/atoms command");
spatflag = 1;
delete[] spatialid;
spatialid = utils::strdup(arg[iarg+1]+2);
spatlead = utils::numeric(FLERR,arg[iarg+2],false,lmp);
iarg += 3;
@ -152,6 +149,7 @@ FixAppendAtoms::FixAppendAtoms(LAMMPS *lmp, int narg, char **arg) :
ranz = utils::numeric(FLERR,arg[iarg+3],false,lmp);
xseed = utils::inumeric(FLERR,arg[iarg+4],false,lmp);
if (xseed <= 0) error->all(FLERR,"Illegal fix append/atoms command");
delete randomx;
randomx = new RanMars(lmp,xseed + comm->me);
iarg += 5;
} else if (strcmp(arg[iarg],"temp") == 0) {
@ -165,7 +163,10 @@ FixAppendAtoms::FixAppendAtoms(LAMMPS *lmp, int narg, char **arg) :
if (t_period <= 0) error->all(FLERR,"Illegal fix append/atoms command");
if (t_extent <= 0) error->all(FLERR,"Illegal fix append/atoms command");
if (tseed <= 0) error->all(FLERR,"Illegal fix append/atoms command");
delete randomt;
randomt = new RanMars(lmp,tseed + comm->me);
delete[] gfactor1;
delete[] gfactor2;
gfactor1 = new double[atom->ntypes+1];
gfactor2 = new double[atom->ntypes+1];
iarg += 5;

View File

@ -39,10 +39,8 @@ FixWallPiston::FixWallPiston(LAMMPS *lmp, int narg, char **arg) :
force_reneighbor = 1;
next_reneighbor = -1;
if (narg < 4) error->all(FLERR,"Illegal fix wall/piston command");
if (narg < 4) utils::missing_cmd_args(FLERR,"fix wall/piston", error);
randomt = nullptr;
gfactor1 = gfactor2 = nullptr;
tempflag = 0;
scaleflag = 1;
roughflag = 0;
@ -92,6 +90,9 @@ FixWallPiston::FixWallPiston(LAMMPS *lmp, int narg, char **arg) :
if (t_period <= 0) error->all(FLERR,"Illegal fix wall/piston command");
if (t_extent <= 0) error->all(FLERR,"Illegal fix wall/piston command");
if (tseed <= 0) error->all(FLERR,"Illegal fix wall/piston command");
delete randomt;
delete[] gfactor1;
delete[] gfactor2;
randomt = new RanMars(lmp,tseed + comm->me);
gfactor1 = new double[atom->ntypes+1];
gfactor2 = new double[atom->ntypes+1];

View File

@ -55,16 +55,10 @@ ComputeVoronoi::ComputeVoronoi(LAMMPS *lmp, int narg, char **arg) :
surface = VOROSURF_NONE;
maxedge = 0;
fthresh = ethresh = 0.0;
radstr = nullptr;
onlyGroup = false;
occupation = false;
con_mono = nullptr;
con_poly = nullptr;
tags = nullptr;
oldmaxtag = 0;
occvec = sendocc = lroot = lnext = nullptr;
faces = nullptr;
int iarg = 3;
while (iarg<narg) {
@ -79,6 +73,7 @@ ComputeVoronoi::ComputeVoronoi(LAMMPS *lmp, int narg, char **arg) :
else if (strcmp(arg[iarg], "radius") == 0) {
if (iarg + 2 > narg || strstr(arg[iarg+1],"v_") != arg[iarg+1] )
error->all(FLERR,"Illegal compute voronoi/atom command");
delete[] radstr;
radstr = utils::strdup(&arg[iarg+1][2]);
iarg += 2;
}

View File

@ -168,30 +168,24 @@ ComputeRDF::~ComputeRDF()
void ComputeRDF::init()
{
const double skin = neighbor->skin;
if (!force->pair && !cutflag)
error->all(FLERR,"Compute rdf requires a pair style or an explicit cutoff");
if (cutflag) {
double skin = neighbor->skin;
mycutneigh = cutoff_user + skin;
double cutghost; // as computed by Neighbor and Comm
if (force->pair)
cutghost = MAX(force->pair->cutforce+skin,comm->cutghostuser);
else
cutghost = comm->cutghostuser;
if (force->pair) cutghost = MAX(force->pair->cutforce+skin,comm->cutghostuser);
else cutghost = comm->cutghostuser;
if (mycutneigh > cutghost)
error->all(FLERR,"Compute rdf cutoff exceeds ghost atom range - "
"use comm_modify cutoff command");
if (force->pair && mycutneigh < force->pair->cutforce + skin)
if (comm->me == 0)
error->warning(FLERR,"Compute rdf cutoff less than neighbor cutoff - "
"forcing a needless neighbor list build");
error->all(FLERR,"Compute rdf cutoff plus skin {} exceeds ghost atom range {} - "
"use comm_modify cutoff command to increase it", mycutneigh, cutghost);
delr = cutoff_user / nbin;
} else delr = force->pair->cutforce / nbin;
} delr = force->pair->cutforce / nbin;
delrinv = 1.0/delr;

View File

@ -218,7 +218,7 @@ ComputeReduce::ComputeReduce(LAMMPS *lmp, int narg, char **arg) :
input_mode = PERATOM;
else if (strcmp(arg[iarg + 1], "local") == 0)
input_mode = LOCAL;
iarg += 2;
iarg += 1;
} else
error->all(FLERR, "Unknown compute {} keyword: {}", style, arg[iarg]);
}

View File

@ -103,7 +103,7 @@ void CreateAtoms::command(int narg, char **arg)
style = REGION;
if (narg < 3) utils::missing_cmd_args(FLERR, "create_atoms region", error);
region = domain->get_region_by_id(arg[2]);
if (!region) error->all(FLERR, "Create_atoms region {} does not exist", arg[2]);
if (!region) error->all(FLERR, 2, "Create_atoms region {} does not exist", arg[2]);
region->init();
region->prematch();
iarg = 3;
@ -127,7 +127,7 @@ void CreateAtoms::command(int narg, char **arg)
region = nullptr;
else {
region = domain->get_region_by_id(arg[4]);
if (!region) error->all(FLERR, "Create_atoms region {} does not exist", arg[4]);
if (!region) error->all(FLERR, 4, "Create_atoms region {} does not exist", arg[4]);
region->init();
region->prematch();
}
@ -138,7 +138,7 @@ void CreateAtoms::command(int narg, char **arg)
meshfile = arg[2];
iarg = 3;
} else
error->all(FLERR, "Unknown create_atoms command option {}", arg[1]);
error->all(FLERR, 1, "Unknown create_atoms command option {}", arg[1]);
// process optional keywords

View File

@ -184,12 +184,12 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
char *id;
int igrid,idata,index;
int iflag =
utils::check_grid_reference((char *) "Dump image",
arg[iarg+1],nevery,id,
igrid,idata,index,lmp);
int iflag = utils::check_grid_reference((char *) "Dump image", arg[iarg+1], nevery, id,
igrid,idata,index,lmp);
if (iflag < 0) error->all(FLERR,"Invalid grid reference in dump image command");
delete[] id_grid_compute;
delete[] id_grid_fix;
if (iflag == ArgInfo::COMPUTE) id_grid_compute = utils::strdup(id);
else if (iflag == ArgInfo::FIX) id_grid_fix = utils::strdup(id);
delete[] id;
@ -252,6 +252,7 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
} else if (strcmp(arg[iarg],"view") == 0) {
if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
if (utils::strmatch(arg[iarg+1],"^v_")) {
delete[] thetastr;
thetastr = utils::strdup(arg[iarg+1]+2);
} else {
const double theta = utils::numeric(FLERR,arg[iarg+1],false,lmp);
@ -260,6 +261,7 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
image->theta = DEG2RAD * theta;
}
if (utils::strmatch(arg[iarg+2],"^v_")) {
delete[] phistr;
phistr = utils::strdup(arg[iarg+2]+2);
} else {
image->phi = DEG2RAD * utils::numeric(FLERR,arg[iarg+2],false,lmp);
@ -272,14 +274,17 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
else if (strcmp(arg[iarg+1],"d") == 0) cflag = DYNAMIC;
else error->all(FLERR,"Illegal dump image command");
if (utils::strmatch(arg[iarg+2],"^v_")) {
delete[] cxstr;
cxstr = utils::strdup(arg[iarg+2]+2);
cflag = DYNAMIC;
} else cx = utils::numeric(FLERR,arg[iarg+2],false,lmp);
if (utils::strmatch(arg[iarg+3],"^v_")) {
delete[] cystr;
cystr = utils::strdup(arg[iarg+3]+2);
cflag = DYNAMIC;
} else cy = utils::numeric(FLERR,arg[iarg+3],false,lmp);
if (utils::strmatch(arg[iarg+4],"^v_")) {
delete[] czstr;
czstr = utils::strdup(arg[iarg+4]+2);
cflag = DYNAMIC;
} else cz = utils::numeric(FLERR,arg[iarg+4],false,lmp);
@ -288,12 +293,15 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
} else if (strcmp(arg[iarg],"up") == 0) {
if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command");
if (utils::strmatch(arg[iarg+1],"^v_")) {
delete[] upxstr;
upxstr = utils::strdup(arg[iarg+1]+2);
} else image->up[0] = utils::numeric(FLERR,arg[iarg+1],false,lmp);
if (utils::strmatch(arg[iarg+2],"^v_")) {
delete[] upystr;
upystr = utils::strdup(arg[iarg+2]+2);
} else image->up[1] = utils::numeric(FLERR,arg[iarg+2],false,lmp);
if (utils::strmatch(arg[iarg+3],"^v_")) {
delete[] upzstr;
upzstr = utils::strdup(arg[iarg+3]+2);
} else image->up[2] = utils::numeric(FLERR,arg[iarg+3],false,lmp);
iarg += 4;
@ -301,6 +309,7 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
} else if (strcmp(arg[iarg],"zoom") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
if (utils::strmatch(arg[iarg+1],"^v_")) {
delete[] zoomstr;
zoomstr = utils::strdup(arg[iarg+1]+2);
} else {
double zoom = utils::numeric(FLERR,arg[iarg+1],false,lmp);

View File

@ -114,37 +114,27 @@ void Error::universe_warn(const std::string &file, int line, const std::string &
force MPI_Abort if running in multi-partition mode
------------------------------------------------------------------------- */
void Error::all(const std::string &file, int line, const std::string &str)
void Error::all(const std::string &file, int line, int failed, const std::string &str)
{
MPI_Barrier(world);
int me;
std::string lastcmd = "(unknown)";
std::string mesg = "ERROR: " + str + fmt::format(" ({}:{})\n", truncpath(file), line);
MPI_Comm_rank(world,&me);
// add text about the input following the error message
if (me == 0) {
std::string mesg = "ERROR: " + str;
if (input && input->line) lastcmd = input->line;
try {
mesg += fmt::format(" ({}:{})\nLast command: {}\n", truncpath(file),line,lastcmd);
} catch (fmt::format_error &) {
; // do nothing
}
utils::logmesg(lmp,mesg);
}
if (failed > NOLASTLINE) mesg += utils::point_to_error(input, failed);
if (comm->me == 0) utils::logmesg(lmp,mesg);
// allow commands if an exception was caught in a run
// update may be a null pointer when catching command-line errors
if (update) update->whichflag = 0;
std::string msg = fmt::format("ERROR: {} ({}:{})\n", str, truncpath(file), line);
if (universe->nworlds > 1)
throw LAMMPSAbortException(msg, universe->uworld);
throw LAMMPSAbortException(mesg, universe->uworld);
else
throw LAMMPSException(msg);
throw LAMMPSException(mesg);
}
/* ----------------------------------------------------------------------
@ -154,15 +144,13 @@ void Error::all(const std::string &file, int line, const std::string &str)
forces abort of entire world (and universe) if any proc in world calls
------------------------------------------------------------------------- */
void Error::one(const std::string &file, int line, const std::string &str)
void Error::one(const std::string &file, int line, int failed, const std::string &str)
{
int me;
std::string lastcmd = "(unknown)";
MPI_Comm_rank(world,&me);
if (input && input->line) lastcmd = input->line;
std::string mesg = fmt::format("ERROR on proc {}: {} ({}:{})\nLast command: {}\n",
me,str,truncpath(file),line,lastcmd);
std::string mesg = fmt::format("ERROR on proc {}: {} ({}:{})\n", comm->me, str,
truncpath(file), line);
if (failed > NOPOINTER) mesg += utils::point_to_error(input, failed);
utils::logmesg(lmp,mesg);
if (universe->nworlds > 1)
@ -177,27 +165,27 @@ void Error::one(const std::string &file, int line, const std::string &str)
}
/* ----------------------------------------------------------------------
forward vararg version to single string version
forward vararg versions to single string version
------------------------------------------------------------------------- */
void Error::_all(const std::string &file, int line, fmt::string_view format,
void Error::_all(const std::string &file, int line, int failed, fmt::string_view format,
fmt::format_args args)
{
try {
all(file,line,fmt::vformat(format, args));
all(file, line, failed, fmt::vformat(format, args));
} catch (fmt::format_error &e) {
all(file,line,e.what());
all(file, line, NOPOINTER, e.what());
}
exit(1); // to trick "smart" compilers into believing this does not return
}
void Error::_one(const std::string &file, int line, fmt::string_view format,
void Error::_one(const std::string &file, int line, int failed, fmt::string_view format,
fmt::format_args args)
{
try {
one(file,line,fmt::vformat(format, args));
one(file, line, failed, fmt::vformat(format, args));
} catch (fmt::format_error &e) {
one(file,line,e.what());
one(file, line, NOPOINTER, e.what());
}
exit(1); // to trick "smart" compilers into believing this does not return
}

View File

@ -27,18 +27,50 @@ class Error : protected Pointers {
[[noreturn]] void universe_one(const std::string &, int, const std::string &);
void universe_warn(const std::string &, int, const std::string &);
[[noreturn]] void all(const std::string &, int, const std::string &);
template <typename... Args>
[[noreturn]] void all(const std::string &file, int line, const std::string &format, Args &&...args)
static constexpr int NOPOINTER = -2;
static constexpr int NOLASTLINE = -3;
// regular error calls
[[noreturn]] void all(const std::string &file, int line, const std::string &str)
{
_all(file, line, format, fmt::make_format_args(args...));
all(file, line, NOPOINTER, str);
}
[[noreturn]] void one(const std::string &, int, const std::string &);
template <typename... Args>
[[noreturn]] void one(const std::string &file, int line, const std::string &format, Args &&...args)
[[noreturn]] void all(const std::string &file, int line, const std::string &format,
Args &&...args)
{
_one(file, line, format, fmt::make_format_args(args...));
_all(file, line, NOPOINTER, format, fmt::make_format_args(args...));
}
[[noreturn]] void one(const std::string &file, int line, const std::string &str)
{
one(file, line, NOPOINTER, str);
}
template <typename... Args>
[[noreturn]] void one(const std::string &file, int line, const std::string &format,
Args &&...args)
{
_one(file, line, NOPOINTER, format, fmt::make_format_args(args...));
}
// overloaded error calls indicating faulty argument in command line
[[noreturn]] void all(const std::string &, int, int, const std::string &);
template <typename... Args>
[[noreturn]] void all(const std::string &file, int line, int failed, const std::string &format,
Args &&...args)
{
_all(file, line, failed, format, fmt::make_format_args(args...));
}
[[noreturn]] void one(const std::string &, int, int, const std::string &);
template <typename... Args>
[[noreturn]] void one(const std::string &file, int line, int failed, const std::string &format,
Args &&...args)
{
_one(file, line, failed, format, fmt::make_format_args(args...));
}
void warning(const std::string &, int, const std::string &);
@ -72,8 +104,8 @@ class Error : protected Pointers {
int numwarn, maxwarn, allwarn;
// internal versions that accept explicit fmtlib arguments
[[noreturn]] void _all(const std::string &, int, fmt::string_view, fmt::format_args args);
[[noreturn]] void _one(const std::string &, int, fmt::string_view, fmt::format_args args);
[[noreturn]] void _all(const std::string &, int, int, fmt::string_view, fmt::format_args args);
[[noreturn]] void _one(const std::string &, int, int, fmt::string_view, fmt::format_args args);
void _warning(const std::string &, int, fmt::string_view, fmt::format_args args);
void _message(const std::string &, int, fmt::string_view, fmt::format_args args);
};

View File

@ -85,11 +85,13 @@ FixAddForce::FixAddForce(LAMMPS *lmp, int narg, char **arg) :
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "fix addforce region", error);
region = domain->get_region_by_id(arg[iarg + 1]);
if (!region) error->all(FLERR, "Region {} for fix addforce does not exist", arg[iarg + 1]);
delete[] idregion;
idregion = utils::strdup(arg[iarg + 1]);
iarg += 2;
} else if (strcmp(arg[iarg], "energy") == 0) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "fix addforce energy", error);
if (utils::strmatch(arg[iarg + 1], "^v_")) {
delete[] estr;
estr = utils::strdup(arg[iarg + 1] + 2);
} else
error->all(FLERR, "Invalid fix addforce energy argument: {}", arg[iarg + 1]);

View File

@ -42,19 +42,20 @@ enum{DISCARD,KEEP};
static constexpr int OFFSET = 16384;
// clang-format on
/* ---------------------------------------------------------------------- */
FixAveGrid::FixAveGrid(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg), id_bias(nullptr), which(nullptr), argindex(nullptr), ids(nullptr),
value2index(nullptr), value2grid(nullptr), value2data(nullptr), grid2d(nullptr), grid3d(nullptr),
grid_buf1(nullptr), grid_buf2(nullptr), grid_output(nullptr), grid_sample(nullptr),
grid_nfreq(nullptr), grid_running(nullptr), grid_window(nullptr), grid2d_previous(nullptr),
grid3d_previous(nullptr), grid_sample_previous(nullptr), grid_nfreq_previous(nullptr),
grid_running_previous(nullptr), grid_window_previous(nullptr), bin(nullptr), skip(nullptr),
vresult(nullptr)
Fix(lmp, narg, arg), id_bias(nullptr), which(nullptr), argindex(nullptr), ids(nullptr),
value2index(nullptr), value2grid(nullptr), value2data(nullptr), grid2d(nullptr),
grid3d(nullptr), grid_buf1(nullptr), grid_buf2(nullptr), grid_output(nullptr),
grid_sample(nullptr), grid_nfreq(nullptr), grid_running(nullptr), grid_window(nullptr),
grid2d_previous(nullptr), grid3d_previous(nullptr), grid_sample_previous(nullptr),
grid_nfreq_previous(nullptr), grid_running_previous(nullptr), grid_window_previous(nullptr),
bin(nullptr), skip(nullptr), vresult(nullptr)
{
if (narg < 10) utils::missing_cmd_args(FLERR,"fix ave/grid", error);
if (narg < 10) utils::missing_cmd_args(FLERR, "fix ave/grid", error);
// clang-format off
pergrid_flag = 1;
nevery = utils::inumeric(FLERR,arg[3],false,lmp);
nrepeat = utils::inumeric(FLERR,arg[4],false,lmp);
@ -193,7 +194,6 @@ FixAveGrid::FixAveGrid(LAMMPS *lmp, int narg, char **arg) :
aveflag = ONE;
nwindow = 0;
biasflag = 0;
id_bias = nullptr;
adof = domain->dimension;
cdof = 0.0;
@ -231,6 +231,7 @@ FixAveGrid::FixAveGrid(LAMMPS *lmp, int narg, char **arg) :
if (iarg+2 > nargnew)
error->all(FLERR,"Illegal fix ave/grid command");
biasflag = 1;
delete[] id_bias;
id_bias = utils::strdup(arg[iarg+1]);
iarg += 2;
@ -347,11 +348,7 @@ FixAveGrid::FixAveGrid(LAMMPS *lmp, int narg, char **arg) :
// vresult for per-atom variable evaluation
maxatom = 0;
bin = nullptr;
skip = nullptr;
maxvar = 0;
vresult = nullptr;
// nvalid = next step on which end_of_step does something
// add nvalid to all computes that store invocation times
@ -372,6 +369,7 @@ FixAveGrid::~FixAveGrid()
delete[] argindex;
for (int m = 0; m < nvalues; m++) delete[] ids[m];
delete[] ids;
delete[] id_bias;
delete[] value2index;
delete[] value2grid;
delete[] value2data;

View File

@ -60,7 +60,9 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
// then read options so know mode = SCALAR/VECTOR before re-reading values
nvalues = 0;
int iarg = 6;
// the first six arguments have fixed positions
const int ioffset = 6;
int iarg = ioffset;
while (iarg < narg) {
if (utils::strmatch(arg[iarg],"^[cfv]_")) {
nvalues++;
@ -68,9 +70,10 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
} else break;
}
if (nvalues == 0)
error->all(FLERR,"No values from computes, fixes, or variables used in fix ave/time command");
error->all(FLERR, ioffset,
"No values from computes, fixes, or variables used in fix ave/time command");
// parse optional keywords
// parse optional keywords which must follow the data
options(iarg,narg,arg);
@ -79,10 +82,11 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
int expand = 0;
char **earg;
nvalues = utils::expand_args(FLERR,nvalues,&arg[6],mode,earg,lmp);
int *amap = nullptr;
nvalues = utils::expand_args(FLERR,nvalues,&arg[ioffset],mode,earg,lmp,&amap);
key2col.clear();
if (earg != &arg[6]) expand = 1;
if (earg != &arg[ioffset]) expand = 1;
arg = earg;
// parse values
@ -97,9 +101,11 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
key2col[arg[i]] = i;
if ((val.which == ArgInfo::NONE) || (val.which == ArgInfo::UNKNOWN) || (argi.get_dim() > 1))
error->all(FLERR,"Invalid fix ave/time argument: {}", arg[i]);
error->all(FLERR, amap[i] + ioffset,"Invalid fix ave/time argument: {}", arg[i]);
val.argindex = argi.get_index1();
if (expand) val.iarg = amap[i] + ioffset;
else val.iarg = i + ioffset;
val.varlen = 0;
val.offcol = 0;
val.id = argi.get_name();
@ -115,16 +121,16 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
for (int i = 0; i < noff; i++) {
if (offlist[i] < 1 || offlist[i] > nvalues)
error->all(FLERR,"Invalid fix ave/time off column: {}", offlist[i]);
values[offlist[i]-1].offcol = 1;
values[offlist[i] - 1].offcol = 1;
}
// setup and error check
// for fix inputs, check that fix frequency is acceptable
// set variable_length if any compute is variable length
if (nevery <= 0) error->all(FLERR,"Illegal fix ave/time nevery value: {}", nevery);
if (nrepeat <= 0) error->all(FLERR,"Illegal fix ave/time nrepeat value: {}", nrepeat);
if (nfreq <= 0) error->all(FLERR,"Illegal fix ave/time nfreq value: {}", nfreq);
if (nevery <= 0) error->all(FLERR, 3, "Illegal fix ave/time nevery value: {}", nevery);
if (nrepeat <= 0) error->all(FLERR, 4, "Illegal fix ave/time nrepeat value: {}", nrepeat);
if (nfreq <= 0) error->all(FLERR, 5, "Illegal fix ave/time nfreq value: {}", nfreq);
if (nfreq % nevery || nrepeat*nevery > nfreq)
error->all(FLERR,"Inconsistent fix ave/time nevery/nrepeat/nfreq values");
if (ave != RUNNING && overwrite)
@ -134,25 +140,29 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
if ((val.which == ArgInfo::COMPUTE) && (mode == SCALAR)) {
val.val.c = modify->get_compute_by_id(val.id);
if (!val.val.c) error->all(FLERR,"Compute ID {} for fix ave/time does not exist", val.id);
if (!val.val.c)
error->all(FLERR, val.iarg, "Compute ID {} for fix ave/time does not exist", val.id);
if (val.argindex == 0 && (val.val.c->scalar_flag == 0))
error->all(FLERR,"Fix ave/time compute {} does not calculate a scalar", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} does not calculate a scalar", val.id);
if (val.argindex && (val.val.c->vector_flag == 0))
error->all(FLERR,"Fix ave/time compute {} does not calculate a vector", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} does not calculate a vector", val.id);
if (val.argindex && (val.argindex > val.val.c->size_vector) &&
(val.val.c->size_vector_variable == 0))
error->all(FLERR, "Fix ave/time compute {} vector is accessed out-of-range", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} vector is accessed out-of-range",
val.id);
if (val.argindex && val.val.c->size_vector_variable) val.varlen = 1;
} else if ((val.which == ArgInfo::COMPUTE) && (mode == VECTOR)) {
val.val.c = modify->get_compute_by_id(val.id);
if (!val.val.c) error->all(FLERR,"Compute ID {} for fix ave/time does not exist", val.id);
if (!val.val.c)
error->all(FLERR, val.iarg, "Compute ID {} for fix ave/time does not exist", val.id);
if ((val.argindex == 0) && (val.val.c->vector_flag == 0))
error->all(FLERR,"Fix ave/time compute {} does not calculate a vector", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} does not calculate a vector", val.id);
if (val.argindex && (val.val.c->array_flag == 0))
error->all(FLERR,"Fix ave/time compute {} does not calculate an array", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} does not calculate an array", val.id);
if (val.argindex && (val.argindex > val.val.c->size_array_cols))
error->all(FLERR,"Fix ave/time compute {} array is accessed out-of-range", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} array is accessed out-of-range",
val.id);
if ((val.argindex == 0) && (val.val.c->size_vector_variable)) val.varlen = 1;
if (val.argindex && (val.val.c->size_array_rows_variable)) val.varlen = 1;
@ -160,47 +170,54 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
val.val.f = modify->get_fix_by_id(val.id);
if (!val.val.f) error->all(FLERR,"Fix ID {} for fix ave/time does not exist", val.id);
if ((val.argindex == 0) && (val.val.f->scalar_flag == 0))
error->all(FLERR,"Fix ave/time fix {} does not calculate a scalar", val.id);
error->all(FLERR, val.iarg, "Fix ave/time fix {} does not calculate a scalar", val.id);
if (val.argindex && (val.val.f->vector_flag == 0))
error->all(FLERR,"Fix ave/time fix {} does not calculate a vector", val.id);
error->all(FLERR, val.iarg, "Fix ave/time fix {} does not calculate a vector", val.id);
if (val.argindex && (val.val.f->size_vector_variable))
error->all(FLERR,"Fix ave/time fix {} vector cannot be variable length", val.id);
error->all(FLERR, val.iarg, "Fix ave/time fix {} vector cannot be variable length", val.id);
if (val.argindex && (val.argindex > val.val.f->size_vector))
error->all(FLERR,"Fix ave/time fix {} vector is accessed out-of-range", val.id);
error->all(FLERR, val.iarg, "Fix ave/time fix {} vector is accessed out-of-range", val.id);
if (nevery % val.val.f->global_freq)
error->all(FLERR, "Fix {} for fix ave/time not computed at compatible time", val.id);
error->all(FLERR, val.iarg, "Fix {} for fix ave/time not computed at compatible time",
val.id);
} else if ((val.which == ArgInfo::FIX) && (mode == VECTOR)) {
val.val.f = modify->get_fix_by_id(val.id);
if (!val.val.f) error->all(FLERR,"Fix ID {} for fix ave/time does not exist", val.id);
if (!val.val.f)
error->all(FLERR, val.iarg, "Fix ID {} for fix ave/time does not exist", val.id);
if ((val.argindex == 0) && (val.val.f->vector_flag == 0))
error->all(FLERR,"Fix ave/time fix {} does not calculate a vector", val.id);
error->all(FLERR, val.iarg, "Fix ave/time fix {} does not calculate a vector", val.id);
if (val.argindex && (val.val.f->array_flag == 0))
error->all(FLERR,"Fix ave/time fix {} does not calculate an array", val.id);
error->all(FLERR, val.iarg, "Fix ave/time fix {} does not calculate an array", val.id);
if (val.argindex && (val.val.f->size_array_rows_variable))
error->all(FLERR,"Fix ave/time fix {} array cannot have variable row length", val.id);
error->all(FLERR, val.iarg, "Fix ave/time fix {} array cannot have variable row length",
val.id);
if (val.argindex && (val.argindex > val.val.f->size_array_cols))
error->all(FLERR,"Fix ave/time fix {} array is accessed out-of-range", val.id);
error->all(FLERR, val.iarg, "Fix ave/time fix {} array is accessed out-of-range", val.id);
if (nevery % val.val.f->global_freq)
error->all(FLERR, "Fix {} for fix ave/time not computed at compatible time", val.id);
error->all(FLERR, val.iarg, "Fix {} for fix ave/time not computed at compatible time",
val.id);
} else if ((val.which == ArgInfo::VARIABLE) && (mode == SCALAR)) {
int ivariable = input->variable->find(val.id.c_str());
if (ivariable < 0)
error->all(FLERR,"Variable name {} for fix ave/time does not exist", val.id);
error->all(FLERR, val.iarg, "Variable name {} for fix ave/time does not exist", val.id);
if ((val.argindex == 0) && (input->variable->equalstyle(ivariable) == 0))
error->all(FLERR,"Fix ave/time variable {} is not equal-style variable", val.id);
error->all(FLERR, val.iarg, "Fix ave/time variable {} is not equal-style variable", val.id);
if ((val.argindex) && (input->variable->vectorstyle(ivariable) == 0))
error->all(FLERR,"Fix ave/time variable {} is not vector-style variable", val.id);
error->all(FLERR, val.iarg, "Fix ave/time variable {} is not vector-style variable",
val.id);
} else if ((val.which == ArgInfo::VARIABLE) && (mode == VECTOR)) {
int ivariable = input->variable->find(val.id.c_str());
if (ivariable < 0)
error->all(FLERR,"Variable name {} for fix ave/time does not exist", val.id);
error->all(FLERR, val.iarg, "Variable name {} for fix ave/time does not exist", val.id);
if ((val.argindex == 0) && (input->variable->vectorstyle(ivariable) == 0))
error->all(FLERR,"Fix ave/time variable {} is not vector-style variable", val.id);
error->all(FLERR, val.iarg, "Fix ave/time variable {} is not vector-style variable",
val.id);
if (val.argindex)
error->all(FLERR,"Fix ave/time mode vector variable {} cannot be indexed", val.id);
error->all(FLERR, val.iarg, "Fix ave/time mode vector variable {} cannot be indexed",
val.id);
val.varlen = 1;
}
}
@ -258,7 +275,9 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
fprintf(fp,"\n");
}
if (yaml_flag) fputs("---\n",fp);
if (ferror(fp)) error->one(FLERR,"Error writing file header: {}", utils::getsyserror());
if (ferror(fp))
error->one(FLERR, Error::NOLASTLINE, "Error writing fix ave/time ID {} file header: {}",
id, utils::getsyserror());
filepos = platform::ftell(fp);
}
@ -272,6 +291,7 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
if (expand) {
for (int i = 0; i < nvalues; i++) delete[] earg[i];
memory->sfree(earg);
memory->sfree(amap);
}
// allocate memory for averaging
@ -377,12 +397,12 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
extvalue = 0;
}
if (extvalue == -1)
error->all(FLERR,"Fix ave/time cannot set output array intensive/extensive "
"from these inputs");
error->all(FLERR, Error::NOLASTLINE, "Fix ave/time cannot set output array "
"intensive/extensive from these inputs");
if (extarray < -1) extarray = extvalue;
else if (extvalue != extarray)
error->all(FLERR,"Fix ave/time cannot set output array intensive/extensive "
"from these inputs");
error->all(FLERR, Error::NOLASTLINE, "Fix ave/time cannot set output array "
"intensive/extensive from these inputs");
}
}
}
@ -462,15 +482,17 @@ void FixAveTime::init()
if (val.which == ArgInfo::COMPUTE) {
val.val.c = modify->get_compute_by_id(val.id);
if (!val.val.c)
error->all(FLERR,"Compute ID {} for fix ave/time does not exist", val.id);
error->all(FLERR, Error::NOLASTLINE, "Compute ID {} for fix ave/time does not exist",
val.id);
} else if (val.which == ArgInfo::FIX) {
val.val.f = modify->get_fix_by_id(val.id);
if (!val.val.f)
error->all(FLERR,"Fix ID {} for fix ave/time does not exist", val.id);
error->all(FLERR, Error::NOLASTLINE, "Fix ID {} for fix ave/time does not exist", val.id);
} else if (val.which == ArgInfo::VARIABLE) {
val.val.v = input->variable->find(val.id.c_str());
if (val.val.v < 0)
error->all(FLERR,"Variable name {} for fix ave/time does not exist", val.id);
error->all(FLERR, Error::NOLASTLINE, "Variable name {} for fix ave/time does not exist",
val.id);
}
}
@ -655,14 +677,16 @@ void FixAveTime::invoke_scalar(bigint ntimestep)
fmt::print(fp,"{}",ntimestep);
for (i = 0; i < nvalues; i++) fprintf(fp,format,vector_total[i]/norm);
fprintf(fp,"\n");
if (ferror(fp)) error->one(FLERR,"Error writing out time averaged data");
if (ferror(fp))
error->one(FLERR, Error::NOLASTLINE, "Error writing out time averaged data: {}",
utils::getsyserror());
}
fflush(fp);
if (overwrite) {
bigint fileend = platform::ftell(fp);
if ((fileend > 0) && (platform::ftruncate(fp,fileend)))
error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror());
error->warning(FLERR, "Error while tuncating output: {}", utils::getsyserror());
}
}
}
@ -767,7 +791,8 @@ void FixAveTime::invoke_vector(bigint ntimestep)
double *varvec;
int nvec = input->variable->compute_vector(val.val.v,&varvec);
if (nvec != nrows)
error->all(FLERR,"Fix ave/time vector-style variable {} changed length", val.id);
error->all(FLERR, Error::NOLASTLINE, "Fix ave/time vector-style variable {} changed length",
val.id);
for (int i = 0; i < nrows; i++)
column[i] = varvec[i];
}
@ -881,7 +906,7 @@ void FixAveTime::invoke_vector(bigint ntimestep)
if (overwrite) {
bigint fileend = platform::ftell(fp);
if ((fileend > 0) && (platform::ftruncate(fp,fileend)))
error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror());
error->warning(FLERR, "Error while tuncating output: {}", utils::getsyserror());
}
}
}
@ -912,7 +937,7 @@ int FixAveTime::column_length(int dynamic)
}
if (length == 0) length = lengthone;
else if (lengthone != length)
error->all(FLERR,"Fix ave/time columns are inconsistent lengths");
error->all(FLERR, Error::NOLASTLINE, "Fix ave/time columns have inconsistent lengths");
}
}
@ -935,10 +960,10 @@ int FixAveTime::column_length(int dynamic)
if (all_variable_length) {
if (length == 0) length = lengthone;
else if (lengthone != length)
error->all(FLERR,"Fix ave/time columns are inconsistent lengths");
error->all(FLERR, Error::NOLASTLINE, "Fix ave/time columns have inconsistent lengths");
} else {
if (lengthone != nrows)
error->all(FLERR,"Fix ave/time columns are inconsistent lengths");
error->all(FLERR, Error::NOLASTLINE, "Fix ave/time columns have inconsistent lengths");
}
}
}
@ -1002,7 +1027,7 @@ int FixAveTime::modify_param(int narg, char **arg)
}
}
if ((icol < 0) || (icol >= (int) values.size()))
error->all(FLERR, "Thermo_modify colname column {} invalid", arg[1]);
error->all(FLERR, 1 + 1, "Thermo_modify colname column {} invalid", arg[1]);
values[icol].keyword = arg[2];
return 3;
}
@ -1042,7 +1067,7 @@ void FixAveTime::options(int iarg, int narg, char **arg)
if (strcmp(arg[iarg],"file") == 0) fp = fopen(arg[iarg+1],"w");
else fp = fopen(arg[iarg+1],"a");
if (fp == nullptr)
error->one(FLERR,"Cannot open fix ave/time file {}: {}",
error->one(FLERR, iarg+1, "Cannot open fix ave/time file {}: {}",
arg[iarg+1], utils::getsyserror());
}
iarg += 2;
@ -1051,12 +1076,13 @@ void FixAveTime::options(int iarg, int narg, char **arg)
if (strcmp(arg[iarg+1],"one") == 0) ave = ONE;
else if (strcmp(arg[iarg+1],"running") == 0) ave = RUNNING;
else if (strcmp(arg[iarg+1],"window") == 0) ave = WINDOW;
else error->all(FLERR,"Unknown fix ave/time ave keyword {}", arg[iarg+1]);
else error->all(FLERR, iarg+1, "Unknown fix ave/time ave keyword {}", arg[iarg+1]);
if (ave == WINDOW) {
if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "fix ave/time ave window", error);
nwindow = utils::inumeric(FLERR,arg[iarg+2],false,lmp);
if (nwindow <= 0)
error->all(FLERR,"Illegal fix ave/time ave window argument {}; must be > 0", nwindow);
error->all(FLERR, iarg+2, "Illegal fix ave/time ave window argument {}; must be > 0",
nwindow);
}
iarg += 2;
if (ave == WINDOW) iarg++;
@ -1068,7 +1094,7 @@ void FixAveTime::options(int iarg, int narg, char **arg)
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix ave/time mode", error);
if (strcmp(arg[iarg+1],"scalar") == 0) mode = SCALAR;
else if (strcmp(arg[iarg+1],"vector") == 0) mode = VECTOR;
else error->all(FLERR,"Unknown fix ave/time mode {}", arg[iarg+1]);
else error->all(FLERR,iarg+1,"Unknown fix ave/time mode {}", arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"off") == 0) {
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix ave/time off", error);

View File

@ -43,6 +43,7 @@ class FixAveTime : public Fix {
struct value_t {
int which; // type of data: COMPUTE, FIX, VARIABLE
int argindex; // 1-based index if data is vector, else 0
int iarg; // argument index in original argument list
int varlen; // 1 if value is from variable-length compute
int offcol;
std::string id; // compute/fix/variable ID

View File

@ -38,7 +38,7 @@ FixPrint::FixPrint(LAMMPS *lmp, int narg, char **arg) :
nevery = 1;
} else {
nevery = utils::inumeric(FLERR, arg[3], false, lmp);
if (nevery <= 0) error->all(FLERR, "Illegal fix print nevery value {}; must be > 0", nevery);
if (nevery <= 0) error->all(FLERR, 3, "Illegal fix print nevery value {}; must be > 0", nevery);
}
text = utils::strdup(arg[4]);
@ -121,12 +121,15 @@ void FixPrint::init()
if (var_print) {
ivar_print = input->variable->find(var_print);
if (ivar_print < 0)
error->all(FLERR, "Variable {} for fix print timestep does not exist", var_print);
error->all(FLERR, Error::NOLASTLINE, "Variable {} for fix print timestep does not exist",
var_print);
if (!input->variable->equalstyle(ivar_print))
error->all(FLERR, "Variable {} for fix print timestep is invalid style", var_print);
error->all(FLERR, Error::NOLASTLINE, "Variable {} for fix print timestep is invalid style",
var_print);
next_print = static_cast<bigint>(input->variable->compute_equal(ivar_print));
if (next_print <= update->ntimestep)
error->all(FLERR, "Fix print timestep variable {} returned a bad timestep: {}", var_print,
error->all(FLERR, Error::NOLASTLINE,
"Fix print timestep variable {} returned a bad timestep: {}", var_print,
next_print);
} else {
if (update->ntimestep % nevery)

View File

@ -26,8 +26,10 @@ class Input : protected Pointers {
friend class Error;
friend class Deprecated;
friend class SimpleCommandsTest_Echo_Test;
friend std::string utils::point_to_error(Input *input, int failed);
public:
char *command; // ptr to current command
int narg; // # of command args
char **arg; // parsed args for command
class Variable *variable; // defined variables
@ -42,7 +44,6 @@ class Input : protected Pointers {
int get_jump_skip() const { return jump_skip; }
protected:
char *command; // ptr to current command
int echo_screen; // 0 = no, 1 = yes
int echo_log; // 0 = no, 1 = yes

View File

@ -139,6 +139,7 @@ pairclass(nullptr), pairnames(nullptr), pairmasks(nullptr)
ago = -1;
cutneighmax = 0.0;
cutneighmin = BIG;
cutneighsq = nullptr;
cutneighghostsq = nullptr;
cuttype = nullptr;
@ -1099,8 +1100,10 @@ int Neighbor::init_pair()
NeighList *ptr;
// use counter to avoid getting stuck
int done = 0;
while (!done) {
int count = 0;
while (!done && (count < 100)) {
done = 1;
for (i = 0; i < npair_perpetual; i++) {
for (k = 0; k < 3; k++) {
@ -1109,8 +1112,9 @@ int Neighbor::init_pair()
if (k == 1) ptr = lists[plist[i]]->listskip;
if (k == 2) ptr = lists[plist[i]]->listfull;
if (ptr == nullptr) continue;
for (m = 0; m < nrequest; m++)
for (m = 0; m < nrequest; m++) {
if (ptr == lists[m]) break;
}
for (j = 0; j < npair_perpetual; j++)
if (m == plist[j]) break;
if (j < i) continue;
@ -1122,7 +1126,11 @@ int Neighbor::init_pair()
}
if (!done) break;
}
++count;
}
if (count == 100)
error->all(FLERR, "Failed to reorder neighbor lists to satisfy constraints - "
"Contact the LAMMPS developers for assistance");
// debug output
@ -1185,8 +1193,8 @@ void Neighbor::morph_unique()
for (int i = 0; i < nrequest; i++) {
irq = requests[i];
// if cut flag set by requestor and cutoff is different than default,
// set unique flag, otherwise unset cut flag
// if cut flag set by requestor and cutoff is larger than minimum for default,
// and the list is not a skip list, set unique flag; otherwise unset cut flag
// this forces Pair,Stencil,Bin styles to be instantiated separately
// also add skin to cutoff of perpetual lists
@ -1194,7 +1202,7 @@ void Neighbor::morph_unique()
if (!irq->occasional)
irq->cutoff += skin;
if (irq->cutoff != cutneighmax) {
if ((irq->cutoff > cutneighmin) && !irq->skip) {
irq->unique = 1;
} else {
irq->cut = 0;
@ -1510,6 +1518,10 @@ void Neighbor::morph_copy_trim()
if (jrq->copy && jrq->copylist == i) continue;
// cannot copy or trim if some pair-wise cutoffs are too small
if (irq->cut && !jrq->cut && (irq->cutoff > cutneighmin)) continue;
// trim a list with longer cutoff
if (irq->cut) icut = irq->cutoff;

View File

@ -710,10 +710,11 @@ double Pair::mix_energy(double eps1, double eps2, double sig1, double sig2)
return sqrt(eps1*eps2);
else if (mix_flag == ARITHMETIC)
return sqrt(eps1*eps2);
else if (mix_flag == SIXTHPOWER)
return (2.0 * sqrt(eps1*eps2) * powint(sig1, 3) * powint(sig2, 3)
/ (powint(sig1, 6) + powint(sig2, 6)));
else did_mix = false;
else if (mix_flag == SIXTHPOWER) {
if ((sig1 != 0.0) && (sig2 != 0.0))
return (2.0 * sqrt(eps1*eps2) * powint(sig1, 3) * powint(sig2, 3)
/ (powint(sig1, 6) + powint(sig2, 6)));
} else did_mix = false;
return 0.0;
}

View File

@ -125,6 +125,8 @@ Respa::Respa(LAMMPS *lmp, int narg, char **arg) :
nhybrid_styles = hybrid->nstyles;
// each hybrid sub-style needs to be assigned to a respa level
if (iarg + nhybrid_styles > narg) error->all(FLERR, "Illegal run_style respa command");
delete[] hybrid_level;
delete[] hybrid_compute;
hybrid_level = new int[nhybrid_styles];
hybrid_compute = new int[nhybrid_styles];
for (int i = 0; i < nhybrid_styles; ++i) {

View File

@ -111,6 +111,55 @@ bool utils::strmatch(const std::string &text, const std::string &pattern)
return (pos >= 0);
}
bool utils::strsame(const std::string &text1, const std::string &text2)
{
const char *ptr1 = text1.c_str();
const char *ptr2 = text2.c_str();
while (*ptr1 && *ptr2) {
// ignore whitespace
while (*ptr1 && isspace(*ptr1)) ++ptr1;
while (*ptr2 && isspace(*ptr2)) ++ptr2;
// strings differ
if (*ptr1 != *ptr2) return false;
// reached end of both strings
if (!*ptr1 && !*ptr2) return true;
++ptr1;
++ptr2;
}
return true;
}
std::string utils::strcompress(const std::string &text)
{
const char *ptr = text.c_str();
std::string output;
// remove leading whitespace
while (*ptr && isspace(*ptr)) ++ptr;
while (*ptr) {
// copy non-blank characters
while (*ptr && !isspace(*ptr)) output += *ptr++;
if (!*ptr) break;
// add one blank only
if (isspace(*ptr)) output += ' ';
// skip additional blanks
while (*ptr && isspace(*ptr)) ++ptr;
}
// remove trailing blank
if (output.back() == ' ') output.erase(output.size() - 1, 1);
return output;
}
/** This function is a companion function to utils::strmatch(). Arguments
* and logic is the same, but instead of a boolean, it returns the
* sub-string that matches the regex pattern. There can be only one match.
@ -132,6 +181,70 @@ void utils::missing_cmd_args(const std::string &file, int line, const std::strin
if (error) error->all(file, line, "Illegal {} command: missing argument(s)", cmd);
}
std::string utils::point_to_error(Input *input, int failed)
{
if (input && input->line && input->command) {
std::string lastline = utils::strcompress(input->line);
std::string lastargs = input->command;
std::string cmdline = "Last input line: ";
// extended output
if (failed > Error::NOPOINTER) {
// indicator points to command by default
int indicator = 0;
int quoted = 0;
lastargs += ' ';
// assemble pre-processed command line and update error indicator position, if needed.
for (int i = 0; i < input->narg; ++i) {
std::string inputarg = input->arg[i];
if (i == failed) indicator = lastargs.size();
// argument contains whitespace. add quotes. check which type of quotes, too
if (inputarg.find_first_of(" \t\n") != std::string::npos) {
if (i == failed) quoted = 2;
if (inputarg.find_first_of('"') != std::string::npos) {
lastargs += "'";
lastargs += inputarg;
lastargs += "'";
} else {
lastargs += '"';
lastargs += inputarg;
lastargs += '"';
}
} else
lastargs += inputarg;
lastargs += ' ';
}
indicator += cmdline.size();
// the string is unchanged by substitution (ignoring whitespace), print output only once
if (utils::strsame(lastline, lastargs)) {
cmdline += lastargs;
} else {
cmdline += lastline;
cmdline += '\n';
// must have the same number of chars as "Last input line: " used in the previous line
cmdline += "--> parsed line: ";
cmdline += lastargs;
}
// construct and append error indicator line
cmdline += '\n';
cmdline += std::string(indicator, ' ');
cmdline += std::string(strlen(input->arg[failed]) + quoted, '^');
cmdline += '\n';
} else {
cmdline += lastline;
cmdline += '\n';
}
return cmdline;
} else
return std::string("");
}
/* specialization for the case of just a single string argument */
void utils::logmesg(LAMMPS *lmp, const std::string &mesg)
@ -646,14 +759,14 @@ tagint utils::tnumeric(const char *file, int line, const char *str, bool do_abor
// clang-format off
template <typename TYPE>
void utils::bounds(const char *file, int line, const std::string &str,
bigint nmin, bigint nmax, TYPE &nlo, TYPE &nhi, Error *error)
bigint nmin, bigint nmax, TYPE &nlo, TYPE &nhi, Error *error, int failed)
{
nlo = nhi = -1;
// check for illegal characters
size_t found = str.find_first_not_of("*-0123456789");
if (found != std::string::npos) {
if (error) error->all(file, line, "Invalid range string: {}", str);
if (error) error->all(file, line, failed, "Invalid range string: {}", str);
return;
}
@ -676,23 +789,23 @@ void utils::bounds(const char *file, int line, const std::string &str,
if (error) {
if ((nlo <= 0) || (nhi <= 0))
error->all(file, line, "Invalid range string: {}", str);
error->all(file, line, failed, "Invalid range string: {}", str);
if (nlo < nmin)
error->all(file, line, "Numeric index {} is out of bounds ({}-{})", nlo, nmin, nmax);
error->all(file, line, failed, "Numeric index {} is out of bounds ({}-{})", nlo, nmin, nmax);
else if (nhi > nmax)
error->all(file, line, "Numeric index {} is out of bounds ({}-{})", nhi, nmin, nmax);
error->all(file, line, failed, "Numeric index {} is out of bounds ({}-{})", nhi, nmin, nmax);
else if (nlo > nhi)
error->all(file, line, "Numeric index {} is out of bounds ({}-{})", nlo, nmin, nhi);
error->all(file, line, failed, "Numeric index {} is out of bounds ({}-{})", nlo, nmin, nhi);
}
}
template void utils::bounds<>(const char *, int, const std::string &,
bigint, bigint, int &, int &, Error *);
bigint, bigint, int &, int &, Error *, int);
template void utils::bounds<>(const char *, int, const std::string &,
bigint, bigint, long &, long &, Error *);
bigint, bigint, long &, long &, Error *, int);
template void utils::bounds<>(const char *, int, const std::string &,
bigint, bigint, long long &, long long &, Error *);
bigint, bigint, long long &, long long &, Error *, int);
// clang-format on
/* ----------------------------------------------------------------------
@ -732,7 +845,7 @@ template void utils::bounds_typelabel<>(const char *, int, const std::string &,
------------------------------------------------------------------------- */
int utils::expand_args(const char *file, int line, int narg, char **arg, int mode, char **&earg,
LAMMPS *lmp)
LAMMPS *lmp, int **argmap)
{
int iarg;
@ -747,10 +860,18 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
return narg;
}
// determine argument offset, if possible
int ioffset = 0;
if (lmp->input->arg) {
for (int i = 0; i < lmp->input->narg; ++i)
if (lmp->input->arg[i] == arg[0]) ioffset = i;
}
// maxarg should always end up equal to newarg, so caller can free earg
int maxarg = narg - iarg;
earg = (char **) lmp->memory->smalloc(maxarg * sizeof(char *), "input:earg");
earg = (char **) lmp->memory->smalloc(maxarg * sizeof(char *), "expand_args:earg");
int *amap = (int *) lmp->memory->smalloc(maxarg * sizeof(int), "expand_args:amap");
int newarg = 0, expandflag, nlo, nhi, nmax;
std::string id, wc, tail;
@ -813,16 +934,18 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
// expand wild card string to nlo/nhi numbers
if (expandflag) {
utils::bounds(file, line, wc, 1, nmax, nlo, nhi, lmp->error);
utils::bounds(file, line, wc, 1, nmax, nlo, nhi, lmp->error, iarg + ioffset);
if (newarg + nhi - nlo + 1 > maxarg) {
maxarg += nhi - nlo + 1;
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "input:earg");
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "expand_args:earg");
amap = (int *) lmp->memory->srealloc(amap, maxarg * sizeof(char *), "expand_args:amap");
}
for (int index = nlo; index <= nhi; index++) {
earg[newarg] =
utils::strdup(fmt::format("{}:{}:{}[{}]{}", gridid[0], gridid[1], id, index, tail));
amap[newarg] = iarg;
newarg++;
}
}
@ -900,7 +1023,7 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
if (index >= 0) {
if (mode == 0 && lmp->input->variable->vectorstyle(index)) {
utils::bounds(file, line, wc, 1, MAXSMALLINT, nlo, nhi, lmp->error);
utils::bounds(file, line, wc, 1, MAXSMALLINT, nlo, nhi, lmp->error, iarg + ioffset);
if (nhi < MAXSMALLINT) {
nmax = nhi;
expandflag = 1;
@ -931,12 +1054,12 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
if (expandflag) {
// expand wild card string to nlo/nhi numbers
utils::bounds(file, line, wc, 1, nmax, nlo, nhi, lmp->error);
utils::bounds(file, line, wc, 1, nmax, nlo, nhi, lmp->error, iarg + ioffset);
if (newarg + nhi - nlo + 1 > maxarg) {
maxarg += nhi - nlo + 1;
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "input:earg");
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "expand_args:earg");
amap = (int *) lmp->memory->srealloc(amap, maxarg * sizeof(char *), "expand_args:amap");
}
for (int index = nlo; index <= nhi; index++) {
@ -944,6 +1067,7 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
earg[newarg] = utils::strdup(fmt::format("{}2_{}[{}]{}", word[0], id, index, tail));
else
earg[newarg] = utils::strdup(fmt::format("{}_{}[{}]{}", word[0], id, index, tail));
amap[newarg] = iarg;
newarg++;
}
}
@ -954,14 +1078,21 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
if (!expandflag) {
if (newarg == maxarg) {
maxarg++;
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "input:earg");
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "expand_args:earg");
amap = (int *) lmp->memory->srealloc(amap, maxarg * sizeof(char *), "expand_args:amap");
}
earg[newarg] = utils::strdup(word);
amap[newarg] = iarg;
newarg++;
}
}
// printf("NEWARG %d\n",newarg); for (int i = 0; i < newarg; i++) printf(" arg %d: %s\n",i,earg[i]);
if (argmap)
*argmap = amap;
else
lmp->memory->sfree(amap);
// fprintf(stderr, "NEWARG %d\n",newarg); for (int i = 0; i < newarg; i++) printf(" arg %d: %s %d\n",i,earg[i], amap ? amap[i] : -1);
return newarg;
}

View File

@ -28,18 +28,34 @@ namespace LAMMPS_NS {
// forward declarations
class Error;
class Input;
class LAMMPS;
namespace utils {
/*! Match text against a simplified regex pattern
*
* \param text the text to be matched against the pattern
* \param pattern the search pattern, which may contain regexp markers
* \param text the text to be matched against the pattern
* \param pattern the search pattern, which may contain regexp markers
* \return true if the pattern matches, false if not */
bool strmatch(const std::string &text, const std::string &pattern);
/*! Compare two string while ignoring whitespace
*
* \param text1 the first text to be compared
* \param text2 the second text to be compared
* \return true if the non-whitespace part of the two strings matches, false if not */
bool strsame(const std::string &text1, const std::string &text2);
/*! Compress whitespace in a string
*
* \param text the text to be compressed
* \return string with whitespace compressed to single blanks */
std::string strcompress(const std::string &text);
/*! Find sub-string that matches a simplified regex pattern
*
* \param text the text to be matched against the pattern
@ -59,6 +75,15 @@ namespace utils {
void missing_cmd_args(const std::string &file, int line, const std::string &cmd, Error *error);
/*! Create string with last command and optionally pointing to arg with error
*
* This function is a helper function for error messages. It creates
*
* \param input pointer to the Input class instance (for access to last command args)
* \param faile index of the faulty argument (-1 to point to the command itself)
* \return string with two lines: the pre-processed command and a '^' pointing to the faulty argument */
std::string point_to_error(Input *input, int failed);
/*! Internal function handling the argument list for logmesg(). */
void fmtargs_logmesg(LAMMPS *lmp, fmt::string_view format, fmt::format_args args);
@ -326,11 +351,12 @@ namespace utils {
* \param nmax largest allowed upper bound
* \param nlo lower bound
* \param nhi upper bound
* \param error pointer to Error class for out-of-bounds messages */
* \param error pointer to Error class for out-of-bounds messages
* \param failed argument index with failed expansion (optional) */
template <typename TYPE>
void bounds(const char *file, int line, const std::string &str, bigint nmin, bigint nmax,
TYPE &nlo, TYPE &nhi, Error *error);
TYPE &nlo, TYPE &nhi, Error *error, int failed = -2); // -2 = Error::NOPOINTER
/*! Same as utils::bounds(), but string may be a typelabel
*
@ -376,17 +402,23 @@ This functions adds the following case to :cpp:func:`utils::bounds() <LAMMPS_NS:
* caller. Otherwise arg and earg will point to the same address
* and no explicit de-allocation is needed by the caller.
*
* \param file name of source file for error message
* \param line line number in source file for error message
* \param narg number of arguments in current list
* \param arg argument list, possibly containing wildcards
* \param mode select between global vectors(=0) and arrays (=1)
* \param earg new argument list with wildcards expanded
* \param lmp pointer to top-level LAMMPS class instance
* The *argmap* pointer to an int pointer may be used to accept an array
* of integers mapping the arguments after the expansion to their original
* index. If this pointer is NULL (the default) than this map is not created.
* Otherwise, it must be deallocated by the calling code.
*
* \param file name of source file for error message
* \param line line number in source file for error message
* \param narg number of arguments in current list
* \param arg argument list, possibly containing wildcards
* \param mode select between global vectors(=0) and arrays (=1)
* \param earg new argument list with wildcards expanded
* \param lmp pointer to top-level LAMMPS class instance
* \param argmap pointer to integer pointer for mapping expanded indices to input (optional)
* \return number of arguments in expanded list */
int expand_args(const char *file, int line, int narg, char **arg, int mode, char **&earg,
LAMMPS *lmp);
LAMMPS *lmp, int **argmap = nullptr);
/*! Expand type label string into its equivalent numeric type
*
@ -397,9 +429,9 @@ This functions adds the following case to :cpp:func:`utils::bounds() <LAMMPS_NS:
* pointer is returned.
* If a string is returned, the calling code must free it with delete[].
*
* \param file name of source file for error message
* \param line line number in source file for error message
* \param str type string to be expanded
* \param file name of source file for error message
* \param line line number in source file for error message
* \param str type string to be expanded
* \param mode select labelmap using constants from Atom class
* \param lmp pointer to top-level LAMMPS class instance
* \return pointer to expanded string or null pointer */

View File

@ -5227,14 +5227,14 @@ void Variable::print_var_error(const std::string &srcfile, const int lineno,
if ((ivar >= 0) && (ivar < nvar)) {
std::string msg = fmt::format("Variable {}: ",names[ivar]) + errmsg;
if (global)
error->all(srcfile,lineno,msg);
error->all(srcfile, lineno, Error::NOLASTLINE, msg);
else
error->one(srcfile,lineno,msg);
error->one(srcfile, lineno, Error::NOLASTLINE, msg);
} else {
if (global)
error->all(srcfile,lineno,errmsg);
error->all(srcfile,lineno, Error::NOLASTLINE, errmsg);
else
error->one(srcfile,lineno,errmsg);
error->one(srcfile,lineno, Error::NOLASTLINE, errmsg);
}
}

View File

@ -2,7 +2,6 @@ LAMMPS-GUI TODO list:
# Short term goals (v1.x)
- add a preferences option to override light/dark theme setting and add choice for theme
- implement a timed "Auto-Save" feature that saves after some idle time. set timeout in Editor preferences.
- add a "Filter data" checkbox to the "Charts" window to select whether data should be dropped.
- add a "Charts tab" to the preferences with the following (default) settings:
@ -16,8 +15,6 @@ LAMMPS-GUI TODO list:
colors to individual atom types.
- Support color by property (e.g. scan computes or fixes with per-atom data), define colormaps etc.
- Add a "Diameters" dialog where diamaters can by specified by atom type
- figure out how widgets can be resized to fraction of available screen size.
- figure out stacking order of frames and whether it can be more flexible
- implement indenting regions for (nested) loops?
- implement data file manager GUI with the following features:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -62,6 +62,7 @@
Make Tutorial wizards more compact
Include download and compilation of WHAM software from Alan Grossfield
Add dialog to run WHAM directly from LAMMPS-GUI
Add entry to Run menu to restart the LAMMPS instance
Use mutex to avoid corruption of thermo data
</description>
</release>

View File

@ -212,6 +212,7 @@ LammpsGui::LammpsGui(QWidget *parent, const QString &filename) :
connect(ui->actionRun_Buffer, &QAction::triggered, this, &LammpsGui::run_buffer);
connect(ui->actionRun_File, &QAction::triggered, this, &LammpsGui::run_file);
connect(ui->actionStop_LAMMPS, &QAction::triggered, this, &LammpsGui::stop_run);
connect(ui->actionRestart_LAMMPS, &QAction::triggered, this, &LammpsGui::restart_lammps);
connect(ui->actionSet_Variables, &QAction::triggered, this, &LammpsGui::edit_variables);
connect(ui->actionImage, &QAction::triggered, this, &LammpsGui::render_image);
connect(ui->actionLAMMPS_Tutorial, &QAction::triggered, this, &LammpsGui::tutorial_web);
@ -1161,7 +1162,7 @@ void LammpsGui::run_done()
status->setText("Failed.");
ui->textEdit->setHighlight(nline, true);
QMessageBox::critical(this, "LAMMPS-GUI Error",
QString("Error running LAMMPS:\n\n") + errorbuf);
QString("<p>Error running LAMMPS:\n\n<pre>") + errorbuf + "</pre></p>");
}
ui->textEdit->setCursor(nline);
ui->textEdit->setFileList();

View File

@ -111,6 +111,7 @@ private slots:
void findandreplace();
void run_buffer() { do_run(true); }
void run_file() { do_run(false); }
void restart_lammps() { lammps.close(); };
void edit_variables();
void render_image();
@ -183,6 +184,7 @@ class TutorialWizard : public QWizard {
public:
TutorialWizard(int ntutorial, QWidget *parent = nullptr);
void accept() override;
private:
int _ntutorial;
};

View File

@ -67,6 +67,7 @@
<file>icons/search.png</file>
<file>icons/system-box.png</file>
<file>icons/system-help.png</file>
<file>icons/system-restart.png</file>
<file>icons/system-run.png</file>
<file>icons/trash.png</file>
<file>icons/tutorial-logo.png</file>

View File

@ -74,6 +74,7 @@
<addaction name="actionRun_Buffer"/>
<addaction name="actionRun_File"/>
<addaction name="actionStop_LAMMPS"/>
<addaction name="actionRestart_LAMMPS"/>
<addaction name="separator"/>
<addaction name="actionSet_Variables"/>
<addaction name="separator"/>
@ -270,7 +271,7 @@
<iconset theme=":/icons/run-file.png"/>
</property>
<property name="text">
<string>&amp;Run LAMMPS from File</string>
<string>Run LAMMPS from &amp;File</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+Return</string>
@ -287,6 +288,14 @@
<string>Ctrl+/</string>
</property>
</action>
<action name="actionRestart_LAMMPS">
<property name="icon">
<iconset theme=":/icons/system-restart.png"/>
</property>
<property name="text">
<string>Restart &amp;LAMMPS</string>
</property>
</action>
<action name="actionImage">
<property name="icon">
<iconset theme=":/icons/emblem-photos.png"/>

View File

@ -151,6 +151,10 @@ TEST_F(Advanced_utils, expand_args)
args[7] = utils::strdup("c_gofr[*2][2]");
args[8] = utils::strdup("c_gofr[*][*]");
// disable use of input->command and input->arg which point to the last run command right now
lmp->input->command = nullptr;
lmp->input->arg = nullptr;
auto narg = utils::expand_args(FLERR, oarg, args, 0, earg, lmp);
EXPECT_EQ(narg, 16);
EXPECT_STREQ(earg[0], "v_step");

View File

@ -1,7 +1,7 @@
---
lammps_version: 19 Nov 2024
date_generated: Wed Dec 11 15:29:39 2024
epsilon: 1e-7
epsilon: 1e-6
skip_tests:
prerequisites: ! |
pair dispersion/d3

View File

@ -46,6 +46,49 @@ TEST(Utils, strdup)
delete[] copy2;
}
TEST(Utils, strsame)
{
std::string text1("some_text");
std::string text2("some_text");
ASSERT_TRUE(utils::strsame(text1, text2));
text1 = " some _\ttext\n ";
ASSERT_TRUE(utils::strsame(text1, text2));
text2 = " some _ text\n ";
ASSERT_TRUE(utils::strsame(text1, text2));
text2 = "some_other_text";
ASSERT_FALSE(utils::strsame(text1, text2));
text2 = " some other_text";
ASSERT_FALSE(utils::strsame(text1, text2));
}
TEST(Utils, strcompress)
{
auto compressed = utils::strcompress("\t some text ");
ASSERT_THAT(compressed, StrEq("some text"));
compressed = utils::strcompress("some \ntext");
ASSERT_THAT(compressed, StrEq("some text"));
compressed = utils::strcompress("sometext");
ASSERT_THAT(compressed, StrEq("sometext"));
compressed = utils::strcompress("some text \r\n");
ASSERT_THAT(compressed, StrEq("some text"));
compressed = utils::strcompress("some other text \r\n");
ASSERT_THAT(compressed, StrEq("some other text"));
compressed = utils::strcompress("\v some \t\t text \f");
ASSERT_THAT(compressed, StrEq("some text"));
compressed = utils::strcompress(" some\t text ");
ASSERT_THAT(compressed, StrEq("some text"));
compressed = utils::strcompress(" \t\n ");
ASSERT_THAT(compressed, StrEq(""));
}
TEST(Utils, trim)
{
auto trimmed = utils::trim("\t some text");