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_MANIFOLD=on \
-D PKG_MDI=on \ -D PKG_MDI=on \
-D PKG_MGPT=on \ -D PKG_MGPT=on \
-D PKG_ML-PACE=on \
-D PKG_ML-RANN=on \ -D PKG_ML-RANN=on \
-D PKG_MOLFILE=on \ -D PKG_MOLFILE=on \
-D PKG_NETCDF=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 Removed commands and packages
============================= =============================
.. contents::
------
This page lists LAMMPS commands and packages that have been removed from This page lists LAMMPS commands and packages that have been removed from
the distribution and provides suggestions for alternatives or the distribution and provides suggestions for alternatives or
replacements. LAMMPS has special dummy styles implemented, that will 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 style/command is used that has been removed or will replace the command
with the direct alternative (if available) and print a warning. 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 The LAMMPS shell has been removed from the LAMMPS distribution. Users
LAMMPS executable directly instead of having a separate tool. A are encouraged to use the :ref:`LAMMPS-GUI <lammps_gui>` tool instead.
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>`
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 The i-PI tool has been removed from the LAMMPS distribution. Instead,
since they were superseded by the more general and extensible "chunk instructions to install i-PI from PyPI via pip are provided.
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.
Box command USER-REAXC package
----------- ------------------
.. deprecated:: 22Dec2022 .. deprecated:: 7Feb2024
The *box* command has been removed and the LAMMPS code changed so it won't The USER-REAXC package has been renamed to :ref:`REAXFF <PKG-REAXFF>`.
be needed. If present, LAMMPS will ignore the command and print a warning. 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 The MPIIO package has been removed from LAMMPS since it was unmaintained
been folded into the :doc:`reset_atoms <reset_atoms>` command. If for many years and thus not updated to incorporate required changes that
present, LAMMPS will replace the commands accordingly and print a had been applied to the corresponding non-MPIIO commands. As a
warning. 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 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 with LATTE as a plugin library (similar to the way fix latte worked), as
well as on a different set of MPI processors. 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 Minimize style fire/old
----------------------- -----------------------
@ -97,38 +102,38 @@ The same functionality is available through
:doc:`bond style mesocnt <bond_mesocnt>` and :doc:`bond style mesocnt <bond_mesocnt>` and
:doc:`angle style mesocnt <angle_mesocnt>`. :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 The *box* command has been removed and the LAMMPS code changed so it won't
for many years and thus not updated to incorporate required changes that be needed. If present, LAMMPS will ignore the command and print a warning.
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>`.
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 MESSAGE package
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. .. 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 REAX package
------------ ------------
.. deprecated:: 4Jan2019
The REAX package has been removed since it was superseded by the The REAX package has been removed since it was superseded by the
:ref:`REAXFF package <PKG-REAXFF>`. The REAXFF package has been tested :ref:`REAXFF package <PKG-REAXFF>`. The REAXFF package has been tested
to yield equivalent results to the REAX package, offers better 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 have to be adapted. The REAXFF package was originally called
USER-REAXC. USER-REAXC.
USER-REAXC package MEAM package
------------------ ------------
.. deprecated:: 7Feb2024 .. deprecated:: 4Jan2019
The USER-REAXC package has been renamed to :ref:`REAXFF <PKG-REAXFF>`. The MEAM package in Fortran has been replaced by a C++ implementation.
In the process also the pair style and related fixes were renamed to use The code in the :ref:`MEAM package <PKG-MEAM>` is a translation of the
the "reaxff" string instead of "reax/c". For a while LAMMPS was maintaining Fortran code of MEAM into C++, which removes several restrictions
backward compatibility by providing aliases for the styles. These have (e.g. there can be multiple instances in hybrid pair styles) and allows
been removed, so using "reaxff" is now *required*. 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 USER-CUDA package
----------------- -----------------
.. deprecated:: 31May2016
The USER-CUDA package had been removed, since it had been unmaintained 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 for a long time and had known bugs and problems. Significant parts of
the design were transferred to the 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 the :ref:`GPU package <PKG-GPU>` are maintained
and allow running LAMMPS with GPU acceleration. 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, The fixes ave/spatial and ave/spatial/sphere have been removed from LAMMPS
instructions to install i-PI from PyPI via pip are provided. 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 The functionality of the restart2data tool has been folded into the
are encouraged to use the :ref:`LAMMPS-GUI <lammps_gui>` tool instead. 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 :ftype set_string_variable: subroutine
:f set_internal_variable: :f:subr:`set_internal_variable` :f set_internal_variable: :f:subr:`set_internal_variable`
:ftype set_internal_variable: subroutine :ftype set_internal_variable: subroutine
:f eval: :f:func:`eval`
:ftype eval: function
:f gather_atoms: :f:subr:`gather_atoms` :f gather_atoms: :f:subr:`gather_atoms`
:ftype gather_atoms: subroutine :ftype gather_atoms: subroutine
:f gather_atoms_concat: :f:subr:`gather_atoms_concat` :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 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. and thus time can be saved and people can focus on learning LAMMPS.
The tutorials at https://lammpstutorials.github.io/ are specifically 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 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 the functionality of LAMMPS-GUI with external tools. That said, LAMMPS-GUI
has some unique functionality that is not found elsewhere: has some unique functionality that is not found elsewhere:
- auto-adapting to features available in the integrated LAMMPS library - 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>` - interactive visualization using the :doc:`dump image <dump_image>`
command with the option to copy-paste the resulting settings command with the option to copy-paste the resulting settings
- automatic slide show generation from dump image out at runtime - 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_command`
- :cpp:func:`lammps_commands_list` - :cpp:func:`lammps_commands_list`
- :cpp:func:`lammps_commands_string` - :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 .. doxygenfunction:: lammps_commands_string
:project: progguide :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, This section documents accessing or modifying data stored by computes,
fixes, or variables in LAMMPS using the following functions: 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_string_variable`
- :cpp:func:`lammps_set_internal_variable` - :cpp:func:`lammps_set_internal_variable`
- :cpp:func:`lammps_variable_info` - :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_DATATYPE_CONST
.. doxygenenum:: _LMP_STYLE_CONST .. doxygenenum:: _LMP_STYLE_CONST

View File

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

View File

@ -163,6 +163,7 @@ struct _liblammpsplugin {
int (*set_string_variable)(void *, const char *, const char *); int (*set_string_variable)(void *, const char *, const char *);
int (*set_internal_variable)(void *, const char *, double); int (*set_internal_variable)(void *, const char *, double);
int (*variable_info)(void *, int, char *, int); int (*variable_info)(void *, int, char *, int);
double (*eval)(void *, const char *);
void (*gather_atoms)(void *, const char *, int, int, void *); void (*gather_atoms)(void *, const char *, int, int, void *);
void (*gather_atoms_concat)(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_variable => lmp_set_variable
PROCEDURE :: set_string_variable => lmp_set_string_variable PROCEDURE :: set_string_variable => lmp_set_string_variable
PROCEDURE :: set_internal_variable => lmp_set_internal_variable PROCEDURE :: set_internal_variable => lmp_set_internal_variable
PROCEDURE :: eval => lmp_eval
PROCEDURE, PRIVATE :: lmp_gather_atoms_int PROCEDURE, PRIVATE :: lmp_gather_atoms_int
PROCEDURE, PRIVATE :: lmp_gather_atoms_double PROCEDURE, PRIVATE :: lmp_gather_atoms_double
GENERIC :: gather_atoms => lmp_gather_atoms_int, & GENERIC :: gather_atoms => lmp_gather_atoms_int, &
@ -618,7 +619,14 @@ MODULE LIBLAMMPS
INTEGER(c_int) :: lammps_set_internal_variable INTEGER(c_int) :: lammps_set_internal_variable
END FUNCTION 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 IMPORT :: c_int, c_ptr
IMPLICIT NONE IMPLICIT NONE
TYPE(c_ptr), VALUE :: handle, name, data TYPE(c_ptr), VALUE :: handle, name, data
@ -1812,7 +1820,7 @@ CONTAINS
SUBROUTINE lmp_set_internal_variable(self, name, val) SUBROUTINE lmp_set_internal_variable(self, name, val)
CLASS(lammps), INTENT(IN) :: self CLASS(lammps), INTENT(IN) :: self
CHARACTER(LEN=*), INTENT(IN) :: name CHARACTER(LEN=*), INTENT(IN) :: name
REAL(KIND=c_double), INTENT(IN) :: val REAL(c_double), INTENT(IN) :: val
INTEGER :: err INTEGER :: err
TYPE(c_ptr) :: Cname TYPE(c_ptr) :: Cname
@ -1826,6 +1834,18 @@ CONTAINS
END IF END IF
END SUBROUTINE lmp_set_internal_variable 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) ! equivalent function to lammps_gather_atoms (for integers)
SUBROUTINE lmp_gather_atoms_int(self, name, count, data) SUBROUTINE lmp_gather_atoms_int(self, name, count, data)
CLASS(lammps), INTENT(IN) :: self 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 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 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 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 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 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.argtypes = [c_void_p, c_char_p]
self.lib.lammps_extract_variable_datatype.restype = c_int 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.argtypes = [c_void_p, c_char_p]
self.lib.lammps_fix_external_get_force.restype = POINTER(POINTER(c_double)) 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 # return vector of atom properties gathered across procs
# 3 variants to match src/library.cpp # 3 variants to match src/library.cpp
# name = atom property recognized by LAMMPS in atom->extract() # name = atom property recognized by LAMMPS in atom->extract()

View File

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

View File

@ -41,6 +41,9 @@ using namespace LAMMPS_NS;
using namespace FixConst; using namespace FixConst;
static constexpr double QSUMSMALL = 0.00001; 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 { namespace {
class qeq_parser_error : public std::exception { class qeq_parser_error : public std::exception {

View File

@ -16,12 +16,6 @@
#include "fix.h" #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 { namespace LAMMPS_NS {
class FixQEq : public Fix { class FixQEq : public Fix {
@ -36,6 +30,7 @@ class FixQEq : public Fix {
void min_pre_force(int) override; void min_pre_force(int) override;
double compute_scalar() override; double compute_scalar() override;
static constexpr double DANGER_ZONE = 0.90;
// derived child classes must provide these functions // derived child classes must provide these functions

View File

@ -33,6 +33,8 @@
using namespace LAMMPS_NS; 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) 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); MPI_Allreduce(&cpu_loop,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
cpu_loop = tmp/nprocs; cpu_loop = tmp/nprocs;
if (time_loop > 0.0) cpu_loop = cpu_loop/time_loop*100.0; if (time_loop > 0.0) cpu_loop = cpu_loop/time_loop*100.0;
output->thermo->footer();
if (me == 0) { if (me == 0) {
output->thermo->footer();
int ntasks = nprocs * nthreads; int ntasks = nprocs * nthreads;
utils::logmesg(lmp,"Loop time of {:.6g} on {} procs for {} steps with {} atoms\n\n", utils::logmesg(lmp,"Loop time of {:.6g} on {} procs for {} steps with {} atoms\n\n",
time_loop,ntasks,update->nsteps,atom->natoms); time_loop,ntasks,update->nsteps,atom->natoms);

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 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. must be freed with :cpp:func:`lammps_free` after use to avoid a memory leak.
*See also*
:cpp:func:`lammps_eval`
\endverbatim \endverbatim
* *
* \param handle pointer to a previously created LAMMPS instance * \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 trigger an evaluation. Instead it provides direct access to a read-only
location of the last thermo output data and the corresponding keyword 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* 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:: .. note::
@ -899,6 +906,14 @@ argument string.
- actual field data for column - actual field data for column
- pointer to int, int64_t or double - pointer to int, int64_t or double
- yes - yes
* - lock
- acquires lock to thermo data cache
- NULL pointer
- no
* - unlock
- releases lock to thermo data cache
- NULL pointer
- no
\endverbatim \endverbatim
* *
@ -954,8 +969,14 @@ void *lammps_last_thermo(void *handle, const char *what, int index)
} else if (field.type == multitype::LAMMPS_DOUBLE) { } else if (field.type == multitype::LAMMPS_DOUBLE) {
val = (void *) &field.data.d; 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; } else val = nullptr;
} }
END_CAPTURE END_CAPTURE
return val; return val;
@ -2904,6 +2925,39 @@ int lammps_variable_info(void *handle, int idx, char *buffer, int buf_size) {
return 0; 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 // 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_string_variable(void *handle, const char *name, const char *str);
int lammps_set_internal_variable(void *handle, const char *name, double value); int lammps_set_internal_variable(void *handle, const char *name, double value);
int lammps_variable_info(void *handle, int idx, char *buf, int bufsize); 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 * 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) : Thermo::Thermo(LAMMPS *_lmp, int narg, char **arg) :
Pointers(_lmp), style(nullptr), vtype(nullptr), field2index(nullptr), argindex1(nullptr), Pointers(_lmp), style(nullptr), vtype(nullptr), cache_mutex(nullptr), field2index(nullptr),
argindex2(nullptr), temperature(nullptr), pressure(nullptr), pe(nullptr) argindex1(nullptr), argindex2(nullptr), temperature(nullptr), pressure(nullptr), pe(nullptr)
{ {
style = utils::strdup(arg[0]); style = utils::strdup(arg[0]);
@ -208,6 +208,7 @@ void Thermo::init()
ValueTokenizer *format_line = nullptr; ValueTokenizer *format_line = nullptr;
if (format_line_user.size()) format_line = new ValueTokenizer(format_line_user); if (format_line_user.size()) format_line = new ValueTokenizer(format_line_user);
lock_cache();
field_data.clear(); field_data.clear();
field_data.resize(nfield); field_data.resize(nfield);
std::string format_this, format_line_user_def; std::string format_this, format_line_user_def;
@ -277,6 +278,7 @@ void Thermo::init()
format[i] += fmt::format("{:<8} = {} ", keyword[i], format_this); 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 // chop off trailing blank or add closing bracket if needed and then add newline
if (lineflag == ONELINE) if (lineflag == ONELINE)
@ -320,6 +322,9 @@ void Thermo::init()
if (index_press_scalar >= 0) pressure = computes[index_press_scalar]; if (index_press_scalar >= 0) pressure = computes[index_press_scalar];
if (index_press_vector >= 0) pressure = computes[index_press_vector]; if (index_press_vector >= 0) pressure = computes[index_press_vector];
if (index_pe >= 0) pe = computes[index_pe]; if (index_pe >= 0) pe = computes[index_pe];
// create mutex to protect access to cached thermo data
cache_mutex = new std::mutex;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -366,11 +371,19 @@ void Thermo::header()
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
// called at the end of a run from Finish class
void Thermo::footer() void Thermo::footer()
{ {
if (comm->me == 0) {
if (lineflag == YAMLLINE) utils::logmesg(lmp, "...\n"); if (lineflag == YAMLLINE) utils::logmesg(lmp, "...\n");
} }
// no more locking for cached thermo data access needed
delete cache_mutex;
cache_mutex = nullptr;
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
void Thermo::compute(int flag) void Thermo::compute(int flag)
@ -422,6 +435,7 @@ void Thermo::compute(int flag)
} }
// add each thermo value to line with its specific format // add each thermo value to line with its specific format
lock_cache();
field_data.clear(); field_data.clear();
field_data.resize(nfield); field_data.resize(nfield);
@ -441,6 +455,7 @@ void Thermo::compute(int flag)
field_data[ifield] = bivalue; field_data[ifield] = bivalue;
} }
} }
unlock_cache();
// print line to screen and logfile // 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"); if (iarg + 2 > narg) error->all(FLERR, "Illegal thermo_modify command");
triclinic_general = utils::logical(FLERR, arg[iarg + 1], false, lmp); triclinic_general = utils::logical(FLERR, arg[iarg + 1], false, lmp);
if (triclinic_general && !domain->triclinic_general) 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"); "if simulation box is not general triclinic");
iarg += 2; iarg += 2;
@ -1566,6 +1582,26 @@ int Thermo::evaluate_keyword(const std::string &word, double *answer)
return 0; 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 extraction of Compute, Fix, Variable results
compute/fix are normalized by atoms if returning extensive value compute/fix are normalized by atoms if returning extensive value

View File

@ -16,6 +16,7 @@
#include "pointers.h" #include "pointers.h"
#include <map> #include <map>
#include <mutex>
namespace LAMMPS_NS { namespace LAMMPS_NS {
@ -43,6 +44,8 @@ class Thermo : protected Pointers {
int evaluate_keyword(const std::string &, double *); int evaluate_keyword(const std::string &, double *);
// for accessing cached thermo and related data // for accessing cached thermo and related data
void lock_cache();
void unlock_cache();
const int *get_line() const { return &nline; } const int *get_line() const { return &nline; }
const char *get_image_fname() const { return image_fname.c_str(); } const char *get_image_fname() const { return image_fname.c_str(); }
@ -82,6 +85,9 @@ class Thermo : protected Pointers {
int nline; int nline;
std::string image_fname; std::string image_fname;
// mutex for locking the cache
std::mutex *cache_mutex;
// data used by routines that compute single values // data used by routines that compute single values
int ivalue; // integer value to print 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 // data = 2 values, 1st is string to eval, 2nd is filled on retrieval
} else if (strcmp(arg[1],"equal") == 0) { } else if (strcmp(arg[1],"equal") == 0) {
if (narg != 3) if (narg < 3) utils::missing_cmd_args(FLERR, "variable equal", error);
error->all(FLERR,"Illegal variable command: expected 3 arguments but found {}{}",
narg, utils::errorurl(3)); // 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]); int ivar = find(arg[0]);
if (ivar >= 0) { if (ivar >= 0) {
if (style[ivar] != EQUAL) if (style[ivar] != EQUAL)
error->all(FLERR,"Cannot redefine variable as a different style"); error->all(FLERR,"Cannot redefine variable as a different style");
delete[] data[ivar][0]; delete[] data[ivar][0];
data[ivar][0] = utils::strdup(arg[2]); data[ivar][0] = utils::strdup(combined);
replaceflag = 1; replaceflag = 1;
} else { } else {
if (nvar == maxvar) grow(); if (nvar == maxvar) grow();
@ -474,7 +480,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0; which[nvar] = 0;
pad[nvar] = 0; pad[nvar] = 0;
data[nvar] = new char*[num[nvar]]; 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]; data[nvar][1] = new char[VALUELENGTH];
strcpy(data[nvar][1],"(undefined)"); strcpy(data[nvar][1],"(undefined)");
} }
@ -485,15 +491,21 @@ void Variable::set(int narg, char **arg)
// data = 1 value, string to eval // data = 1 value, string to eval
} else if (strcmp(arg[1],"atom") == 0) { } else if (strcmp(arg[1],"atom") == 0) {
if (narg != 3) if (narg < 3) utils::missing_cmd_args(FLERR, "variable atom", error);
error->all(FLERR,"Illegal variable command: expected 3 arguments but found {}{}",
narg, utils::errorurl(3)); // 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]); int ivar = find(arg[0]);
if (ivar >= 0) { if (ivar >= 0) {
if (style[ivar] != ATOM) if (style[ivar] != ATOM)
error->all(FLERR,"Cannot redefine variable as a different style"); error->all(FLERR,"Cannot redefine variable as a different style");
delete[] data[ivar][0]; delete[] data[ivar][0];
data[ivar][0] = utils::strdup(arg[2]); data[ivar][0] = utils::strdup(combined);
replaceflag = 1; replaceflag = 1;
} else { } else {
if (nvar == maxvar) grow(); if (nvar == maxvar) grow();
@ -502,7 +514,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0; which[nvar] = 0;
pad[nvar] = 0; pad[nvar] = 0;
data[nvar] = new char*[num[nvar]]; data[nvar] = new char*[num[nvar]];
data[nvar][0] = utils::strdup(arg[2]); data[nvar][0] = utils::strdup(combined);
} }
// VECTOR // 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 // immediately store it as N-length vector and set dynamic flag to 0
} else if (strcmp(arg[1],"vector") == 0) { } else if (strcmp(arg[1],"vector") == 0) {
if (narg != 3) if (narg < 3) utils::missing_cmd_args(FLERR, "variable atom", error);
error->all(FLERR,"Illegal variable command: expected 3 arguments but found {}{}",
narg, utils::errorurl(3)); // 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]); int ivar = find(arg[0]);
if (ivar >= 0) { if (ivar >= 0) {
if (style[ivar] != VECTOR) if (style[ivar] != VECTOR)
error->all(FLERR,"Cannot redefine variable as a different style"); error->all(FLERR,"Cannot redefine variable as a different style");
delete[] data[ivar][0]; delete[] data[ivar][0];
delete[] data[ivar][1]; delete[] data[ivar][1];
data[ivar][0] = utils::strdup(arg[2]); data[ivar][0] = utils::strdup(combined);
if (data[ivar][0][0] != '[') if (data[ivar][0][0] != '[')
vecs[ivar].dynamic = 1; vecs[ivar].dynamic = 1;
else { else {
@ -539,7 +557,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0; which[nvar] = 0;
pad[nvar] = 0; pad[nvar] = 0;
data[nvar] = new char*[num[nvar]]; data[nvar] = new char*[num[nvar]];
data[nvar][0] = utils::strdup(arg[2]); data[nvar][0] = utils::strdup(combined);
if (data[nvar][0][0] != '[') { if (data[nvar][0][0] != '[') {
vecs[nvar].dynamic = 1; vecs[nvar].dynamic = 1;
data[nvar][1] = nullptr; data[nvar][1] = nullptr;

View File

@ -61,6 +61,8 @@
Highlight warnings and error messages in Output window Highlight warnings and error messages in Output window
Make Tutorial wizards more compact Make Tutorial wizards more compact
Include download and compilation of WHAM software from Alan Grossfield 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> </description>
</release> </release>
<release version="1.6.11" timestamp="1725080055"> <release version="1.6.11" timestamp="1725080055">

View File

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

View File

@ -55,8 +55,79 @@ index 0000000..b4f0fe6
+ TYPE DOC + TYPE DOC
+ PERMISSIONS OWNER_READ GROUP_READ WORLD_READ + 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 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 --- a/wham-2d/wham-2d.c
+++ b/wham-2d/wham-2d.c +++ b/wham-2d/wham-2d.c
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
@ -77,6 +148,15 @@ index fb6e059..2c5594f 100644
int main(int argc, char *argv[]) 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++) @@ -76,6 +76,61 @@ for (i=0; i<argc; i++)
} }
printf("\n"); printf("\n");
@ -139,6 +219,143 @@ index fb6e059..2c5594f 100644
PERIODICx = parse_periodic(argv[1], &PERIODx); PERIODICx = parse_periodic(argv[1], &PERIODx);
if (PERIODICx) 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 diff --git a/wham-2d/wham-2d.h b/wham-2d/wham-2d.h
index b17e4bd..5fc17ff 100644 index b17e4bd..5fc17ff 100644
--- a/wham-2d/wham-2d.h --- a/wham-2d/wham-2d.h
@ -163,10 +380,67 @@ index b17e4bd..5fc17ff 100644
// Value inserted for the free energy of masked values // 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 diff --git a/wham/wham.c b/wham/wham.c
index 487871b..1496eed 100644 index 487871b..edb8125 100644
--- a/wham/wham.c --- a/wham/wham.c
+++ b/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 @@ @@ -21,7 +21,7 @@
#include "wham.h" #include "wham.h"
@ -184,6 +458,15 @@ index 487871b..1496eed 100644
int main(int argc, char *argv[]) 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++) @@ -82,6 +83,61 @@ for (i=0; i<argc; i++)
} }
printf("\n"); printf("\n");
@ -246,6 +529,213 @@ index 487871b..1496eed 100644
if (toupper(argv[1][0]) == 'P') if (toupper(argv[1][0]) == 'P')
{ {
PERIODIC = 1; 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 diff --git a/wham/wham.h b/wham/wham.h
index aacc1e8..7d509f2 100644 index aacc1e8..7d509f2 100644
--- a/wham/wham.h --- 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_variable(void *, const char *, const char *);
extern int lammps_set_string_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_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(void *, char *, int, int, void *);
extern void lammps_gather_atoms_concat(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_variable(void *, const char *, const char *);
extern int lammps_set_string_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_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(void *, char *, int, int, void *);
extern void lammps_gather_atoms_concat(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}'")); EXPECT_THAT((char *)ptr, StrEq("'xx_$(4+5)_$(PI) ${one}-${two}-${three}'"));
lammps_free(ptr); 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

@ -538,6 +538,27 @@ create_atoms 1 single &
expanded = self.lmp.expand("'xx_$(4+5)_$(PI) ${one}-${two}-${three}'") expanded = self.lmp.expand("'xx_$(4+5)_$(PI) ${one}-${two}-${three}'")
self.assertEqual(expanded, "'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): def test_get_thermo(self):
self.lmp.command("units lj") self.lmp.command("units lj")
self.lmp.command("atom_style atomic") self.lmp.command("atom_style atomic")