Merge remote-tracking branch 'github/develop' into python_computes

This commit is contained in:
Axel Kohlmeyer
2025-01-14 00:53:19 -05:00
38 changed files with 1931 additions and 258 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

@ -605,6 +605,16 @@ foreach(PKG_WITH_INCL KSPACE PYTHON ML-IAP VORONOI COLVARS ML-HDNNP MDI MOLFILE
endif()
endforeach()
# settings for misc packages and styles
if(PKG_MISC)
option(LAMMPS_ASYNC_IMD "Asynchronous IMD processing" OFF)
mark_as_advanced(LAMMPS_ASYNC_IMD)
if(LAMMPS_ASYNC_IMD)
target_compile_definitions(lammps PRIVATE -DLAMMPS_ASYNC_IMD)
message(STATUS "Using IMD in asynchronous mode")
endif()
endif()
# optionally enable building script wrappers using swig
option(WITH_SWIG "Build scripting language wrappers with SWIG" OFF)
if(WITH_SWIG)

View File

@ -48,6 +48,7 @@ This is the list of packages that may require additional steps.
* :ref:`LEPTON <lepton>`
* :ref:`MACHDYN <machdyn>`
* :ref:`MDI <mdi>`
* :ref:`MISC <misc>`
* :ref:`ML-HDNNP <ml-hdnnp>`
* :ref:`ML-IAP <mliap>`
* :ref:`ML-PACE <ml-pace>`
@ -2031,7 +2032,7 @@ TBB and MKL.
.. _mdi:
MDI package
-----------------------------
-----------
.. tabs::
@ -2058,6 +2059,37 @@ MDI package
----------
.. _misc:
MISC package
------------
The :doc:`fix imd <fix_imd>` style in this package can be run either
synchronously (communication with IMD clients is done in the main
process) or asynchronously (the fix spawns a separate thread that can
communicate with IMD clients concurrently to the LAMMPS execution).
.. tabs::
.. tab:: CMake build
.. code-block:: bash
-D LAMMPS_ASYNC_IMD=value # Run IMD server asynchronously
# value = no (default) or yes
.. tab:: Traditional make
To enable asynchronous mode the ``-DLAMMPS_ASYNC_IMD`` define
needs to be added to the ``LMP_INC`` variable in the
``Makefile.machine`` you are using. For example:
.. code-block:: make
LMP_INC = -DLAMMPS_ASYNC_IMD -DLAMMPS_MEMALIGN=64
----------
.. _molfile:
MOLFILE package

View File

@ -49,6 +49,7 @@ packages:
* :ref:`LEPTON <lepton>`
* :ref:`MACHDYN <machdyn>`
* :ref:`MDI <mdi>`
* :ref:`MISC <misc>`
* :ref:`ML-HDNNP <ml-hdnnp>`
* :ref:`ML-IAP <mliap>`
* :ref:`ML-PACE <ml-pace>`

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

@ -26,6 +26,29 @@ Syntax
*nowait* arg = *on* or *off*
off = LAMMPS waits to be connected to an IMD client before continuing (default)
on = LAMMPS listens for an IMD client, but continues with the run
*version* arg = *2* or *3*
2 = use IMD protocol version 2 (default)
3 = use IMD protocol version 3.
The following keywords are only supported for IMD protocol version 3.
.. parsed-literal::
*time* arg = *on* or *off*
off = simulation time is not transmitted (default)
on = simulation time is transmitted.
*box* arg = *on* or *off*
off = simulation box data is not transmitted (default)
on = simulation box data is transmitted.
*coordinates* arg = *on* or *off*
off = atomic coordinates are not transmitted (default)
on = atomic coordinates are transmitted.
*velocities* arg = *on* or *off*
off = atomic velocities are not transmitted (default)
on = atomic velocities are transmitted.
*forces* arg = *on* or *off*
off = atomic forces are not transmitted (default)
on = atomic forces are transmitted.
Examples
""""""""
@ -40,16 +63,19 @@ Description
This fix implements the "Interactive MD" (IMD) protocol which allows
realtime visualization and manipulation of MD simulations through the
IMD protocol, as initially implemented in VMD and NAMD. Specifically
it allows LAMMPS to connect an IMD client, for example the `VMD visualization program <VMD_>`_, so that it can monitor the progress of the
simulation and interactively apply forces to selected atoms.
IMD protocol, as initially implemented in VMD and NAMD. Specifically it
allows LAMMPS to connect an IMD client, for example the `VMD
visualization program <VMD_>`_ (currently only supports IMDv2) or the
`Python IMDClient <IMDClient_>`_ (supports both IMDv2 and IMDv3), so
that it can monitor the progress of the simulation and interactively
apply forces to selected atoms.
If LAMMPS is compiled with the pre-processor flag -DLAMMPS_ASYNC_IMD
then fix imd will use POSIX threads to spawn a IMD communication
thread on MPI rank 0 in order to offload data reading and writing
from the main execution thread and potentially lower the inferred
latencies for slow communication links. This feature has only been
tested under linux.
If LAMMPS is compiled with the pre-processor flag
:ref:`-DLAMMPS_ASYNC_IMD <misc>` then fix imd will use POSIX threads to
spawn an IMD communication thread on MPI rank 0 in order to offload data
exchange with the IMD client from the main execution thread and
potentially lower the inferred latencies for slow communication
links. This feature has only been tested under linux.
The source code for this fix includes code developed by the Theoretical
and Computational Biophysics Group in the Beckman Institute for Advanced
@ -94,6 +120,15 @@ with different units or as a measure to tweak the forces generated by
the manipulation of the IMD client, this option allows to make
adjustments.
.. versionadded:: TBD
In `IMDv3 <IMDv3_>`_, the IMD protocol has been extended to allow for
the transmission of simulation time, box dimensions, atomic coordinates,
velocities, and forces. The *version* keyword allows to select the
version of the protocol to be used. The *time*, *box*, *coordinates*,
*velocities*, and *forces* keywords allow to select which data is
transmitted to the IMD client. The default is to transmit all data.
To connect VMD to a listening LAMMPS simulation on the same machine
with fix imd enabled, one needs to start VMD and load a coordinate or
topology file that matches the fix group. When the VMD command
@ -129,6 +164,10 @@ screen output is active.
.. _imdvmd: https://www.ks.uiuc.edu/Research/vmd/imd/
.. _IMDClient: https://github.com/Becksteinlab/imdclient/tree/main/imdclient
.. _IMDv3: https://imdclient.readthedocs.io/en/latest/protocol_v3.html
Restart, fix_modify, output, run start/stop, minimize info
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
@ -147,14 +186,14 @@ This fix is part of the MISC package. It is only enabled if LAMMPS was
built with that package. See the :doc:`Build package <Build_package>`
page for more info.
When used in combination with VMD, a topology or coordinate file has
to be loaded, which matches (in number and ordering of atoms) the
group the fix is applied to. The fix internally sorts atom IDs by
ascending integer value; in VMD (and thus the IMD protocol) those will
be assigned 0-based consecutive index numbers.
When used in combination with VMD, a topology or coordinate file has to
be loaded, which matches (in number and ordering of atoms) the group the
fix is applied to. The fix internally sorts atom IDs by ascending
integer value; in VMD (and thus the IMD protocol) those will be assigned
0-based consecutive index numbers.
When using multiple active IMD connections at the same time, each
needs to use a different port number.
fix instance needs to use a different port number.
Related commands
""""""""""""""""

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

@ -0,0 +1,13 @@
"""
For use with 'in.deca-ala-solv_imd_v3'.
Tested with imdclient v0.1.4 and MDAnalysis v2.8.0
"""
from imdclient.IMD import IMDReader
import MDAnalysis as mda
u = mda.Universe('data.deca-ala-solv', "imd://localhost:5678", topology_format='DATA')
for ts in u.trajectory:
print(ts.time)
print(ts.velocities)

View File

@ -0,0 +1,31 @@
#
units real
neighbor 2.5 bin
neigh_modify delay 1 every 1
atom_style full
bond_style harmonic
angle_style charmm
dihedral_style charmm
improper_style harmonic
pair_style lj/charmm/coul/long 8 10
pair_modify mix arithmetic
special_bonds charmm
read_data data.deca-ala-solv
group peptide id <= 103
fix rigidh all shake 1e-6 100 1000 t 1 2 3 4 5 a 23
thermo 100
thermo_style multi
timestep 2.0
kspace_style pppm 1e-5
fix ensemble all npt temp 300.0 300.0 100.0 iso 1.0 1.0 1000.0 drag 0.2
# IMD setup. Client code available in 'deca-ala-solv_imd_v3.py'
fix comm all imd 5678 unwrap on trate 10 version 3 time on box on coordinates on velocities on forces off
run 5000000

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
@ -426,6 +426,9 @@ class lammps(object):
self.lib.lammps_compute_addstep.argtype = [c_void_p, self.c_bigint]
self.lib.lammps_compute_addstep_all.argtype = [c_void_p, self.c_bigint]
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))
@ -1693,6 +1696,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;

File diff suppressed because it is too large Load Diff

View File

@ -56,6 +56,9 @@ FixStyle(imd,FixIMD);
#include <pthread.h>
#endif
/* IMDv3 session information */
struct IMDSessionInfo;
/* prototype for c wrapper that calls the real worker */
extern "C" void *fix_imd_ioworker(void *);
@ -69,8 +72,12 @@ class FixIMD : public Fix {
void init() override;
void setup(int) override;
void post_force(int) override;
void end_of_step() override;
void post_force_respa(int, int, int) override;
double memory_usage() override;
// Fix nevery at 1, use trate to skip in 'end_of_step`
int nevery = 1;
int imd_version; // version of the IMD protocol to be used.
protected:
int imd_port;
@ -80,13 +87,15 @@ class FixIMD : public Fix {
int num_coords; // total number of atoms controlled by this fix
int size_one; // bytes per atom in communication buffer.
int maxbuf; // size of atom communication buffer.
void *comm_buf; // communication buffer
void *coord_data; // communication buffer for coordinates
void *vel_data; // communication buffer for velocities
void *force_data; // communication buffer for forces
void *idmap; // hash for mapping atom indices to consistent order.
tagint *rev_idmap; // list of the hash keys for reverse mapping.
int imd_forces; // number of forces communicated via IMD.
void *force_buf; // force data buffer
double imd_fscale; // scale factor for forces. in case VMD's units are off.
int imd_forces; // number of forces communicated via IMD.
void *recv_force_buf; // force data buffer
double imd_fscale; // scale factor for forces. in case VMD's units are off.
int imd_inactive; // true if IMD connection stopped.
int imd_terminate; // true if IMD requests termination of run.
@ -96,12 +105,22 @@ class FixIMD : public Fix {
int nowait_flag; // true if LAMMPS should not wait with the execution for VMD.
int connect_msg; // flag to indicate whether a "listen for connection message" is needed.
/* IMDv3-only */
IMDSessionInfo *imdsinfo; // session information for IMDv3
int me; // my MPI rank in this "world".
int nlevels_respa; // flag to determine respa levels.
int msglen;
char *msgdata;
private:
void setup_v2();
void setup_v3();
void handle_step_v2();
void handle_client_input_v3();
void handle_output_v3();
#if defined(LAMMPS_ASYNC_IMD)
int buf_has_data; // flag to indicate to the i/o thread what to do.
pthread_mutex_t write_mutex; // mutex for sending coordinates to i/o thread

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;
@ -2906,6 +2927,41 @@ int lammps_variable_info(void *handle, int idx, char *buffer, int buf_size) {
/* ---------------------------------------------------------------------- */
/** 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;
}
/* ---------------------------------------------------------------------- */
/** Clear whether a compute has been invoked.
*
\verbatim embed:rst

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);
void lammps_compute_clearstep(void * handle);
#if defined(LAMMPS_SMALLSMALL)

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")