Merge pull request #4434 from akohlmey/collected-small-changes

Collected small changes and fixes
This commit is contained in:
Axel Kohlmeyer
2025-01-14 00:41:10 -05:00
committed by GitHub
30 changed files with 942 additions and 137 deletions

View File

@ -67,7 +67,6 @@ jobs:
-D PKG_MANIFOLD=on \
-D PKG_MDI=on \
-D PKG_MGPT=on \
-D PKG_ML-PACE=on \
-D PKG_ML-RANN=on \
-D PKG_MOLFILE=on \
-D PKG_NETCDF=on \

View File

@ -0,0 +1,53 @@
# GitHub action to build LAMMPS-GUI as a flatpak bundle
name: "Build LAMMPS-GUI as flatpak bundle"
on:
push:
branches:
- develop
workflow_dispatch:
concurrency:
group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{github.event_name == 'pull_request'}}
jobs:
build:
name: LAMMPS-GUI flatpak build
if: ${{ github.repository == 'lammps/lammps' }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Install extra packages
run: |
sudo apt-get update
sudo apt-get install -y ccache \
libeigen3-dev \
libcurl4-openssl-dev \
mold \
ninja-build \
python3-dev \
flatpak \
flatpak-builder
- name: Set up access to flatpak repo
run: flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
- name: Build flatpak
run: |
mkdir flatpack-state
sed -i -e 's/branch:.*/branch: develop/' tools/lammps-gui/org.lammps.lammps-gui.yml
flatpak-builder --force-clean --verbose --repo=flatpak-repo \
--install-deps-from=flathub --state-dir=flatpak-state \
--user --ccache --default-branch=${{ github.ref_name }} \
flatpak-build tools/lammps-gui/org.lammps.lammps-gui.yml
flatpak build-bundle --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \
--verbose flatpak-repo LAMMPS-Linux-x86_64-GUI.flatpak \
org.lammps.lammps-gui ${{ github.ref_name }}
flatpak install -y -v --user LAMMPS-Linux-x86_64-GUI.flatpak

View File

@ -1,6 +1,10 @@
Removed commands and packages
=============================
.. contents::
------
This page lists LAMMPS commands and packages that have been removed from
the distribution and provides suggestions for alternatives or
replacements. LAMMPS has special dummy styles implemented, that will
@ -8,47 +12,60 @@ stop LAMMPS and print a suitable error message in most cases, when a
style/command is used that has been removed or will replace the command
with the direct alternative (if available) and print a warning.
restart2data tool
-----------------
LAMMPS shell
------------
.. versionchanged:: 23Nov2013
.. versionchanged:: 29Aug2024
The functionality of the restart2data tool has been folded into the
LAMMPS executable directly instead of having a separate tool. A
combination of the commands :doc:`read_restart <read_restart>` and
:doc:`write_data <write_data>` can be used to the same effect. For
added convenience this conversion can also be triggered by
:doc:`command-line flags <Run_options>`
The LAMMPS shell has been removed from the LAMMPS distribution. Users
are encouraged to use the :ref:`LAMMPS-GUI <lammps_gui>` tool instead.
Fix ave/spatial and fix ave/spatial/sphere
------------------------------------------
i-PI tool
---------
.. deprecated:: 11Dec2015
.. versionchanged:: 27Jun2024
The fixes ave/spatial and ave/spatial/sphere have been removed from LAMMPS
since they were superseded by the more general and extensible "chunk
infrastructure". Here the system is partitioned in one of many possible
ways through the :doc:`compute chunk/atom <compute_chunk_atom>` command
and then averaging is done using :doc:`fix ave/chunk <fix_ave_chunk>`.
Please refer to the :doc:`chunk HOWTO <Howto_chunk>` section for an overview.
The i-PI tool has been removed from the LAMMPS distribution. Instead,
instructions to install i-PI from PyPI via pip are provided.
Box command
-----------
USER-REAXC package
------------------
.. deprecated:: 22Dec2022
.. deprecated:: 7Feb2024
The *box* command has been removed and the LAMMPS code changed so it won't
be needed. If present, LAMMPS will ignore the command and print a warning.
The USER-REAXC package has been renamed to :ref:`REAXFF <PKG-REAXFF>`.
In the process also the pair style and related fixes were renamed to use
the "reaxff" string instead of "reax/c". For a while LAMMPS was maintaining
backward compatibility by providing aliases for the styles. These have
been removed, so using "reaxff" is now *required*.
Reset_ids, reset_atom_ids, reset_mol_ids commands
-------------------------------------------------
MPIIO package
-------------
.. deprecated:: 22Dec2022
.. deprecated:: 21Nov2023
The *reset_ids*, *reset_atom_ids*, and *reset_mol_ids* commands have
been folded into the :doc:`reset_atoms <reset_atoms>` command. If
present, LAMMPS will replace the commands accordingly and print a
warning.
The MPIIO package has been removed from LAMMPS since it was unmaintained
for many years and thus not updated to incorporate required changes that
had been applied to the corresponding non-MPIIO commands. As a
consequence the MPIIO commands had become unreliable and sometimes
crashing LAMMPS or corrupting data. Similar functionality is available
through the :ref:`ADIOS package <PKG-ADIOS>` and the :ref:`NETCDF
package <PKG-NETCDF>`. Also, the :doc:`dump_modify nfile or dump_modify
fileper <dump_modify>` keywords may be used for an efficient way of
writing out dump files when running on large numbers of processors.
Similarly, the "nfile" and "fileper" keywords exist for restarts:
see :doc:`restart <restart>`, :doc:`read_restart <read_restart>`,
:doc:`write_restart <write_restart>`.
MSCG package
------------
.. deprecated:: 21Nov2023
The MSCG package has been removed from LAMMPS since it was unmaintained
for many years and instead superseded by the `OpenMSCG software
<https://software.rcc.uchicago.edu/mscg/>`_ of the Voth group at the
University of Chicago, which can be used independent from LAMMPS.
LATTE package
-------------
@ -64,18 +81,6 @@ packages, including LATTE. See the ``examples/QUANTUM`` dir and the
with LATTE as a plugin library (similar to the way fix latte worked), as
well as on a different set of MPI processors.
MEAM package
------------
The MEAM package in Fortran has been replaced by a C++ implementation.
The code in the :ref:`MEAM package <PKG-MEAM>` is a translation of the
Fortran code of MEAM into C++, which removes several restrictions
(e.g. there can be multiple instances in hybrid pair styles) and allows
for some optimizations leading to better performance. The pair style
:doc:`meam <pair_meam>` has the exact same syntax. For a transition
period the C++ version of MEAM was called USER-MEAMC so it could
coexist with the Fortran version.
Minimize style fire/old
-----------------------
@ -97,38 +102,38 @@ The same functionality is available through
:doc:`bond style mesocnt <bond_mesocnt>` and
:doc:`angle style mesocnt <angle_mesocnt>`.
MPIIO package
-------------
Box command
-----------
.. deprecated:: 21Nov2023
.. deprecated:: 22Dec2022
The MPIIO package has been removed from LAMMPS since it was unmaintained
for many years and thus not updated to incorporate required changes that
had been applied to the corresponding non-MPIIO commands. As a
consequence the MPIIO commands had become unreliable and sometimes
crashing LAMMPS or corrupting data. Similar functionality is available
through the :ref:`ADIOS package <PKG-ADIOS>` and the :ref:`NETCDF
package <PKG-NETCDF>`. Also, the :doc:`dump_modify nfile or dump_modify
fileper <dump_modify>` keywords may be used for an efficient way of
writing out dump files when running on large numbers of processors.
Similarly, the "nfile" and "fileper" keywords exist for restarts:
see :doc:`restart <restart>`, :doc:`read_restart <read_restart>`,
:doc:`write_restart <write_restart>`.
The *box* command has been removed and the LAMMPS code changed so it won't
be needed. If present, LAMMPS will ignore the command and print a warning.
Reset_ids, reset_atom_ids, reset_mol_ids commands
-------------------------------------------------
MSCG package
------------
.. deprecated:: 22Dec2022
.. deprecated:: 21Nov2023
The *reset_ids*, *reset_atom_ids*, and *reset_mol_ids* commands have
been folded into the :doc:`reset_atoms <reset_atoms>` command. If
present, LAMMPS will replace the commands accordingly and print a
warning.
The MSCG package has been removed from LAMMPS since it was unmaintained
for many years and instead superseded by the `OpenMSCG software
<https://software.rcc.uchicago.edu/mscg/>`_ of the Voth group at the
University of Chicago, which can be used independent from LAMMPS.
MESSAGE package
---------------
.. deprecated:: 4May2022
The MESSAGE package has been removed since it was superseded by the
:ref:`MDI package <PKG-MDI>`. MDI implements the same functionality
and in a more general way with direct support for more applications.
REAX package
------------
.. deprecated:: 4Jan2019
The REAX package has been removed since it was superseded by the
:ref:`REAXFF package <PKG-REAXFF>`. The REAXFF package has been tested
to yield equivalent results to the REAX package, offers better
@ -138,20 +143,25 @@ syntax compatible with the removed reax pair style, so input files will
have to be adapted. The REAXFF package was originally called
USER-REAXC.
USER-REAXC package
------------------
MEAM package
------------
.. deprecated:: 7Feb2024
.. deprecated:: 4Jan2019
The USER-REAXC package has been renamed to :ref:`REAXFF <PKG-REAXFF>`.
In the process also the pair style and related fixes were renamed to use
the "reaxff" string instead of "reax/c". For a while LAMMPS was maintaining
backward compatibility by providing aliases for the styles. These have
been removed, so using "reaxff" is now *required*.
The MEAM package in Fortran has been replaced by a C++ implementation.
The code in the :ref:`MEAM package <PKG-MEAM>` is a translation of the
Fortran code of MEAM into C++, which removes several restrictions
(e.g. there can be multiple instances in hybrid pair styles) and allows
for some optimizations leading to better performance. The pair style
:doc:`meam <pair_meam>` has the exact same syntax. For a transition
period the C++ version of MEAM was called USER-MEAMC so it could
coexist with the Fortran version.
USER-CUDA package
-----------------
.. deprecated:: 31May2016
The USER-CUDA package had been removed, since it had been unmaintained
for a long time and had known bugs and problems. Significant parts of
the design were transferred to the
@ -160,19 +170,27 @@ performance characteristics on NVIDIA GPUs. Both, the KOKKOS
and the :ref:`GPU package <PKG-GPU>` are maintained
and allow running LAMMPS with GPU acceleration.
i-PI tool
---------
Fix ave/spatial and fix ave/spatial/sphere
------------------------------------------
.. versionchanged:: 27Jun2024
.. deprecated:: 11Dec2015
The i-PI tool has been removed from the LAMMPS distribution. Instead,
instructions to install i-PI from PyPI via pip are provided.
The fixes ave/spatial and ave/spatial/sphere have been removed from LAMMPS
since they were superseded by the more general and extensible "chunk
infrastructure". Here the system is partitioned in one of many possible
ways through the :doc:`compute chunk/atom <compute_chunk_atom>` command
and then averaging is done using :doc:`fix ave/chunk <fix_ave_chunk>`.
Please refer to the :doc:`chunk HOWTO <Howto_chunk>` section for an overview.
LAMMPS shell
------------
restart2data tool
-----------------
.. versionchanged:: 29Aug2024
.. deprecated:: 23Nov2013
The LAMMPS shell has been removed from the LAMMPS distribution. Users
are encouraged to use the :ref:`LAMMPS-GUI <lammps_gui>` tool instead.
The functionality of the restart2data tool has been folded into the
LAMMPS executable directly instead of having a separate tool. A
combination of the commands :doc:`read_restart <read_restart>` and
:doc:`write_data <write_data>` can be used to the same effect. For
added convenience this conversion can also be triggered by
:doc:`command-line flags <Run_options>`

View File

@ -321,6 +321,8 @@ of the contents of the :f:mod:`LIBLAMMPS` Fortran interface to LAMMPS.
:ftype set_string_variable: subroutine
:f set_internal_variable: :f:subr:`set_internal_variable`
:ftype set_internal_variable: subroutine
:f eval: :f:func:`eval`
:ftype eval: function
:f gather_atoms: :f:subr:`gather_atoms`
:ftype gather_atoms: subroutine
:f gather_atoms_concat: :f:subr:`gather_atoms_concat`

View File

@ -64,13 +64,18 @@ simple LAMMPS simulations. It is very suitable for tutorials on LAMMPS
since you only need to learn how to use a single program for most tasks
and thus time can be saved and people can focus on learning LAMMPS.
The tutorials at https://lammpstutorials.github.io/ are specifically
updated for use with LAMMPS-GUI.
updated for use with LAMMPS-GUI and can their tutorial materials can
be downloaded and loaded directly from the GUI.
Another design goal is to keep the barrier low when replacing part of
the functionality of LAMMPS-GUI with external tools. That said, LAMMPS-GUI
has some unique functionality that is not found elsewhere:
- auto-adapting to features available in the integrated LAMMPS library
- auto-completion for LAMMPS commands and options
- context-sensitive online help
- start and stop of simulations via mouse or keyboard
- monitoring of simulation progress
- interactive visualization using the :doc:`dump image <dump_image>`
command with the option to copy-paste the resulting settings
- automatic slide show generation from dump image out at runtime

View File

@ -7,6 +7,7 @@ This section documents the following functions:
- :cpp:func:`lammps_command`
- :cpp:func:`lammps_commands_list`
- :cpp:func:`lammps_commands_string`
- :cpp:func:`lammps_expand`
--------------------
@ -79,3 +80,8 @@ Below is a short example using some of these functions.
.. doxygenfunction:: lammps_commands_string
:project: progguide
-----------------------
.. doxygenfunction:: lammps_expand
:project: progguide

View File

@ -1,5 +1,5 @@
Compute, fixes, variables
=========================
Computes, fixes, variables
==========================
This section documents accessing or modifying data stored by computes,
fixes, or variables in LAMMPS using the following functions:
@ -12,6 +12,7 @@ fixes, or variables in LAMMPS using the following functions:
- :cpp:func:`lammps_set_string_variable`
- :cpp:func:`lammps_set_internal_variable`
- :cpp:func:`lammps_variable_info`
- :cpp:func:`lammps_eval`
-----------------------
@ -55,6 +56,11 @@ fixes, or variables in LAMMPS using the following functions:
-----------------------
.. doxygenfunction:: lammps_eval
:project: progguide
-----------------------
.. doxygenenum:: _LMP_DATATYPE_CONST
.. doxygenenum:: _LMP_STYLE_CONST

View File

@ -117,6 +117,7 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
ADDSYM(set_string_variable);
ADDSYM(set_internal_variable);
ADDSYM(variable_info);
ADDSYM(eval);
ADDSYM(gather_atoms);
ADDSYM(gather_atoms_concat);

View File

@ -163,6 +163,7 @@ struct _liblammpsplugin {
int (*set_string_variable)(void *, const char *, const char *);
int (*set_internal_variable)(void *, const char *, double);
int (*variable_info)(void *, int, char *, int);
double (*eval)(void *, const char *);
void (*gather_atoms)(void *, const char *, int, int, void *);
void (*gather_atoms_concat)(void *, const char *, int, int, void *);

View File

@ -126,6 +126,7 @@ MODULE LIBLAMMPS
PROCEDURE :: set_variable => lmp_set_variable
PROCEDURE :: set_string_variable => lmp_set_string_variable
PROCEDURE :: set_internal_variable => lmp_set_internal_variable
PROCEDURE :: eval => lmp_eval
PROCEDURE, PRIVATE :: lmp_gather_atoms_int
PROCEDURE, PRIVATE :: lmp_gather_atoms_double
GENERIC :: gather_atoms => lmp_gather_atoms_int, &
@ -618,7 +619,14 @@ MODULE LIBLAMMPS
INTEGER(c_int) :: lammps_set_internal_variable
END FUNCTION lammps_set_internal_variable
SUBROUTINE lammps_gather_atoms(handle, name, type, count, data) BIND(C)
FUNCTION lammps_eval(handle, expr) BIND(C)
IMPORT :: c_ptr, c_double
IMPLICIT NONE
TYPE(c_ptr), VALUE :: handle, expr
REAL(c_double) :: lammps_eval
END FUNCTION lammps_eval
SUBROUTINE lammps_gather_atoms(handle, name, TYPE, count, DATA) BIND(C)
IMPORT :: c_int, c_ptr
IMPLICIT NONE
TYPE(c_ptr), VALUE :: handle, name, data
@ -1812,7 +1820,7 @@ CONTAINS
SUBROUTINE lmp_set_internal_variable(self, name, val)
CLASS(lammps), INTENT(IN) :: self
CHARACTER(LEN=*), INTENT(IN) :: name
REAL(KIND=c_double), INTENT(IN) :: val
REAL(c_double), INTENT(IN) :: val
INTEGER :: err
TYPE(c_ptr) :: Cname
@ -1826,6 +1834,18 @@ CONTAINS
END IF
END SUBROUTINE lmp_set_internal_variable
! equivalent function to lammps_eval
FUNCTION lmp_eval(self, expr)
CLASS(lammps), INTENT(IN) :: self
CHARACTER(LEN=*), INTENT(IN) :: expr
REAL(c_double) :: lmp_eval
TYPE(c_ptr) :: Cexpr
Cexpr = f2c_string(expr)
lmp_eval = lammps_eval(self%handle, Cexpr)
CALL lammps_free(Cexpr)
END FUNCTION lmp_eval
! equivalent function to lammps_gather_atoms (for integers)
SUBROUTINE lmp_gather_atoms_int(self, name, count, data)
CLASS(lammps), INTENT(IN) :: self

View File

@ -103,7 +103,7 @@ class command_wrapper(object):
This method is where the Python 'magic' happens. If a method is not
defined by the class command_wrapper, it assumes it is a LAMMPS command. It takes
all the arguments, concatinates them to a single string, and executes it using
:py:meth:`lammps.command()`.
:py:meth:`lammps.command`.
Starting with Python 3.6 it also supports keyword arguments. key=value is
transformed into 'key value'. Note, since these have come last in the
@ -422,6 +422,9 @@ class lammps(object):
self.lib.lammps_extract_variable_datatype.argtypes = [c_void_p, c_char_p]
self.lib.lammps_extract_variable_datatype.restype = c_int
self.lib.lammps_eval.argtypes = [c_void_p, c_char_p]
self.lib.lammps_eval.restype = c_double
self.lib.lammps_fix_external_get_force.argtypes = [c_void_p, c_char_p]
self.lib.lammps_fix_external_get_force.restype = POINTER(POINTER(c_double))
@ -1671,6 +1674,30 @@ class lammps(object):
# -------------------------------------------------------------------------
def eval(self, expr):
""" Evaluate a LAMMPS immediate variable expression
.. versionadded:: TBD
This function is a wrapper around the function :cpp:func:`lammps_eval`
of the C library interface. It evaluates and expression like in
immediate variables and returns the value.
:param expr: immediate variable expression
:type name: string
:return: the result of the evaluation
:rtype: c_double
"""
if expr: newexpr = expr.encode()
else: return None
with ExceptionCheck(self):
return self.lib.lammps_eval(self.lmp, newexpr)
return None
# -------------------------------------------------------------------------
# return vector of atom properties gathered across procs
# 3 variants to match src/library.cpp
# name = atom property recognized by LAMMPS in atom->extract()

View File

@ -17,7 +17,7 @@
################################################################################
class wrapper(object):
"""lammps API IPython Wrapper
""" lammps API IPython Wrapper
This is a wrapper class that provides additional methods on top of an
existing :py:class:`lammps` instance. It provides additional methods

View File

@ -63,6 +63,8 @@ void ComputeReaxFFAtomKokkos<DeviceType>::init()
template<class DeviceType>
void ComputeReaxFFAtomKokkos<DeviceType>::compute_bonds()
{
invoked_bonds = update->ntimestep;
if (atom->nmax > nmax) {
memory->destroy(array_atom);
nmax = atom->nmax;

View File

@ -41,6 +41,9 @@ using namespace LAMMPS_NS;
using namespace FixConst;
static constexpr double QSUMSMALL = 0.00001;
static constexpr int MIN_CAP = 50;
static constexpr double SAFE_ZONE = 1.2;
static constexpr bigint MIN_NBRS = 100;
namespace {
class qeq_parser_error : public std::exception {

View File

@ -16,12 +16,6 @@
#include "fix.h"
#define EV_TO_KCAL_PER_MOL 14.4
#define DANGER_ZONE 0.90
#define MIN_CAP 50
#define SAFE_ZONE 1.2
#define MIN_NBRS 100
namespace LAMMPS_NS {
class FixQEq : public Fix {
@ -36,6 +30,7 @@ class FixQEq : public Fix {
void min_pre_force(int) override;
double compute_scalar() override;
static constexpr double DANGER_ZONE = 0.90;
// derived child classes must provide these functions

View File

@ -33,6 +33,8 @@
using namespace LAMMPS_NS;
static constexpr double EV_TO_KCAL_PER_MOL = 14.4;
/* ---------------------------------------------------------------------- */
FixQEqShielded::FixQEqShielded(LAMMPS *lmp, int narg, char **arg) : FixQEq(lmp, narg, arg)

View File

@ -121,9 +121,9 @@ void Finish::end(int flag)
MPI_Allreduce(&cpu_loop,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
cpu_loop = tmp/nprocs;
if (time_loop > 0.0) cpu_loop = cpu_loop/time_loop*100.0;
output->thermo->footer();
if (me == 0) {
output->thermo->footer();
int ntasks = nprocs * nthreads;
utils::logmesg(lmp,"Loop time of {:.6g} on {} procs for {} steps with {} atoms\n\n",
time_loop,ntasks,update->nsteps,atom->natoms);

View File

@ -208,14 +208,14 @@ FixDeposit::FixDeposit(LAMMPS *lmp, int narg, char **arg) :
FixDeposit::~FixDeposit()
{
delete random;
delete [] molfrac;
delete [] idrigid;
delete [] idshake;
delete [] idregion;
delete [] vstr;
delete [] xstr;
delete [] ystr;
delete [] zstr;
delete[] molfrac;
delete[] idrigid;
delete[] idshake;
delete[] idregion;
delete[] vstr;
delete[] xstr;
delete[] ystr;
delete[] zstr;
memory->destroy(coords);
memory->destroy(imageflags);
}
@ -737,7 +737,7 @@ void FixDeposit::options(int narg, char **arg)
mode = MOLECULE;
onemols = &atom->molecules[imol];
nmol = onemols[0]->nset;
delete [] molfrac;
delete[] molfrac;
molfrac = new double[nmol];
molfrac[0] = 1.0/nmol;
for (int i = 1; i < nmol-1; i++) molfrac[i] = molfrac[i-1] + 1.0/nmol;
@ -755,13 +755,13 @@ void FixDeposit::options(int narg, char **arg)
iarg += nmol+1;
} else if (strcmp(arg[iarg],"rigid") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix deposit command");
delete [] idrigid;
delete[] idrigid;
idrigid = utils::strdup(arg[iarg+1]);
rigidflag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"shake") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix deposit command");
delete [] idshake;
delete[] idshake;
idshake = utils::strdup(arg[iarg+1]);
shakeflag = 1;
iarg += 2;

View File

@ -516,6 +516,9 @@ treated as part of the command and will **not** start a second command.
The function returns the expanded string in a new string buffer that
must be freed with :cpp:func:`lammps_free` after use to avoid a memory leak.
*See also*
:cpp:func:`lammps_eval`
\endverbatim
*
* \param handle pointer to a previously created LAMMPS instance
@ -850,7 +853,11 @@ This differs from :cpp:func:`lammps_get_thermo` in that it does **not**
trigger an evaluation. Instead it provides direct access to a read-only
location of the last thermo output data and the corresponding keyword
strings. How to handle the return value depends on the value of the *what*
argument string.
argument string. When accessing the data from a concurrent thread while
LAMMPS is running, the cache needs to be locked first and then unlocked
after the data is obtained, so that the data is not corrupted while
reading in case LAMMPS wants to update it at the same time. Outside
of a run, the lock/unlock calls have no effect.
.. note::
@ -899,6 +906,14 @@ argument string.
- actual field data for column
- pointer to int, int64_t or double
- yes
* - lock
- acquires lock to thermo data cache
- NULL pointer
- no
* - unlock
- releases lock to thermo data cache
- NULL pointer
- no
\endverbatim
*
@ -954,8 +969,14 @@ void *lammps_last_thermo(void *handle, const char *what, int index)
} else if (field.type == multitype::LAMMPS_DOUBLE) {
val = (void *) &field.data.d;
}
} else if (strcmp(what, "lock") == 0) {
th->lock_cache();
val = nullptr;
} else if (strcmp(what, "unlock") == 0) {
th->unlock_cache();
val = nullptr;
} else val = nullptr;
}
END_CAPTURE
return val;
@ -2904,6 +2925,39 @@ int lammps_variable_info(void *handle, int idx, char *buffer, int buf_size) {
return 0;
}
/** Evaluate an immediate variable expression
*
\verbatim embed:rst
.. versionadded:: TBD
This function takes a string with an expression that can be used
for :doc:`equal style variables <variable>`, evaluates it and returns
the resulting (scalar) value as a floating point number.
*See also*
:cpp:func:`lammps_expand`
\endverbatim
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
* \param expr string with expression
* \return result from expression */
double lammps_eval(void *handle, const char *expr)
{
auto lmp = (LAMMPS *) handle;
double result = 0.0;
BEGIN_CAPTURE
{
result = lmp->input->variable->compute_equal(expr);
}
END_CAPTURE
return result;
}
// ----------------------------------------------------------------------
// Library functions for scatter/gather operations of data
// ----------------------------------------------------------------------

View File

@ -189,6 +189,7 @@ int lammps_set_variable(void *handle, const char *name, const char *str);
int lammps_set_string_variable(void *handle, const char *name, const char *str);
int lammps_set_internal_variable(void *handle, const char *name, double value);
int lammps_variable_info(void *handle, int idx, char *buf, int bufsize);
double lammps_eval(void *handle, const char *expr);
/* ----------------------------------------------------------------------
* Library functions for scatter/gather operations of data

View File

@ -100,8 +100,8 @@ static char fmtbuf[512];
/* ---------------------------------------------------------------------- */
Thermo::Thermo(LAMMPS *_lmp, int narg, char **arg) :
Pointers(_lmp), style(nullptr), vtype(nullptr), field2index(nullptr), argindex1(nullptr),
argindex2(nullptr), temperature(nullptr), pressure(nullptr), pe(nullptr)
Pointers(_lmp), style(nullptr), vtype(nullptr), cache_mutex(nullptr), field2index(nullptr),
argindex1(nullptr), argindex2(nullptr), temperature(nullptr), pressure(nullptr), pe(nullptr)
{
style = utils::strdup(arg[0]);
@ -208,6 +208,7 @@ void Thermo::init()
ValueTokenizer *format_line = nullptr;
if (format_line_user.size()) format_line = new ValueTokenizer(format_line_user);
lock_cache();
field_data.clear();
field_data.resize(nfield);
std::string format_this, format_line_user_def;
@ -277,6 +278,7 @@ void Thermo::init()
format[i] += fmt::format("{:<8} = {} ", keyword[i], format_this);
}
}
unlock_cache();
// chop off trailing blank or add closing bracket if needed and then add newline
if (lineflag == ONELINE)
@ -320,6 +322,9 @@ void Thermo::init()
if (index_press_scalar >= 0) pressure = computes[index_press_scalar];
if (index_press_vector >= 0) pressure = computes[index_press_vector];
if (index_pe >= 0) pe = computes[index_pe];
// create mutex to protect access to cached thermo data
cache_mutex = new std::mutex;
}
/* ----------------------------------------------------------------------
@ -366,9 +371,17 @@ void Thermo::header()
/* ---------------------------------------------------------------------- */
// called at the end of a run from Finish class
void Thermo::footer()
{
if (lineflag == YAMLLINE) utils::logmesg(lmp, "...\n");
if (comm->me == 0) {
if (lineflag == YAMLLINE) utils::logmesg(lmp, "...\n");
}
// no more locking for cached thermo data access needed
delete cache_mutex;
cache_mutex = nullptr;
}
/* ---------------------------------------------------------------------- */
@ -422,6 +435,7 @@ void Thermo::compute(int flag)
}
// add each thermo value to line with its specific format
lock_cache();
field_data.clear();
field_data.resize(nfield);
@ -441,6 +455,7 @@ void Thermo::compute(int flag)
field_data[ifield] = bivalue;
}
}
unlock_cache();
// print line to screen and logfile
@ -579,7 +594,8 @@ void Thermo::modify_params(int narg, char **arg)
if (iarg + 2 > narg) error->all(FLERR, "Illegal thermo_modify command");
triclinic_general = utils::logical(FLERR, arg[iarg + 1], false, lmp);
if (triclinic_general && !domain->triclinic_general)
error->all(FLERR,"Thermo_modify triclinic/general cannot be used "
error->all(FLERR,
"Thermo_modify triclinic/general cannot be used "
"if simulation box is not general triclinic");
iarg += 2;
@ -1566,6 +1582,26 @@ int Thermo::evaluate_keyword(const std::string &word, double *answer)
return 0;
}
/* ---------------------------------------------------------------------- */
// lock cache for current thermo data
void Thermo::lock_cache()
{
// no locking outside of a run
if (!cache_mutex) return;
cache_mutex->lock();
}
// unlock cache for current thermo data
void Thermo::unlock_cache()
{
// no locking outside of a run
if (!cache_mutex) return;
cache_mutex->unlock();
}
/* ----------------------------------------------------------------------
extraction of Compute, Fix, Variable results
compute/fix are normalized by atoms if returning extensive value

View File

@ -16,6 +16,7 @@
#include "pointers.h"
#include <map>
#include <mutex>
namespace LAMMPS_NS {
@ -43,6 +44,8 @@ class Thermo : protected Pointers {
int evaluate_keyword(const std::string &, double *);
// for accessing cached thermo and related data
void lock_cache();
void unlock_cache();
const int *get_line() const { return &nline; }
const char *get_image_fname() const { return image_fname.c_str(); }
@ -82,6 +85,9 @@ class Thermo : protected Pointers {
int nline;
std::string image_fname;
// mutex for locking the cache
std::mutex *cache_mutex;
// data used by routines that compute single values
int ivalue; // integer value to print

View File

@ -457,15 +457,21 @@ void Variable::set(int narg, char **arg)
// data = 2 values, 1st is string to eval, 2nd is filled on retrieval
} else if (strcmp(arg[1],"equal") == 0) {
if (narg != 3)
error->all(FLERR,"Illegal variable command: expected 3 arguments but found {}{}",
narg, utils::errorurl(3));
if (narg < 3) utils::missing_cmd_args(FLERR, "variable equal", error);
// combine excess arguments into single string with a blank as separator
std::string combined = arg[2];
for (int iarg = 3; iarg < narg; ++iarg) {
combined += ' ';
combined += arg[iarg];
}
int ivar = find(arg[0]);
if (ivar >= 0) {
if (style[ivar] != EQUAL)
error->all(FLERR,"Cannot redefine variable as a different style");
delete[] data[ivar][0];
data[ivar][0] = utils::strdup(arg[2]);
data[ivar][0] = utils::strdup(combined);
replaceflag = 1;
} else {
if (nvar == maxvar) grow();
@ -474,7 +480,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
data[nvar][0] = utils::strdup(arg[2]);
data[nvar][0] = utils::strdup(combined);
data[nvar][1] = new char[VALUELENGTH];
strcpy(data[nvar][1],"(undefined)");
}
@ -485,15 +491,21 @@ void Variable::set(int narg, char **arg)
// data = 1 value, string to eval
} else if (strcmp(arg[1],"atom") == 0) {
if (narg != 3)
error->all(FLERR,"Illegal variable command: expected 3 arguments but found {}{}",
narg, utils::errorurl(3));
if (narg < 3) utils::missing_cmd_args(FLERR, "variable atom", error);
// combine excess arguments into single string with a blank as separator
std::string combined = arg[2];
for (int iarg = 3; iarg < narg; ++iarg) {
combined += ' ';
combined += arg[iarg];
}
int ivar = find(arg[0]);
if (ivar >= 0) {
if (style[ivar] != ATOM)
error->all(FLERR,"Cannot redefine variable as a different style");
delete[] data[ivar][0];
data[ivar][0] = utils::strdup(arg[2]);
data[ivar][0] = utils::strdup(combined);
replaceflag = 1;
} else {
if (nvar == maxvar) grow();
@ -502,7 +514,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
data[nvar][0] = utils::strdup(arg[2]);
data[nvar][0] = utils::strdup(combined);
}
// VECTOR
@ -513,16 +525,22 @@ void Variable::set(int narg, char **arg)
// immediately store it as N-length vector and set dynamic flag to 0
} else if (strcmp(arg[1],"vector") == 0) {
if (narg != 3)
error->all(FLERR,"Illegal variable command: expected 3 arguments but found {}{}",
narg, utils::errorurl(3));
if (narg < 3) utils::missing_cmd_args(FLERR, "variable atom", error);
// combine excess arguments into single string with a blank as separator
std::string combined = arg[2];
for (int iarg = 3; iarg < narg; ++iarg) {
combined += ' ';
combined += arg[iarg];
}
int ivar = find(arg[0]);
if (ivar >= 0) {
if (style[ivar] != VECTOR)
error->all(FLERR,"Cannot redefine variable as a different style");
delete[] data[ivar][0];
delete[] data[ivar][1];
data[ivar][0] = utils::strdup(arg[2]);
data[ivar][0] = utils::strdup(combined);
if (data[ivar][0][0] != '[')
vecs[ivar].dynamic = 1;
else {
@ -539,7 +557,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
data[nvar][0] = utils::strdup(arg[2]);
data[nvar][0] = utils::strdup(combined);
if (data[nvar][0][0] != '[') {
vecs[nvar].dynamic = 1;
data[nvar][1] = nullptr;

View File

@ -61,6 +61,8 @@
Highlight warnings and error messages in Output window
Make Tutorial wizards more compact
Include download and compilation of WHAM software from Alan Grossfield
Add dialog to run WHAM directly from LAMMPS-GUI
Use mutex to avoid corruption of thermo data
</description>
</release>
<release version="1.6.11" timestamp="1725080055">

View File

@ -1015,6 +1015,7 @@ void LammpsGui::logupdate()
void *ptr = lammps.last_thermo("setup", 0);
if (ptr && *(int *)ptr) return;
lammps.last_thermo("lock", 0);
ptr = lammps.last_thermo("num", 0);
if (ptr) {
int ncols = *(int *)ptr;
@ -1066,6 +1067,7 @@ void LammpsGui::logupdate()
chartwindow->add_data(step, data, i);
}
}
lammps.last_thermo("unlock", 0);
}
// update list of available image file names

View File

@ -55,8 +55,79 @@ index 0000000..b4f0fe6
+ TYPE DOC
+ PERMISSIONS OWNER_READ GROUP_READ WORLD_READ
+)
diff --git a/nr/locate.c b/nr/locate.c
index 9f92dc0..f3bf294 100644
--- a/nr/locate.c
+++ b/nr/locate.c
@@ -11,7 +11,7 @@ void locate(double xx[], int n, double x, int *j)
ascnd=(xx[n] > xx[0]); // I think this makes it zero based
while (ju-jl > 1) {
jm=(ju+jl) >> 1;
- if (x > xx[jm] == ascnd)
+ if ((x > xx[jm]) == ascnd)
jl=jm;
else
ju=jm;
diff --git a/wham-2d/histogram.c b/wham-2d/histogram.c
index 1bd1329..b5d1c01 100644
--- a/wham-2d/histogram.c
+++ b/wham-2d/histogram.c
@@ -78,14 +78,14 @@ return hp;
}
/* Get a value from a histogram structure
- * Given i and j, the indices into the global histogram, return
+ * Given i and j, the indices into the global histogram, return
* the correct histogram value. Since we only store range of histogram
- * indices containing the nonzero values, we have to check the index value
+ * indices containing the nonzero values, we have to check the index value
* against the range in the structure.
*/
double get_histval(struct histogram *hist, int i, int j)
{
-if ( (i < hist->first_x) || (i > hist->last_x)
+if ( (i < hist->first_x) || (i > hist->last_x)
||(j < hist->first_y) || (j > hist->last_y))
{
return 0.0;
@@ -239,7 +239,7 @@ return error;
// Calculate the free energy, setting the minimum value to 0
-void calc_free(double **free, double **prob, double kT,
+void calc_free(double **free, double **prob, double kT,
int use_mask, int **mask)
{
int i,j;
@@ -257,7 +257,14 @@ for (i=0; i<NUM_BINSx; i++)
}
else
{
- free[i][j] = -kT * log(prob[i][j]);
+ if (prob[i][j] > 0.0)
+ {
+ free[i][j] = -kT * log(prob[i][j]);
+ }
+ else
+ {
+ free[i][j] = 0.0;
+ }
if (free[i][j] < min)
{
min = free[i][j];
@@ -321,8 +328,6 @@ return 0.5*(springx*(dx*dx) + springy*(dy*dy));
void calc_coor(int i, int j, double *coor)
{
-coor[0] = HIST_MINx + BIN_WIDTHx*((double)i+0.5);
-coor[1] = HIST_MINy + BIN_WIDTHy*((double)j+0.5);
+coor[0] = HIST_MINx + BIN_WIDTHx*((double)i+0.5);
+coor[1] = HIST_MINy + BIN_WIDTHy*((double)j+0.5);
}
-
-
diff --git a/wham-2d/wham-2d.c b/wham-2d/wham-2d.c
index fb6e059..2c5594f 100644
index fb6e059..a6b8483 100644
--- a/wham-2d/wham-2d.c
+++ b/wham-2d/wham-2d.c
@@ -25,7 +25,7 @@
@ -77,6 +148,15 @@ index fb6e059..2c5594f 100644
int main(int argc, char *argv[])
{
@@ -57,7 +57,7 @@ double sum;
int iteration;
int max_iteration = 100000;
int numpad;
-int **mask;
+int **mask = NULL;
int use_mask;
cpu1 = ((double) clock())/CLOCKS_PER_SEC;
@@ -76,6 +76,61 @@ for (i=0; i<argc; i++)
}
printf("\n");
@ -139,6 +219,143 @@ index fb6e059..2c5594f 100644
PERIODICx = parse_periodic(argv[1], &PERIODx);
if (PERIODICx)
{
@@ -360,8 +415,8 @@ while ( ! iConverged || first)
for (j=0; j< NUM_BINSy; j++)
{
calc_coor(i,j,coor);
- printf("%f\t%f\t%f\t%f\n", coor[0], coor[1], free_ene[i][j],
- prob[i][j]);
+ if (prob[i][j] != 0.0)
+ printf("%f\t%f\t%f\t%f\n", coor[0], coor[1], free_ene[i][j], prob[i][j]);
}
}
@@ -444,8 +499,9 @@ if (!FREEFILE)
for (j=0; j< NUM_BINSy; j++)
{
calc_coor(i,j,coor);
- printf("%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[i][j], final_prob[i][j]);
+ if (prob[i][j] != 0.0)
+ printf("%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[i][j], final_prob[i][j]);
}
}
exit(errno);
@@ -461,25 +517,28 @@ else
for (j=-numpad; j<0; j++)
{
calc_coor(i,j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[NUM_BINSx+i][NUM_BINSy+j],
- final_prob[NUM_BINSx+i][NUM_BINSy+j]);
+ if (prob[NUM_BINSx+i][NUM_BINSy+j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[NUM_BINSx+i][NUM_BINSy+j],
+ final_prob[NUM_BINSx+i][NUM_BINSy+j]);
}
// center values in y
for (j=0; j<NUM_BINSy; j++)
{
calc_coor(i,j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[NUM_BINSx+i][j],
- final_prob[NUM_BINSx+i][j]);
+ if (prob[NUM_BINSx+i][j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[NUM_BINSx+i][j],
+ final_prob[NUM_BINSx+i][j]);
}
// trailing padding values in y
for (j=0; j<numpad; j++)
{
calc_coor(i,NUM_BINSy+j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[NUM_BINSx+i][j],
- final_prob[NUM_BINSx+i][j]);
+ if (prob[NUM_BINSx+i][j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[NUM_BINSx+i][j],
+ final_prob[NUM_BINSx+i][j]);
}
fprintf(FREEFILE, "\n");
}
@@ -490,25 +549,28 @@ else
for (j=-numpad; j<0; j++)
{
calc_coor(i,j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[i][NUM_BINSy+j],
- final_prob[i][NUM_BINSy+j]);
+ if (prob[i][NUM_BINSy+j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[i][NUM_BINSy+j],
+ final_prob[i][NUM_BINSy+j]);
}
// center values in y
for (j=0; j<NUM_BINSy; j++)
{
calc_coor(i,j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[i][j],
- final_prob[i][j]);
+ if (prob[i][j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[i][j],
+ final_prob[i][j]);
}
// trailing padding values in y
for (j=0; j<numpad; j++)
{
calc_coor(i,NUM_BINSy+j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[i][j],
- final_prob[i][j]);
+ if (prob[i][j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[i][j],
+ final_prob[i][j]);
}
fprintf(FREEFILE, "\n");
}
@@ -519,25 +581,28 @@ else
for (j=-numpad; j<0; j++)
{
calc_coor(NUM_BINSx+i,j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[i][NUM_BINSy+j],
- final_prob[i][NUM_BINSy+j]);
+ if (prob[i][NUM_BINSy+j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[i][NUM_BINSy+j],
+ final_prob[i][NUM_BINSy+j]);
}
// center values in y
for (j=0; j<NUM_BINSy; j++)
{
calc_coor(NUM_BINSx+i,j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[i][j],
- final_prob[i][j]);
+ if (prob[i][j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[i][j],
+ final_prob[i][j]);
}
// trailing padding values in y
for (j=0; j<numpad; j++)
{
calc_coor(NUM_BINSx+i,NUM_BINSy+j,coor);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
- free_ene[i][j],
- final_prob[i][j]);
+ if (prob[i][j] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1],
+ free_ene[i][j],
+ final_prob[i][j]);
}
fprintf(FREEFILE, "\n");
}
diff --git a/wham-2d/wham-2d.h b/wham-2d/wham-2d.h
index b17e4bd..5fc17ff 100644
--- a/wham-2d/wham-2d.h
@ -163,10 +380,67 @@ index b17e4bd..5fc17ff 100644
// Value inserted for the free energy of masked values
diff --git a/wham/histogram.c b/wham/histogram.c
index bc52d74..635b39f 100644
--- a/wham/histogram.c
+++ b/wham/histogram.c
@@ -16,7 +16,7 @@
// Allocate memory for a histogram
-struct histogram *hist_alloc(int first, int last, int num_points,
+struct histogram *hist_alloc(int first, int last, int num_points,
int num_mc_samples)
{
struct histogram *hp;
@@ -45,9 +45,9 @@ return hp;
}
/* Get a value from a histogram structure
- * Given index, the index into the global histogram, return
+ * Given index, the index into the global histogram, return
* the correct histogram value. Since we only store range of histogram
- * indices containing the nonzero values, we have to check the index value
+ * indices containing the nonzero values, we have to check the index value
* against the range in the structure.
*/
double get_histval(struct histogram *hist, int index)
@@ -213,8 +213,16 @@ double min = 1e50;
bin_min = 0;
for (i=0; i<NUM_BINS; i++)
{
- free[i] = -kT * log(prob[i]);
- if (free[i] < min)
+ if (prob[i] > 0.0)
+ {
+ free[i] = -kT * log(prob[i]);
+ }
+ else
+ {
+ free[i] = 0.0;
+ }
+
+ if (free[i] < min)
{
min = free[i];
bin_min = i;
@@ -252,5 +260,5 @@ return 0.5*dx*dx*spring;
double calc_coor(int i)
{
-return HIST_MIN + BIN_WIDTH*((double)i+0.5);
+return HIST_MIN + BIN_WIDTH*((double)i+0.5);
}
diff --git a/wham/wham.c b/wham/wham.c
index 487871b..1496eed 100644
index 487871b..edb8125 100644
--- a/wham/wham.c
+++ b/wham/wham.c
@@ -1,4 +1,4 @@
-/*
+/*
* WHAM -- Weighted Histogram Analysis Method
*
* Reference 1: Computer Physics Communications, 91(1995) 275-282, Benoit Roux
@@ -21,7 +21,7 @@
#include "wham.h"
@ -184,6 +458,15 @@ index 487871b..1496eed 100644
int main(int argc, char *argv[])
{
@@ -41,7 +42,7 @@ int first;
int bin_min;
int have_energy;
char *freefile;
-FILE *METAFILE, *FREEFILE;
+FILE *METAFILE, *FREEFILE;
struct hist_group *hist_group;
struct histogram *hp;
double coor;
@@ -82,6 +83,61 @@ for (i=0; i<argc; i++)
}
printf("\n");
@ -246,6 +529,213 @@ index 487871b..1496eed 100644
if (toupper(argv[1][0]) == 'P')
{
PERIODIC = 1;
@@ -123,7 +179,7 @@ if (argc != 9 && argc !=11)
printf( COMMAND_LINE );
exit(-1);
}
-
+
HIST_MIN = atof(argv[1]);
HIST_MAX = atof(argv[2]);
NUM_BINS = atoi(argv[3]);
@@ -213,13 +269,13 @@ if (!ave_pdf2)
printf("couldn't allocate space for ave_pdf2: %s\n", strerror(errno));
exit(errno);
}
-
+
free_ene = (double *) malloc(sizeof(double) * NUM_BINS);
if (!free_ene)
{
printf("couldn't allocate space for free_ene: %s\n", strerror(errno));
exit(errno);
- }
+ }
i = get_numwindows(METAFILE);
printf("#Number of windows = %d\n", i);
@@ -248,7 +304,7 @@ assert(i == hist_group->num_windows);
// Figure out if we have trajectories at different temperatures.
// Missing temperatures are set to -1 in read_metadata, and
// since we require that either all trajectories specify a temperature
-// or all trajectories are assumed to be at the wham temperature, we only
+// or all trajectories are assumed to be at the wham temperature, we only
// have to check one of them
if (hist_group->kT[0] > 0)
{
@@ -257,7 +313,7 @@ if (hist_group->kT[0] > 0)
else
{
have_energy = 0;
- for (i=0; i< hist_group->num_windows; i++)
+ for (i=0; i< hist_group->num_windows; i++)
{
hist_group->kT[i] = kT;
}
@@ -269,7 +325,7 @@ if (!final_f)
{
printf("couldn't allocate space for final_f: %s\n", strerror(errno));
exit(errno);
- }
+ }
free(HISTOGRAM);
@@ -305,7 +361,8 @@ while (! is_converged(hist_group) || first )
for (i=0; i< NUM_BINS; i++)
{
coor = calc_coor(i);
- printf("%f\t%f\t%f\n", coor, free_ene[i], prob[i]);
+ if (prob[i] != 0.0)
+ printf("%f\t%f\t%f\n", coor, free_ene[i], prob[i]);
}
printf("\n");
@@ -319,7 +376,7 @@ while (! is_converged(hist_group) || first )
}
}
// Cheesy bailout if we're going on too long
- if (iteration >= max_iteration)
+ if (iteration >= max_iteration)
{
printf("Too many iterations: %d\n", iteration);
break;
@@ -383,11 +440,11 @@ for (i=0; i< num_mc_runs; i++)
//printf("Faking %d: %d %d\n", i,j,hp->num_points);
num_used = hp->last - hp->first + 1;
mk_new_hist(hp->cum, hp->data, num_used, hp->num_mc_samples, &idum);
-
+
hist_group->F_old[j] = 0.0;
hist_group->F[j] = 0.0;
}
-
+
// perform WHAM iterations on the fake data sets
iteration = 0;
first = 1;
@@ -403,7 +460,7 @@ for (i=0; i< num_mc_runs; i++)
printf("Too many iterations: %d\n", iteration);
break;
}
- }
+ }
printf("#MC trial %d: %d iterations\n", i, iteration);
printf("#PMF values\n");
// accumulate the average and stdev of the resulting probabilities
@@ -419,18 +476,19 @@ for (i=0; i< num_mc_runs; i++)
for (j=0; j < NUM_BINS; j++)
{
pdf = -kT*log(prob[j]);
-
+
ave_p[j] += prob[j];
ave_pdf[j] += pdf;
ave_p2[j] += prob[j] * prob[j];
ave_pdf2[j] += pdf*pdf;
}
- for (j=0; j<hist_group->num_windows;j++)
+ for (j=0; j<hist_group->num_windows;j++)
{
ave_F[j] += hist_group->F[j] - hist_group->F[0];
- ave_F2[j] += hist_group->F[j]*hist_group->F[j] ;
+ ave_F2[j] += hist_group->F[j]*hist_group->F[j] ;
}
- }
+ }
+ if (num_mc_runs == 0) num_mc_runs = 1;
for (i=0; i < NUM_BINS; i++)
{
ave_p[i] /= (double)num_mc_runs;
@@ -457,12 +515,12 @@ if (!FREEFILE)
for (i=0; i< NUM_BINS; i++)
{
coor = calc_coor(i);
- printf("%f\t%f\t%f\t%f\t%f\n", coor, free_ene[i], ave_pdf2[i],
- prob[i], ave_p2[i]);
+ if (prob[i] != 0.0)
+ printf("%f\t%f\t%f\t%f\t%f\n", coor, free_ene[i], ave_pdf2[i], prob[i], ave_p2[i]);
}
for (i=0; i<hist_group->num_windows; i++)
{
- fprintf(FREEFILE,"%d\t%f\t%f\n", i, final_f[i],ave_F2[i]);
+ printf("%d\t%f\t%f\n", i, final_f[i],ave_F2[i]);
}
exit(errno);
@@ -470,38 +528,37 @@ if (!FREEFILE)
else
{
// write out header
- fprintf(FREEFILE, "#Coor\t\tFree\t+/-\t\tProb\t\t+/-\n");
+ fprintf(FREEFILE, "#Coor\t\tFree\t\t+/-\t\tProb\t\t+/-\n");
// write out the leading padded values
for (i=-numpad; i<0; i++)
{
coor = calc_coor(i);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\t%f\n", coor, free_ene[NUM_BINS+i],
- ave_pdf2[NUM_BINS+i],
- final_prob[NUM_BINS+i],
- ave_p2[NUM_BINS+i]);
+ if (prob[NUM_BINS+1] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\t%f\n", coor, free_ene[NUM_BINS+i],
+ ave_pdf2[NUM_BINS+i], final_prob[NUM_BINS+i], ave_p2[NUM_BINS+i]);
}
// write out the center values
for (i=0; i<NUM_BINS; i++)
{
coor = calc_coor(i);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\t%f\n", coor, free_ene[i],
- ave_pdf2[i],final_prob[i],
- ave_p2[i]);
+ if (prob[i] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\t%f\n", coor, free_ene[i],
+ ave_pdf2[i],final_prob[i],ave_p2[i]);
}
// write out the trailing padded values
for (i=0; i<numpad; i++)
{
coor = calc_coor(NUM_BINS+i);
- fprintf(FREEFILE,"%f\t%f\t%f\t%f\t%f\n", coor, free_ene[i],
- ave_pdf2[i],final_prob[i],
- ave_p2[i]);
+ if (prob[i] != 0.0)
+ fprintf(FREEFILE,"%f\t%f\t%f\t%f\t%f\n", coor, free_ene[i],
+ ave_pdf2[i],final_prob[i], ave_p2[i]);
}
- fprintf(FREEFILE, "#Window\t\tFree\t+/-\t\n");
+ fprintf(FREEFILE, "#Window\t\tFree\t\t+/-\t\n");
for (i=0; i<hist_group->num_windows; i++)
{
- fprintf(FREEFILE,"#%d\t%f\t%f\n", i, final_f[i],ave_F2[i]);
+ fprintf(FREEFILE,"#%d\t\t%f\t%f\n", i, final_f[i],ave_F2[i]);
}
}
@@ -515,7 +572,7 @@ exit(0);
/*
* Perform a single WHAM iteration
*/
-void wham_iteration(struct hist_group* hist_group, double *prob,
+void wham_iteration(struct hist_group* hist_group, double *prob,
int have_energy)
{
int i,j;
@@ -535,9 +592,9 @@ for (i=0; i<NUM_BINS; i++)
num += (double) get_histval( &(hist_group->hists[j]),i);
bias = calc_bias(hist_group,j,coor);
bf = exp((hist_group->F_old[j] - bias) / hist_group->kT[j]);
- /* If we have energies, then the histograms contain boltzmann
- * factors. If not, they contain integer counts. Accordingly,
- * we either use a partition function to normalize, or simply the
+ /* If we have energies, then the histograms contain boltzmann
+ * factors. If not, they contain integer counts. Accordingly,
+ * we either use a partition function to normalize, or simply the
* number of points.
*/
if (have_energy)
diff --git a/wham/wham.h b/wham/wham.h
index aacc1e8..7d509f2 100644
--- a/wham/wham.h

View File

@ -141,6 +141,8 @@ extern int lammps_extract_variable_datatype(void *handle, const char *name);
extern int lammps_set_variable(void *, const char *, const char *);
extern int lammps_set_string_variable(void *, const char *, const char *);
extern int lammps_set_internal_variable(void *, const char *, double);
extern int lammps_variable_info(void *handle, int idx, char *buf, int bufsize);
extern double lammps_eval(void *handle, const char *expr);
extern void lammps_gather_atoms(void *, char *, int, int, void *);
extern void lammps_gather_atoms_concat(void *, char *, int, int, void *);
@ -332,6 +334,8 @@ extern int lammps_extract_variable_datatype(void *handle, const char *name);
extern int lammps_set_variable(void *, const char *, const char *);
extern int lammps_set_string_variable(void *, const char *, const char *);
extern int lammps_set_internal_variable(void *, const char *, double);
extern int lammps_variable_info(void *handle, int idx, char *buf, int bufsize);
extern double lammps_eval(void *handle, const char *expr);
extern void lammps_gather_atoms(void *, char *, int, int, void *);
extern void lammps_gather_atoms_concat(void *, char *, int, int, void *);

View File

@ -233,3 +233,34 @@ TEST_F(LibraryObjects, expand)
EXPECT_THAT((char *)ptr, StrEq("'xx_$(4+5)_$(PI) ${one}-${two}-${three}'"));
lammps_free(ptr);
}
TEST_F(LibraryObjects, eval)
{
lammps_get_last_error_message(lmp, nullptr, 1);
::testing::internal::CaptureStdout();
lammps_commands_string(lmp, "region box1 block 0 10 0 5 -0.5 0.5\n"
"lattice fcc 0.8\n"
"create_box 1 box1\n"
"create_atoms 1 box\n"
"mass * 1.0\n"
"pair_style lj/cut 4.0\n"
"pair_coeff * * 1.0 1.0\n"
"variable t equal 15.0\n"
"velocity all create 1.5 532656\n"
"fix 1 all nve\n"
"run 0 post no\n");
lammps_command(lmp, "variable one index 1 2 3 4");
lammps_command(lmp, "variable two equal 2");
std::string output = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << output;
ASSERT_EQ(lammps_has_error(lmp), 0);
EXPECT_DOUBLE_EQ(lammps_eval(lmp, "4+5"), 9.0);
EXPECT_EQ(lammps_has_error(lmp), 0);
EXPECT_DOUBLE_EQ(lammps_eval(lmp, "v_one / 2.0"), 0.5);
EXPECT_EQ(lammps_has_error(lmp), 0);
EXPECT_DOUBLE_EQ(lammps_eval(lmp, "count(all)"), 36.0);
EXPECT_EQ(lammps_has_error(lmp), 0);
EXPECT_DOUBLE_EQ(lammps_eval(lmp, "pe"), -3.9848867644689534);
EXPECT_EQ(lammps_has_error(lmp), 0);
}

View File

@ -140,8 +140,8 @@ TEST_F(VariableTest, CreateDelete)
command("variable ten1 universe 1 2 3 4");
command("variable ten2 uloop 4");
command("variable ten3 uloop 4 pad");
command("variable ten4 vector [0,1,2,3,5,7,11]");
command("variable ten5 vector [0.5,1.25]");
command("variable ten4 vector [0,1, 2,3, 5,7,11]");
command("variable ten5 vector [ 0.5, 1.25 ]");
command("variable dummy index 0");
command("variable file equal is_file(MYFILE)");
command("variable iswin equal is_os(^Windows)");
@ -323,13 +323,13 @@ TEST_F(VariableTest, Expressions)
BEGIN_HIDE_OUTPUT();
command("variable one index 1");
command("variable two equal 2");
command("variable three equal v_one+v_two");
command("variable three equal v_one + v_two");
command("variable four equal PI");
command("variable five equal version");
command("variable six equal XXX");
command("variable seven equal -v_one");
command("variable eight equal v_three-0.5");
command("variable nine equal v_two*(v_one+v_three)");
command("variable nine equal v_two * (v_one+v_three)");
command("variable ten equal (1.0/v_two)^2");
command("variable eleven equal v_three%2");
command("variable twelve equal 1==2");
@ -341,7 +341,7 @@ TEST_F(VariableTest, Expressions)
command("variable ten8 equal 1|^0");
command("variable ten9 equal v_one-v_ten9");
command("variable ten10 internal 100.0");
command("variable ten11 equal (1!=1)+(2<1)+(2<=1)+(1>2)+(1>=2)+(1&&0)+(0||0)+(1|^1)+10^0");
command("variable ten11 equal (1 != 1)+(2 < 1)+(2<=1)+(1>2)+(1>=2)+(1&&0)+(0||0)+(1|^1)+10^0");
command("variable ten12 equal yes+no+on+off+true+false");
command("variable err1 equal v_one/v_ten7");
command("variable err2 equal v_one%v_ten7");
@ -350,7 +350,7 @@ TEST_F(VariableTest, Expressions)
command("variable vec2 vector v_vec1*0.5");
command("variable vec3 equal v_vec2[3]");
command("variable vec4 vector '[1, 5, 2.5, -10, -5, 20, 120, 4, 3, 3]'");
command("variable sort vector sort(v_vec4)");
command("variable sort vector sort(v_vec4 )");
command("variable rsrt vector rsort(v_vec4)");
command("variable max2 equal sort(v_vec4)[2]");
command("variable rmax equal rsort(v_vec4)[1]");

View File

@ -538,6 +538,27 @@ create_atoms 1 single &
expanded = self.lmp.expand("'xx_$(4+5)_$(PI) ${one}-${two}-${three}'")
self.assertEqual(expanded, "'xx_$(4+5)_$(PI) ${one}-${two}-${three}'")
def test_eval(self):
self.lmp.commands_string(
"""region box1 block 0 10 0 5 -0.5 0.5
lattice fcc 0.8
create_box 1 box1
create_atoms 1 box
mass * 1.0
pair_style lj/cut 4.0
pair_coeff * * 1.0 1.0
variable t equal 15.0
velocity all create 1.5 532656
fix 1 all nve
run 0 post no""")
self.lmp.command("variable one index 1 2 3 4")
self.lmp.command("variable two equal 2")
self.assertEqual(self.lmp.eval("4+5"), 9.0)
self.assertEqual(self.lmp.eval("v_one / 2.0"), 0.5)
self.assertEqual(self.lmp.eval("count(all)"), 36.0)
self.assertEqual(self.lmp.eval("pe"), -3.9848867644689534)
def test_get_thermo(self):
self.lmp.command("units lj")
self.lmp.command("atom_style atomic")