Merge branch 'develop' into add-error-explanations
This commit is contained in:
@ -3,6 +3,9 @@
|
||||
# CMake build system
|
||||
# This file is part of LAMMPS
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.20)
|
||||
message(WARNING "LAMMPS is planning to require at least CMake version 3.20 by Summer 2025. Please upgrade!")
|
||||
endif()
|
||||
########################################
|
||||
# set policy to silence warnings about ignoring <PackageName>_ROOT but use it
|
||||
if(POLICY CMP0074)
|
||||
@ -144,16 +147,28 @@ if((PKG_KOKKOS) AND (Kokkos_ENABLE_CUDA) AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL
|
||||
set(CMAKE_TUNE_DEFAULT "${CMAKE_TUNE_DEFAULT}" "-Xcudafe --diag_suppress=unrecognized_pragma,--diag_suppress=128")
|
||||
endif()
|
||||
|
||||
# we require C++11 without extensions. Kokkos requires at least C++17 (currently)
|
||||
# we *require* C++11 without extensions but prefer C++17.
|
||||
# Kokkos requires at least C++17 (currently)
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
if(cxx_std_17 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_CXX_STANDARD LESS 11)
|
||||
message(FATAL_ERROR "C++ standard must be set to at least 11")
|
||||
endif()
|
||||
if(CMAKE_CXX_STANDARD LESS 17)
|
||||
message(WARNING "Selecting C++17 standard is preferred over C++${CMAKE_CXX_STANDARD}")
|
||||
endif()
|
||||
if(PKG_KOKKOS AND (CMAKE_CXX_STANDARD LESS 17))
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
endif()
|
||||
# turn off C++17 check in lmptype.h
|
||||
if(LAMMPS_CXX11)
|
||||
add_compile_definitions(LAMMPS_CXX11)
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Use compiler extensions")
|
||||
# ugly hacks for MSVC which by default always reports an old C++ standard in the __cplusplus macro
|
||||
@ -347,6 +362,17 @@ foreach(PKG ${STANDARD_PACKAGES} ${SUFFIX_PACKAGES})
|
||||
option(PKG_${PKG} "Build ${PKG} Package" OFF)
|
||||
endforeach()
|
||||
|
||||
set(DEPRECATED_PACKAGES AWPMD ATC POEMS)
|
||||
foreach(PKG ${DEPRECATED_PACKAGES})
|
||||
if(PKG_${PKG})
|
||||
message(WARNING
|
||||
"The ${PKG} package will be removed from LAMMPS in Summer 2025 due to lack of "
|
||||
"maintenance and use of code constructs that conflict with modern C++ compilers "
|
||||
"and standards. Please contact developers@lammps.org if you have any concerns "
|
||||
"about this step.")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
######################################################
|
||||
# packages with special compiler needs or external libs
|
||||
######################################################
|
||||
|
||||
@ -1,50 +1,62 @@
|
||||
# PACE library support for ML-PACE package
|
||||
find_package(pace QUIET)
|
||||
|
||||
# set policy to silence warnings about timestamps of downloaded files. review occasionally if it may be set to NEW
|
||||
if(POLICY CMP0135)
|
||||
cmake_policy(SET CMP0135 OLD)
|
||||
endif()
|
||||
|
||||
set(PACELIB_URL "https://github.com/ICAMS/lammps-user-pace/archive/refs/tags/v.2023.11.25.fix.tar.gz" CACHE STRING "URL for PACE evaluator library sources")
|
||||
set(PACELIB_MD5 "b45de9a633f42ed65422567e3ce56f9f" CACHE STRING "MD5 checksum of PACE evaluator library tarball")
|
||||
mark_as_advanced(PACELIB_URL)
|
||||
mark_as_advanced(PACELIB_MD5)
|
||||
GetFallbackURL(PACELIB_URL PACELIB_FALLBACK)
|
||||
|
||||
# LOCAL_ML-PACE points to top-level dir with local lammps-user-pace repo,
|
||||
# to make it easier to check local build without going through the public github releases
|
||||
if(LOCAL_ML-PACE)
|
||||
set(lib-pace "${LOCAL_ML-PACE}")
|
||||
if(pace_FOUND)
|
||||
find_package(pace)
|
||||
target_link_libraries(lammps PRIVATE pace::pace)
|
||||
else()
|
||||
# download library sources to build folder
|
||||
if(EXISTS ${CMAKE_BINARY_DIR}/libpace.tar.gz)
|
||||
file(MD5 ${CMAKE_BINARY_DIR}/libpace.tar.gz DL_MD5)
|
||||
endif()
|
||||
if(NOT "${DL_MD5}" STREQUAL "${PACELIB_MD5}")
|
||||
message(STATUS "Downloading ${PACELIB_URL}")
|
||||
file(DOWNLOAD ${PACELIB_URL} ${CMAKE_BINARY_DIR}/libpace.tar.gz STATUS DL_STATUS SHOW_PROGRESS)
|
||||
file(MD5 ${CMAKE_BINARY_DIR}/libpace.tar.gz DL_MD5)
|
||||
if((NOT DL_STATUS EQUAL 0) OR (NOT "${DL_MD5}" STREQUAL "${PACELIB_MD5}"))
|
||||
message(WARNING "Download from primary URL ${PACELIB_URL} failed\nTrying fallback URL ${PACELIB_FALLBACK}")
|
||||
file(DOWNLOAD ${PACELIB_FALLBACK} ${CMAKE_BINARY_DIR}/libpace.tar.gz EXPECTED_HASH MD5=${PACELIB_MD5} SHOW_PROGRESS)
|
||||
# set policy to silence warnings about timestamps of downloaded files. review occasionally if it may be set to NEW
|
||||
if(POLICY CMP0135)
|
||||
cmake_policy(SET CMP0135 OLD)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using already downloaded archive ${CMAKE_BINARY_DIR}/libpace.tar.gz")
|
||||
endif()
|
||||
|
||||
set(PACELIB_URL "https://github.com/ICAMS/lammps-user-pace/archive/refs/tags/v.2023.11.25.fix2.tar.gz" CACHE STRING "URL for PACE evaluator library sources")
|
||||
set(PACELIB_MD5 "a53bd87cfee8b07d9f44bc17aad69c3f" CACHE STRING "MD5 checksum of PACE evaluator library tarball")
|
||||
mark_as_advanced(PACELIB_URL)
|
||||
mark_as_advanced(PACELIB_MD5)
|
||||
GetFallbackURL(PACELIB_URL PACELIB_FALLBACK)
|
||||
|
||||
# LOCAL_ML-PACE points to top-level dir with local lammps-user-pace repo,
|
||||
# to make it easier to check local build without going through the public github releases
|
||||
if(LOCAL_ML-PACE)
|
||||
set(lib-pace "${LOCAL_ML-PACE}")
|
||||
else()
|
||||
# download library sources to build folder
|
||||
if(EXISTS ${CMAKE_BINARY_DIR}/libpace.tar.gz)
|
||||
file(MD5 ${CMAKE_BINARY_DIR}/libpace.tar.gz DL_MD5)
|
||||
endif()
|
||||
if(NOT "${DL_MD5}" STREQUAL "${PACELIB_MD5}")
|
||||
message(STATUS "Downloading ${PACELIB_URL}")
|
||||
file(DOWNLOAD ${PACELIB_URL} ${CMAKE_BINARY_DIR}/libpace.tar.gz STATUS DL_STATUS SHOW_PROGRESS)
|
||||
file(MD5 ${CMAKE_BINARY_DIR}/libpace.tar.gz DL_MD5)
|
||||
if((NOT DL_STATUS EQUAL 0) OR (NOT "${DL_MD5}" STREQUAL "${PACELIB_MD5}"))
|
||||
message(WARNING "Download from primary URL ${PACELIB_URL} failed\nTrying fallback URL ${PACELIB_FALLBACK}")
|
||||
file(DOWNLOAD ${PACELIB_FALLBACK} ${CMAKE_BINARY_DIR}/libpace.tar.gz EXPECTED_HASH MD5=${PACELIB_MD5} SHOW_PROGRESS)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using already downloaded archive ${CMAKE_BINARY_DIR}/libpace.tar.gz")
|
||||
endif()
|
||||
|
||||
|
||||
# uncompress downloaded sources
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory lammps-user-pace*
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xzf libpace.tar.gz
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
get_newest_file(${CMAKE_BINARY_DIR}/lammps-user-pace-* lib-pace)
|
||||
endif()
|
||||
|
||||
add_subdirectory(${lib-pace} build-pace)
|
||||
set_target_properties(pace PROPERTIES CXX_EXTENSIONS ON OUTPUT_NAME lammps_pace${LAMMPS_MACHINE})
|
||||
|
||||
if(CMAKE_PROJECT_NAME STREQUAL "lammps")
|
||||
target_link_libraries(lammps PRIVATE pace)
|
||||
# uncompress downloaded sources
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory lammps-user-pace*
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xzf libpace.tar.gz
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
get_newest_file(${CMAKE_BINARY_DIR}/lammps-user-pace-* lib-pace)
|
||||
endif()
|
||||
|
||||
# some preinstalled yaml-cpp versions don't provide a namespaced target
|
||||
find_package(yaml-cpp QUIET)
|
||||
if(TARGET yaml-cpp AND NOT TARGET yaml-cpp::yaml-cpp)
|
||||
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
|
||||
endif()
|
||||
|
||||
add_subdirectory(${lib-pace} build-pace)
|
||||
set_target_properties(pace PROPERTIES CXX_EXTENSIONS ON OUTPUT_NAME lammps_pace${LAMMPS_MACHINE})
|
||||
|
||||
if(CMAKE_PROJECT_NAME STREQUAL "lammps")
|
||||
target_link_libraries(lammps PRIVATE pace)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
Build LAMMPS
|
||||
============
|
||||
|
||||
LAMMPS is built as a library and an executable from source code using
|
||||
either traditional makefiles for use with GNU make (which may require
|
||||
manual editing), or using a build environment generated by CMake (Unix
|
||||
Makefiles, Ninja, Xcode, Visual Studio, KDevelop, CodeBlocks and more).
|
||||
LAMMPS is built as a library and an executable from source code using a
|
||||
build environment generated by CMake (Unix Makefiles, Ninja, Xcode,
|
||||
Visual Studio, KDevelop, CodeBlocks and more depending on the platform).
|
||||
Using CMake is the preferred way to build LAMMPS. In addition, LAMMPS
|
||||
can be compiled using the legacy build system based on traditional
|
||||
makefiles for use with GNU make (which may require manual editing).
|
||||
Support for the legacy build system is slowly being phased out and may
|
||||
not be available for all optional features.
|
||||
|
||||
As an alternative, you can download a package with pre-built executables
|
||||
or automated build trees, as described in the :doc:`Install <Install>`
|
||||
|
||||
@ -16,7 +16,7 @@ environments is on a :doc:`separate page <Howto_cmake>`.
|
||||
|
||||
.. note::
|
||||
|
||||
LAMMPS currently requires that CMake version 3.16 or later is available.
|
||||
LAMMPS currently requires that CMake version 3.20 or later is available.
|
||||
|
||||
.. warning::
|
||||
|
||||
@ -32,11 +32,11 @@ environments is on a :doc:`separate page <Howto_cmake>`.
|
||||
Advantages of using CMake
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
CMake is an alternative to compiling LAMMPS in the traditional way
|
||||
through :doc:`(manually customized) makefiles <Build_make>`. Using
|
||||
CMake has multiple advantages that are specifically helpful for
|
||||
people with limited experience in compiling software or for people
|
||||
that want to modify or extend LAMMPS.
|
||||
CMake is the preferred way of compiling LAMMPS in contrast to the legacy
|
||||
build system based on GNU make and through :doc:`(manually customized)
|
||||
makefiles <Build_make>`. Using CMake has multiple advantages that are
|
||||
specifically helpful for people with limited experience in compiling
|
||||
software or for people that want to modify or extend LAMMPS.
|
||||
|
||||
- CMake can detect available hardware, tools, features, and libraries
|
||||
and adapt the LAMMPS default build configuration accordingly.
|
||||
@ -47,7 +47,7 @@ that want to modify or extend LAMMPS.
|
||||
knowledge of file formats or complex command-line syntax is required.
|
||||
- All enabled components are compiled in a single build operation.
|
||||
- Automated dependency tracking for all files and configuration options.
|
||||
- Support for true out-of-source compilation. Multiple configurations
|
||||
- Support for true out-of-source compilation. Multiple configurations
|
||||
and settings with different choices of LAMMPS packages, settings, or
|
||||
compilers can be configured and built concurrently from the same
|
||||
source tree.
|
||||
|
||||
@ -8,6 +8,10 @@ Building LAMMPS with traditional makefiles requires that you have a
|
||||
for customizing your LAMMPS build with a number of global compilation
|
||||
options and features.
|
||||
|
||||
This build system is slowly being phased out and may not support all
|
||||
optional features and packages in LAMMPS. It is recommended to switch
|
||||
to the :doc:`CMake based build system <Build_cmake>`.
|
||||
|
||||
Requirements
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
||||
@ -90,6 +90,7 @@ OPT.
|
||||
* :doc:`lepton (o) <angle_lepton>`
|
||||
* :doc:`mesocnt <angle_mesocnt>`
|
||||
* :doc:`mm3 <angle_mm3>`
|
||||
* :doc:`mwlc <angle_mwlc>`
|
||||
* :doc:`quartic (o) <angle_quartic>`
|
||||
* :doc:`spica (ko) <angle_spica>`
|
||||
* :doc:`table (o) <angle_table>`
|
||||
|
||||
@ -227,12 +227,12 @@ Tests for the C-style library interface
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Tests for validating the LAMMPS C-style library interface are in the
|
||||
``unittest/c-library`` folder. They are implemented either to be used
|
||||
for utility functions or for LAMMPS commands, but use the functions
|
||||
implemented in the ``src/library.cpp`` file as much as possible. There
|
||||
may be some overlap with other tests, but only in as much as is required
|
||||
to test the C-style library API. The tests are distributed over
|
||||
multiple test programs which try to match the grouping of the
|
||||
``unittest/c-library`` folder. They text either utility functions or
|
||||
LAMMPS commands, but use the functions implemented in
|
||||
``src/library.cpp`` as much as possible. There may be some overlap with
|
||||
other tests as far as the LAMMPS functionality is concerned, but the
|
||||
focus is on testing the C-style library API. The tests are distributed
|
||||
over multiple test programs which try to match the grouping of the
|
||||
functions in the source code and :ref:`in the manual <lammps_c_api>`.
|
||||
|
||||
This group of tests also includes tests invoking LAMMPS in parallel
|
||||
@ -258,7 +258,7 @@ Tests for the Python module and package
|
||||
|
||||
The ``unittest/python`` folder contains primarily tests for classes and
|
||||
functions in the LAMMPS python module but also for commands in the
|
||||
PYTHON package. These tests are only enabled if the necessary
|
||||
PYTHON package. These tests are only enabled, if the necessary
|
||||
prerequisites are detected or enabled during configuration and
|
||||
compilation of LAMMPS (shared library build enabled, Python interpreter
|
||||
found, Python development files found).
|
||||
@ -272,29 +272,30 @@ Tests for the Fortran interface
|
||||
|
||||
Tests for using the Fortran module are in the ``unittest/fortran``
|
||||
folder. Since they are also using the GoogleTest library, they require
|
||||
implementing test wrappers in C++ that will call fortran functions
|
||||
which provide a C function interface through ISO_C_BINDINGS that will in
|
||||
turn call the functions in the LAMMPS Fortran module.
|
||||
test wrappers written in C++ that will call fortran functions with a C
|
||||
function interface through ISO_C_BINDINGS which will in turn call the
|
||||
functions in the LAMMPS Fortran module.
|
||||
|
||||
Tests for the C++-style library interface
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The tests in the ``unittest/cplusplus`` folder are somewhat similar to
|
||||
the tests for the C-style library interface, but do not need to test the
|
||||
several convenience and utility functions that are only available through
|
||||
the C-style interface. Instead it can focus on the more generic features
|
||||
that are used internally. This part of the unit tests is currently still
|
||||
mostly in the planning stage.
|
||||
convenience and utility functions that are only available through the
|
||||
C-style library interface. Instead they focus on the more generic
|
||||
features that are used in LAMMPS internally. This part of the unit
|
||||
tests is currently still mostly in the planning stage.
|
||||
|
||||
Tests for reading and writing file formats
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``unittest/formats`` folder contains test programs for reading and
|
||||
writing files like data files, restart files, potential files or dump files.
|
||||
This covers simple things like the file i/o convenience functions in the
|
||||
``utils::`` namespace to complex tests of atom styles where creating and
|
||||
deleting atoms with different properties is tested in different ways
|
||||
and through script commands or reading and writing of data or restart files.
|
||||
writing files like data files, restart files, potential files or dump
|
||||
files. This covers simple things like the file i/o convenience
|
||||
functions in the ``utils::`` namespace to complex tests of atom styles
|
||||
where creating and deleting of atoms with different properties is tested
|
||||
in different ways and through script commands or reading and writing of
|
||||
data or restart files.
|
||||
|
||||
Tests for styles computing or modifying forces
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -443,7 +444,7 @@ file for a style that is similar to one to be tested. The file name should
|
||||
follow the naming conventions described above and after copying the file,
|
||||
the first step is to replace the style names where needed. The coefficient
|
||||
values do not have to be meaningful, just in a reasonable range for the
|
||||
given system. It does not matter if some forces are large, as long as
|
||||
given system. It does not matter if some forces are large, for as long as
|
||||
they do not diverge.
|
||||
|
||||
The template input files define a large number of index variables at the top
|
||||
@ -531,19 +532,20 @@ Python module.
|
||||
Troubleshooting failed unit tests
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The are by default no unit tests for newly added features (e.g. pair, fix,
|
||||
or compute styles) unless your pull request also includes tests for the
|
||||
added features. If you are modifying some features, you may see failures
|
||||
for existing tests, if your modifications have some unexpected side effects
|
||||
or your changes render the existing test invalid. If you are adding an
|
||||
accelerated version of an existing style, then only tests for INTEL,
|
||||
KOKKOS (with OpenMP only), OPENMP, and OPT will be run automatically.
|
||||
Tests for the GPU package are time consuming and thus are only run
|
||||
*after* a merge, or when a special label, ``gpu_unit_tests`` is added
|
||||
to the pull request. After the test has started, it is often best to
|
||||
remove the label since every PR activity will re-trigger the test (that
|
||||
is a limitation of triggering a test with a label). Support for unit
|
||||
tests when using KOKKOS with GPU acceleration is currently not supported.
|
||||
There are by default no unit tests for newly added features (e.g. pair,
|
||||
fix, or compute styles) unless your pull request also includes tests for
|
||||
these added features. If you are modifying some existing LAMMPS
|
||||
features, you may see failures for existing tests, if your modifications
|
||||
have some unexpected side effects or your changes render the existing
|
||||
test invalid. If you are adding an accelerated version of an existing
|
||||
style, then only tests for INTEL, KOKKOS (with OpenMP only), OPENMP, and
|
||||
OPT will be run automatically. Tests for the GPU package are time
|
||||
consuming and thus are only run *after* a merge, or when a special
|
||||
label, ``gpu_unit_tests`` is added to the pull request. After the test
|
||||
has started, it is often best to remove the label since every PR
|
||||
activity will re-trigger the test (that is a limitation of triggering a
|
||||
test with a label). Support for unit tests using KOKKOS with GPU
|
||||
acceleration is currently not supported.
|
||||
|
||||
When you see a failed build on GitHub, click on ``Details`` to be taken
|
||||
to the corresponding LAMMPS Jenkins CI web page. Click on the "Exit"
|
||||
@ -588,7 +590,7 @@ While the epsilon (relative precision) for a single, `IEEE 754 compliant
|
||||
<https://en.wikipedia.org/wiki/IEEE_754>`_, double precision floating
|
||||
point operation is at about 2.2e-16, the achievable precision for the
|
||||
tests is lower due to most numbers being sums over intermediate results
|
||||
and the non-associativity of floating point math leading to larger
|
||||
for which the non-associativity of floating point math leads to larger
|
||||
errors. As a rule of thumb, the test epsilon can often be in the range
|
||||
5.0e-14 to 1.0e-13. But for "noisy" force kernels, e.g. those a larger
|
||||
amount of arithmetic operations involving `exp()`, `log()` or `sin()`
|
||||
@ -602,7 +604,7 @@ of floating point operations or that some or most intermediate operations
|
||||
may be done using approximations or with single precision floating point
|
||||
math.
|
||||
|
||||
To rerun the failed unit test individually, change to the ``build`` directory
|
||||
To rerun a failed unit test individually, change to the ``build`` directory
|
||||
and run the test with verbose output. For example,
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -235,3 +235,53 @@ from GDB. In addition you get a more specific hint about what cause the
|
||||
segmentation fault, i.e. that it is a NULL pointer dereference. To find
|
||||
out which pointer exactly was NULL, you need to use the debugger, though.
|
||||
|
||||
Debugging when LAMMPS appears to be stuck
|
||||
=========================================
|
||||
|
||||
Sometimes the LAMMPS calculation appears to be stuck, that is the LAMMPS
|
||||
process or processes are active, but there is no visible progress. This
|
||||
can have multiple reasons:
|
||||
|
||||
- The selected styles are slow and require a lot of CPU time and the
|
||||
system is large. When extrapolating the expected speed from smaller
|
||||
systems, one has to factor in that not all models scale linearly with
|
||||
system size, e.g. :doc:`kspace styles like ewald or pppm
|
||||
<kspace_style>`. There is very little that can be done in this case.
|
||||
- The output interval is not set or set to a large value with the
|
||||
:doc:`thermo <thermo>` command. I the first case, there will be output
|
||||
only at the first and last step.
|
||||
- The output is block-buffered and instead of line-buffered. The output
|
||||
will only be written to the screen after 4096 or 8192 characters of
|
||||
output have accumulated. This most often happens for files but also
|
||||
with MPI parallel executables for output to the screen, since the
|
||||
output to the screen is handled by the MPI library so that output from
|
||||
all processes can be shown. This can be suppressed by using the
|
||||
``-nonblock`` or ``-nb`` command-line flag, which turns off buffering
|
||||
for screen and logfile output.
|
||||
- An MPI parallel calculation has a bug where a collective MPI function
|
||||
is called (e.g. ``MPI_Barrier()``, ``MPI_Bcast()``,
|
||||
``MPI_Allreduce()`` and so on) before pending point-to-point
|
||||
communications are completed or when the collective function is only
|
||||
called from a subset of the MPI processes. This also applies to some
|
||||
internal LAMMPS functions like ``Error::all()`` which uses
|
||||
``MPI_Barrier()`` and thus ``Error::one()`` must be called, if the
|
||||
error condition does not happen on all MPI processes simultaneously.
|
||||
- Some function in LAMMPS has a bug where a ``for`` or ``while`` loop
|
||||
does not trigger the exit condition and thus will loop forever. This
|
||||
can happen when the wrong variable is incremented or when one value in
|
||||
a comparison becomes ``NaN`` due to an overflow.
|
||||
|
||||
In the latter two cases, further information and stack traces (see above)
|
||||
can be obtain by attaching a debugger to a running process. For that the
|
||||
process ID (PID) is needed; this can be found on Linux machines with the
|
||||
``top``, ``htop``, ``ps``, or ``pstree`` commands.
|
||||
|
||||
Then running the (GNU) debugger ``gdb`` with the ``-p`` flag followed by
|
||||
the process id will attach the process to the debugger and stop
|
||||
execution of that specific process. From there on it is possible to
|
||||
issue all debugger commands in the same way as when LAMMPS was started
|
||||
from the debugger (see above). Most importantly it is possible to
|
||||
obtain a stack trace with the ``where`` command and thus determine where
|
||||
in the execution of a timestep this process is. Also internal data can
|
||||
be printed and execution single stepped or continued. When the debugger
|
||||
is exited, the calculation will resume normally.
|
||||
|
||||
@ -103,6 +103,7 @@ Tutorials howto
|
||||
Howto_github
|
||||
Howto_lammps_gui
|
||||
Howto_moltemplate
|
||||
Howto_python
|
||||
Howto_pylammps
|
||||
Howto_wsl
|
||||
|
||||
|
||||
@ -1,564 +1,6 @@
|
||||
PyLammps Tutorial
|
||||
=================
|
||||
|
||||
.. contents::
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
:py:class:`PyLammps <lammps.PyLammps>` is a Python wrapper class for
|
||||
LAMMPS which can be created on its own or use an existing
|
||||
:py:class:`lammps Python <lammps.lammps>` object. It creates a simpler,
|
||||
more "pythonic" interface to common LAMMPS functionality, in contrast to
|
||||
the :py:class:`lammps <lammps.lammps>` wrapper for the LAMMPS :ref:`C
|
||||
language library interface API <lammps_c_api>` which is written using
|
||||
`Python ctypes <ctypes_>`_. The :py:class:`lammps <lammps.lammps>`
|
||||
wrapper is discussed on the :doc:`Python_head` doc page.
|
||||
|
||||
Unlike the flat `ctypes <ctypes_>`_ interface, PyLammps exposes a
|
||||
discoverable API. It no longer requires knowledge of the underlying C++
|
||||
code implementation. Finally, the :py:class:`IPyLammps
|
||||
<lammps.IPyLammps>` wrapper builds on top of :py:class:`PyLammps
|
||||
<lammps.PyLammps>` and adds some additional features for `IPython
|
||||
integration <ipython_>`_ into `Jupyter notebooks <jupyter_>`_, e.g. for
|
||||
embedded visualization output from :doc:`dump style image <dump_image>`.
|
||||
|
||||
.. _ctypes: https://docs.python.org/3/library/ctypes.html
|
||||
.. _ipython: https://ipython.org/
|
||||
.. _jupyter: https://jupyter.org/
|
||||
|
||||
Comparison of lammps and PyLammps interfaces
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
lammps.lammps
|
||||
"""""""""""""
|
||||
|
||||
* uses `ctypes <ctypes_>`_
|
||||
* direct memory access to native C++ data with optional support for NumPy arrays
|
||||
* provides functions to send and receive data to LAMMPS
|
||||
* interface modeled after the LAMMPS :ref:`C language library interface API <lammps_c_api>`
|
||||
* requires knowledge of how LAMMPS internally works (C pointers, etc)
|
||||
* full support for running Python with MPI using `mpi4py <https://mpi4py.readthedocs.io>`_
|
||||
* no overhead from creating a more Python-like interface
|
||||
|
||||
lammps.PyLammps
|
||||
"""""""""""""""
|
||||
|
||||
* higher-level abstraction built on *top* of the original :py:class:`ctypes based interface <lammps.lammps>`
|
||||
* manipulation of Python objects
|
||||
* communication with LAMMPS is hidden from API user
|
||||
* shorter, more concise Python
|
||||
* better IPython integration, designed for quick prototyping
|
||||
* designed for serial execution
|
||||
* additional overhead from capturing and parsing the LAMMPS screen output
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
System-wide Installation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Step 1: Building LAMMPS as a shared library
|
||||
"""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
To use LAMMPS inside of Python it has to be compiled as shared
|
||||
library. This library is then loaded by the Python interface. In this
|
||||
example we enable the MOLECULE package and compile LAMMPS with PNG, JPEG
|
||||
and FFMPEG output support enabled.
|
||||
|
||||
Step 1a: For the CMake based build system, the steps are:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir $LAMMPS_DIR/build-shared
|
||||
cd $LAMMPS_DIR/build-shared
|
||||
|
||||
# MPI, PNG, Jpeg, FFMPEG are auto-detected
|
||||
cmake ../cmake -DPKG_MOLECULE=yes -DBUILD_LIB=yes -DBUILD_SHARED_LIBS=yes
|
||||
make
|
||||
|
||||
Step 1b: For the legacy, make based build system, the steps are:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd $LAMMPS_DIR/src
|
||||
|
||||
# add packages if necessary
|
||||
make yes-MOLECULE
|
||||
|
||||
# compile shared library using Makefile
|
||||
make mpi mode=shlib LMP_INC="-DLAMMPS_PNG -DLAMMPS_JPEG -DLAMMPS_FFMPEG" JPG_LIB="-lpng -ljpeg"
|
||||
|
||||
Step 2: Installing the LAMMPS Python package
|
||||
""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
PyLammps is part of the lammps Python package. To install it simply install
|
||||
that package into your current Python installation with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make install-python
|
||||
|
||||
.. note::
|
||||
|
||||
Recompiling the shared library requires re-installing the Python package
|
||||
|
||||
Installation inside of a virtualenv
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can use virtualenv to create a custom Python environment specifically tuned
|
||||
for your workflow.
|
||||
|
||||
Benefits of using a virtualenv
|
||||
""""""""""""""""""""""""""""""
|
||||
|
||||
* isolation of your system Python installation from your development installation
|
||||
* installation can happen in your user directory without root access (useful for HPC clusters)
|
||||
* installing packages through pip allows you to get newer versions of packages than e.g., through apt-get or yum package managers (and without root access)
|
||||
* you can even install specific old versions of a package if necessary
|
||||
|
||||
**Prerequisite (e.g. on Ubuntu)**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
apt-get install python-virtualenv
|
||||
|
||||
Creating a virtualenv with lammps installed
|
||||
"""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# create virtualenv named 'testing'
|
||||
virtualenv $HOME/python/testing
|
||||
|
||||
# activate 'testing' environment
|
||||
source $HOME/python/testing/bin/activate
|
||||
|
||||
Now configure and compile the LAMMPS shared library as outlined above.
|
||||
When using CMake and the shared library has already been build, you
|
||||
need to re-run CMake to update the location of the python executable
|
||||
to the location in the virtual environment with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake . -DPython_EXECUTABLE=$(which python)
|
||||
|
||||
# install LAMMPS package in virtualenv
|
||||
(testing) make install-python
|
||||
|
||||
# install other useful packages
|
||||
(testing) pip install matplotlib jupyter mpi4py
|
||||
|
||||
...
|
||||
|
||||
# return to original shell
|
||||
(testing) deactivate
|
||||
|
||||
Creating a new instance of PyLammps
|
||||
-----------------------------------
|
||||
|
||||
To create a PyLammps object you need to first import the class from the lammps
|
||||
module. By using the default constructor, a new *lammps* instance is created.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import PyLammps
|
||||
L = PyLammps()
|
||||
|
||||
You can also initialize PyLammps on top of this existing *lammps* object:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import lammps, PyLammps
|
||||
lmp = lammps()
|
||||
L = PyLammps(ptr=lmp)
|
||||
|
||||
Commands
|
||||
--------
|
||||
|
||||
Sending a LAMMPS command with the existing library interfaces is done using
|
||||
the command method of the lammps object instance.
|
||||
|
||||
For instance, let's take the following LAMMPS command:
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
region box block 0 10 0 5 -0.5 0.5
|
||||
|
||||
In the original interface this command can be executed with the following
|
||||
Python code if *L* was a lammps instance:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.command("region box block 0 10 0 5 -0.5 0.5")
|
||||
|
||||
With the PyLammps interface, any command can be split up into arbitrary parts
|
||||
separated by white-space, passed as individual arguments to a region method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.region("box block", 0, 10, 0, 5, -0.5, 0.5)
|
||||
|
||||
Note that each parameter is set as Python literal floating-point number. In the
|
||||
PyLammps interface, each command takes an arbitrary parameter list and transparently
|
||||
merges it to a single command string, separating individual parameters by white-space.
|
||||
|
||||
The benefit of this approach is avoiding redundant command calls and easier
|
||||
parameterization. In the original interface parameterization needed to be done
|
||||
manually by creating formatted strings.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.command("region box block %f %f %f %f %f %f" % (xlo, xhi, ylo, yhi, zlo, zhi))
|
||||
|
||||
In contrast, methods of PyLammps accept parameters directly and will convert
|
||||
them automatically to a final command string.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.region("box block", xlo, xhi, ylo, yhi, zlo, zhi)
|
||||
|
||||
System state
|
||||
------------
|
||||
|
||||
In addition to dispatching commands directly through the PyLammps object, it
|
||||
also provides several properties which allow you to query the system state.
|
||||
|
||||
L.system
|
||||
Is a dictionary describing the system such as the bounding box or number of atoms
|
||||
|
||||
L.system.xlo, L.system.xhi
|
||||
bounding box limits along x-axis
|
||||
|
||||
L.system.ylo, L.system.yhi
|
||||
bounding box limits along y-axis
|
||||
|
||||
L.system.zlo, L.system.zhi
|
||||
bounding box limits along z-axis
|
||||
|
||||
L.communication
|
||||
configuration of communication subsystem, such as the number of threads or processors
|
||||
|
||||
L.communication.nthreads
|
||||
number of threads used by each LAMMPS process
|
||||
|
||||
L.communication.nprocs
|
||||
number of MPI processes used by LAMMPS
|
||||
|
||||
L.fixes
|
||||
List of fixes in the current system
|
||||
|
||||
L.computes
|
||||
List of active computes in the current system
|
||||
|
||||
L.dump
|
||||
List of active dumps in the current system
|
||||
|
||||
L.groups
|
||||
List of groups present in the current system
|
||||
|
||||
Working with LAMMPS variables
|
||||
-----------------------------
|
||||
|
||||
LAMMPS variables can be both defined and accessed via the PyLammps interface.
|
||||
|
||||
To define a variable you can use the :doc:`variable <variable>` command:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.variable("a index 2")
|
||||
|
||||
A dictionary of all variables is returned by L.variables
|
||||
|
||||
you can access an individual variable by retrieving a variable object from the
|
||||
L.variables dictionary by name
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
a = L.variables['a']
|
||||
|
||||
The variable value can then be easily read and written by accessing the value
|
||||
property of this object.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
print(a.value)
|
||||
a.value = 4
|
||||
|
||||
Retrieving the value of an arbitrary LAMMPS expressions
|
||||
-------------------------------------------------------
|
||||
|
||||
LAMMPS expressions can be immediately evaluated by using the eval method. The
|
||||
passed string parameter can be any expression containing global thermo values,
|
||||
variables, compute or fix data.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
result = L.eval("ke") # kinetic energy
|
||||
result = L.eval("pe") # potential energy
|
||||
|
||||
result = L.eval("v_t/2.0")
|
||||
|
||||
Accessing atom data
|
||||
-------------------
|
||||
|
||||
All atoms in the current simulation can be accessed by using the L.atoms list.
|
||||
Each element of this list is an object which exposes its properties (id, type,
|
||||
position, velocity, force, etc.).
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# access first atom
|
||||
L.atoms[0].id
|
||||
L.atoms[0].type
|
||||
|
||||
# access second atom
|
||||
L.atoms[1].position
|
||||
L.atoms[1].velocity
|
||||
L.atoms[1].force
|
||||
|
||||
Some properties can also be used to set:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# set position in 2D simulation
|
||||
L.atoms[0].position = (1.0, 0.0)
|
||||
|
||||
# set position in 3D simulation
|
||||
L.atoms[0].position = (1.0, 0.0, 1.)
|
||||
|
||||
Evaluating thermo data
|
||||
----------------------
|
||||
|
||||
Each simulation run usually produces thermo output based on system state,
|
||||
computes, fixes or variables. The trajectories of these values can be queried
|
||||
after a run via the L.runs list. This list contains a growing list of run data.
|
||||
The first element is the output of the first run, the second element that of
|
||||
the second run.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.run(1000)
|
||||
L.runs[0] # data of first 1000 time steps
|
||||
|
||||
L.run(1000)
|
||||
L.runs[1] # data of second 1000 time steps
|
||||
|
||||
Each run contains a dictionary of all trajectories. Each trajectory is
|
||||
accessible through its thermo name:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.runs[0].thermo.Step # list of time steps in first run
|
||||
L.runs[0].thermo.Ke # list of kinetic energy values in first run
|
||||
|
||||
Together with matplotlib plotting data out of LAMMPS becomes simple:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import matplotlib.plot as plt
|
||||
steps = L.runs[0].thermo.Step
|
||||
ke = L.runs[0].thermo.Ke
|
||||
plt.plot(steps, ke)
|
||||
|
||||
Error handling with PyLammps
|
||||
----------------------------
|
||||
|
||||
Using C++ exceptions in LAMMPS for errors allows capturing them on the
|
||||
C++ side and rethrowing them on the Python side. This way you can handle
|
||||
LAMMPS errors through the Python exception handling mechanism.
|
||||
|
||||
.. warning::
|
||||
|
||||
Capturing a LAMMPS exception in Python can still mean that the
|
||||
current LAMMPS process is in an illegal state and must be
|
||||
terminated. It is advised to save your data and terminate the Python
|
||||
instance as quickly as possible.
|
||||
|
||||
Using PyLammps in IPython notebooks and Jupyter
|
||||
-----------------------------------------------
|
||||
|
||||
If the LAMMPS Python package is installed for the same Python interpreter as
|
||||
IPython, you can use PyLammps directly inside of an IPython notebook inside of
|
||||
Jupyter. Jupyter is a powerful integrated development environment (IDE) for
|
||||
many dynamic languages like Python, Julia and others, which operates inside of
|
||||
any web browser. Besides auto-completion and syntax highlighting it allows you
|
||||
to create formatted documents using Markup, mathematical formulas, graphics and
|
||||
animations intermixed with executable Python code. It is a great format for
|
||||
tutorials and showcasing your latest research.
|
||||
|
||||
To launch an instance of Jupyter simply run the following command inside your
|
||||
Python environment (this assumes you followed the Quick Start instructions):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
jupyter notebook
|
||||
|
||||
IPyLammps Examples
|
||||
------------------
|
||||
|
||||
Examples of IPython notebooks can be found in the python/examples/pylammps
|
||||
subdirectory. To open these notebooks launch *jupyter notebook* inside this
|
||||
directory and navigate to one of them. If you compiled and installed
|
||||
a LAMMPS shared library with exceptions, PNG, JPEG and FFMPEG support
|
||||
you should be able to rerun all of these notebooks.
|
||||
|
||||
Validating a dihedral potential
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This example showcases how an IPython Notebook can be used to compare a simple
|
||||
LAMMPS simulation of a harmonic dihedral potential to its analytical solution.
|
||||
Four atoms are placed in the simulation and the dihedral potential is applied on
|
||||
them using a datafile. Then one of the atoms is rotated along the central axis by
|
||||
setting its position from Python, which changes the dihedral angle.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
phi = [d \* math.pi / 180 for d in range(360)]
|
||||
|
||||
pos = [(1.0, math.cos(p), math.sin(p)) for p in phi]
|
||||
|
||||
pe = []
|
||||
for p in pos:
|
||||
L.atoms[3].position = p
|
||||
L.run(0)
|
||||
pe.append(L.eval("pe"))
|
||||
|
||||
By evaluating the potential energy for each position we can verify that
|
||||
trajectory with the analytical formula. To compare both solutions, we plot
|
||||
both trajectories over each other using matplotlib, which embeds the generated
|
||||
plot inside the IPython notebook.
|
||||
|
||||
.. image:: JPG/pylammps_dihedral.jpg
|
||||
:align: center
|
||||
|
||||
Running a Monte Carlo relaxation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This second example shows how to use PyLammps to create a 2D Monte Carlo Relaxation
|
||||
simulation, computing and plotting energy terms and even embedding video output.
|
||||
|
||||
Initially, a 2D system is created in a state with minimal energy.
|
||||
|
||||
.. image:: JPG/pylammps_mc_minimum.jpg
|
||||
:align: center
|
||||
|
||||
It is then disordered by moving each atom by a random delta.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
random.seed(27848)
|
||||
deltaperturb = 0.2
|
||||
|
||||
for i in range(L.system.natoms):
|
||||
x, y = L.atoms[i].position
|
||||
dx = deltaperturb \* random.uniform(-1, 1)
|
||||
dy = deltaperturb \* random.uniform(-1, 1)
|
||||
L.atoms[i].position = (x+dx, y+dy)
|
||||
|
||||
L.run(0)
|
||||
|
||||
.. image:: JPG/pylammps_mc_disordered.jpg
|
||||
:align: center
|
||||
|
||||
Finally, the Monte Carlo algorithm is implemented in Python. It continuously
|
||||
moves random atoms by a random delta and only accepts certain moves.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
estart = L.eval("pe")
|
||||
elast = estart
|
||||
|
||||
naccept = 0
|
||||
energies = [estart]
|
||||
|
||||
niterations = 3000
|
||||
deltamove = 0.1
|
||||
kT = 0.05
|
||||
|
||||
natoms = L.system.natoms
|
||||
|
||||
for i in range(niterations):
|
||||
iatom = random.randrange(0, natoms)
|
||||
current_atom = L.atoms[iatom]
|
||||
|
||||
x0, y0 = current_atom.position
|
||||
|
||||
dx = deltamove \* random.uniform(-1, 1)
|
||||
dy = deltamove \* random.uniform(-1, 1)
|
||||
|
||||
current_atom.position = (x0+dx, y0+dy)
|
||||
|
||||
L.run(1, "pre no post no")
|
||||
|
||||
e = L.eval("pe")
|
||||
energies.append(e)
|
||||
|
||||
if e <= elast:
|
||||
naccept += 1
|
||||
elast = e
|
||||
elif random.random() <= math.exp(natoms\*(elast-e)/kT):
|
||||
naccept += 1
|
||||
elast = e
|
||||
else:
|
||||
current_atom.position = (x0, y0)
|
||||
|
||||
The energies of each iteration are collected in a Python list and finally plotted using matplotlib.
|
||||
|
||||
.. image:: JPG/pylammps_mc_energies_plot.jpg
|
||||
:align: center
|
||||
|
||||
The IPython notebook also shows how to use dump commands and embed video files
|
||||
inside of the IPython notebook.
|
||||
|
||||
Using PyLammps and mpi4py (Experimental)
|
||||
----------------------------------------
|
||||
|
||||
PyLammps can be run in parallel using `mpi4py
|
||||
<https://mpi4py.readthedocs.io>`_. This python package can be installed
|
||||
using
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install mpi4py
|
||||
|
||||
.. warning::
|
||||
|
||||
Usually, any :py:class:`PyLammps <lammps.PyLammps>` command must be
|
||||
executed by *all* MPI processes. However, evaluations and querying
|
||||
the system state is only available on MPI rank 0. Using these
|
||||
functions from other MPI ranks will raise an exception.
|
||||
|
||||
The following is a short example which reads in an existing LAMMPS input
|
||||
file and executes it in parallel. You can find in.melt in the
|
||||
examples/melt folder. Please take note that the
|
||||
:py:meth:`PyLammps.eval() <lammps.PyLammps.eval>` is called only from
|
||||
MPI rank 0.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from mpi4py import MPI
|
||||
from lammps import PyLammps
|
||||
|
||||
L = PyLammps()
|
||||
L.file("in.melt")
|
||||
|
||||
if MPI.COMM_WORLD.rank == 0:
|
||||
print("Potential energy: ", L.eval("pe"))
|
||||
|
||||
MPI.Finalize()
|
||||
|
||||
To run this script (melt.py) in parallel using 4 MPI processes we invoke the
|
||||
following mpirun command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpirun -np 4 python melt.py
|
||||
|
||||
Feedback and Contributing
|
||||
-------------------------
|
||||
|
||||
If you find this Python interface useful, please feel free to provide feedback
|
||||
and ideas on how to improve it to Richard Berger (richard.berger@outlook.com). We also
|
||||
want to encourage people to write tutorial style IPython notebooks showcasing LAMMPS usage
|
||||
and maybe their latest research results.
|
||||
The PyLammps interface is deprecated and will be removed in a future release of
|
||||
LAMMPS. As such, the PyLammps version of this tutorial has been removed and is
|
||||
replaced by the :doc:`Python_head`.
|
||||
|
||||
441
doc/src/Howto_python.rst
Normal file
441
doc/src/Howto_python.rst
Normal file
@ -0,0 +1,441 @@
|
||||
LAMMPS Python Tutorial
|
||||
======================
|
||||
|
||||
.. contents::
|
||||
|
||||
-----
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The :py:class:`lammps <lammps.lammps>` Python module is a wrapper class for the
|
||||
LAMMPS :ref:`C language library interface API <lammps_c_api>` which is written using
|
||||
`Python ctypes <ctypes_>`_. The design choice of this wrapper class is to
|
||||
follow the C language API closely with only small changes related to Python
|
||||
specific requirements and to better accommodate object oriented programming.
|
||||
|
||||
In addition to this flat `ctypes <ctypes_>`_ interface, the
|
||||
:py:class:`lammps <lammps.lammps>` wrapper class exposes a discoverable
|
||||
API that doesn't require as much knowledge of the underlying C language
|
||||
library interface or LAMMPS C++ code implementation.
|
||||
|
||||
Finally, the API exposes some additional features for `IPython integration
|
||||
<ipython_>`_ into `Jupyter notebooks <jupyter_>`_, e.g. for embedded
|
||||
visualization output from :doc:`dump style image <dump_image>`.
|
||||
|
||||
.. _ctypes: https://docs.python.org/3/library/ctypes.html
|
||||
.. _ipython: https://ipython.org/
|
||||
.. _jupyter: https://jupyter.org/
|
||||
|
||||
-----
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
System-wide or User Installation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Step 1: Building LAMMPS as a shared library
|
||||
"""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
To use LAMMPS inside of Python it has to be compiled as shared library.
|
||||
This library is then loaded by the Python interface. In this example we
|
||||
enable the :ref:`MOLECULE package <PKG-MOLECULE>` and compile LAMMPS
|
||||
with :ref:`PNG, JPEG and FFMPEG output support <graphics>` enabled.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: CMake build
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir $LAMMPS_DIR/build-shared
|
||||
cd $LAMMPS_DIR/build-shared
|
||||
|
||||
# MPI, PNG, Jpeg, FFMPEG are auto-detected
|
||||
cmake ../cmake -DPKG_MOLECULE=yes -DPKG_PYTHON=on -DBUILD_SHARED_LIBS=yes
|
||||
make
|
||||
|
||||
.. tab:: Traditional make
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd $LAMMPS_DIR/src
|
||||
|
||||
# add packages if necessary
|
||||
make yes-MOLECULE
|
||||
make yes-PYTHON
|
||||
|
||||
# compile shared library using Makefile
|
||||
make mpi mode=shlib LMP_INC="-DLAMMPS_PNG -DLAMMPS_JPEG -DLAMMPS_FFMPEG" JPG_LIB="-lpng -ljpeg"
|
||||
|
||||
Step 2: Installing the LAMMPS Python package
|
||||
""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Next install the LAMMPS Python package into your current Python installation with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make install-python
|
||||
|
||||
This will create a so-called `"wheel"
|
||||
<https://packaging.python.org/en/latest/discussions/package-formats/#what-is-a-wheel>`_
|
||||
and then install the LAMMPS Python module from that "wheel" into either
|
||||
into a system folder (provided the command is executed with root
|
||||
privileges) or into your personal Python module folder.
|
||||
|
||||
.. note::
|
||||
|
||||
Recompiling the shared library requires re-installing the Python
|
||||
package.
|
||||
|
||||
Installation inside of a virtual environment
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can use virtual environments to create a custom Python environment
|
||||
specifically tuned for your workflow.
|
||||
|
||||
Benefits of using a virtualenv
|
||||
""""""""""""""""""""""""""""""
|
||||
|
||||
* isolation of your system Python installation from your development installation
|
||||
* installation can happen in your user directory without root access (useful for HPC clusters)
|
||||
* installing packages through pip allows you to get newer versions of packages than e.g., through apt-get or yum package managers (and without root access)
|
||||
* you can even install specific old versions of a package if necessary
|
||||
|
||||
**Prerequisite (e.g. on Ubuntu)**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
apt-get install python-venv
|
||||
|
||||
Creating a virtualenv with lammps installed
|
||||
"""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# create virtual envrionment named 'testing'
|
||||
python3 -m venv $HOME/python/testing
|
||||
|
||||
# activate 'testing' environment
|
||||
source $HOME/python/testing/bin/activate
|
||||
|
||||
Now configure and compile the LAMMPS shared library as outlined above.
|
||||
When using CMake and the shared library has already been build, you
|
||||
need to re-run CMake to update the location of the python executable
|
||||
to the location in the virtual environment with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake . -DPython_EXECUTABLE=$(which python)
|
||||
|
||||
# install LAMMPS package in virtualenv
|
||||
(testing) make install-python
|
||||
|
||||
# install other useful packages
|
||||
(testing) pip install matplotlib jupyter mpi4py pandas
|
||||
|
||||
...
|
||||
|
||||
# return to original shell
|
||||
(testing) deactivate
|
||||
|
||||
-------
|
||||
|
||||
Creating a new lammps instance
|
||||
------------------------------
|
||||
|
||||
To create a lammps object you need to first import the class from the lammps
|
||||
module. By using the default constructor, a new :py:class:`lammps
|
||||
<lammps.lammps>` instance is created.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import lammps
|
||||
L = lammps()
|
||||
|
||||
See the :doc:`LAMMPS Python documentation <Python_create>` for how to customize
|
||||
the instance creation with optional arguments.
|
||||
|
||||
-----
|
||||
|
||||
Commands
|
||||
--------
|
||||
|
||||
Sending a LAMMPS command with the library interface is done using
|
||||
the ``command`` method of the lammps object.
|
||||
|
||||
For instance, let's take the following LAMMPS command:
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
region box block 0 10 0 5 -0.5 0.5
|
||||
|
||||
This command can be executed with the following Python code if ``L`` is a ``lammps``
|
||||
instance:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.command("region box block 0 10 0 5 -0.5 0.5")
|
||||
|
||||
For convenience, the ``lammps`` class also provides a command wrapper ``cmd``
|
||||
that turns any LAMMPS command into a regular function call:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.cmd.region("box block", 0, 10, 0, 5, -0.5, 0.5)
|
||||
|
||||
Note that each parameter is set as Python number literal. With
|
||||
the wrapper each command takes an arbitrary parameter list and transparently
|
||||
merges it to a single command string, separating individual parameters by
|
||||
white-space.
|
||||
|
||||
The benefit of this approach is avoiding redundant command calls and easier
|
||||
parameterization. With the ``command`` function each call needs to be assembled
|
||||
manually using formatted strings.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.command(f"region box block {xlo} {xhi} {ylo} {yhi} {zlo} {zhi}")
|
||||
|
||||
The wrapper accepts parameters directly and will convert
|
||||
them automatically to a final command string.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.cmd.region("box block", xlo, xhi, ylo, yhi, zlo, zhi)
|
||||
|
||||
.. note::
|
||||
|
||||
When running in IPython you can use Tab-completion after ``L.cmd.`` to see
|
||||
all available LAMMPS commands.
|
||||
|
||||
-----
|
||||
|
||||
Accessing atom data
|
||||
-------------------
|
||||
|
||||
All per-atom properties that are part of the :doc:`atom style
|
||||
<atom_style>` in the current simulation can be accessed using the
|
||||
:py:meth:`extract_atoms() <lammps.lammps.extract_atoms()>` method. This
|
||||
can be retrieved as ctypes objects or as NumPy arrays through the
|
||||
lammps.numpy module. Those represent the *local* atoms of the
|
||||
individual sub-domain for the current MPI process and may contain
|
||||
information for the local ghost atoms or not depending on the property.
|
||||
Both can be accessed as lists, but for the ctypes list object the size
|
||||
is not known and hast to be retrieved first to avoid out-of-bounds
|
||||
accesses.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
nlocal = L.extract_setting("nlocal")
|
||||
nall = L.extract_setting("nall")
|
||||
print("Number of local atoms ", nlocal, " Number of local and ghost atoms ", nall);
|
||||
|
||||
# access via ctypes directly
|
||||
atom_id = L.extract_atom("id")
|
||||
print("Atom IDs", atom_id[0:nlocal])
|
||||
|
||||
# access through numpy wrapper
|
||||
atom_type = L.numpy.extract_atom("type")
|
||||
print("Atom types", atom_type)
|
||||
|
||||
x = L.numpy.extract_atom("x")
|
||||
v = L.numpy.extract_atom("v")
|
||||
print("positions array shape", x.shape)
|
||||
print("velocity array shape", v.shape)
|
||||
# turn on communicating velocities to ghost atoms
|
||||
L.cmd.comm_modify("vel", "yes")
|
||||
v = L.numpy.extract_atom('v')
|
||||
print("velocity array shape", v.shape)
|
||||
|
||||
Some properties can also be set from Python since internally the
|
||||
data of the C++ code is accessed directly:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# set position in 2D simulation
|
||||
x[0] = (1.0, 0.0)
|
||||
|
||||
# set position in 3D simulation
|
||||
x[0] = (1.0, 0.0, 1.)
|
||||
|
||||
------
|
||||
|
||||
Retrieving the values of thermodynamic data and variables
|
||||
---------------------------------------------------------
|
||||
|
||||
To access thermodynamic data from the last completed timestep,
|
||||
you can use the :py:meth:`get_thermo() <lammps.lammps.get_thermo>`
|
||||
method, and to extract the value of (compatible) variables, you
|
||||
can use the :py:meth:`extract_variable() <lammps.lammps.extract_variable>`
|
||||
method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
result = L.get_thermo("ke") # kinetic energy
|
||||
result = L.get_thermo("pe") # potential energy
|
||||
|
||||
result = L.extract_variable("t") / 2.0
|
||||
|
||||
Error handling
|
||||
--------------
|
||||
|
||||
We are using C++ exceptions in LAMMPS for errors and the C language
|
||||
library interface captures and records them. This allows checking
|
||||
whether errors have happened in Python during a call into LAMMPS and
|
||||
then re-throw the error as a Python exception. This way you can handle
|
||||
LAMMPS errors in the conventional way through the Python exception
|
||||
handling mechanism.
|
||||
|
||||
.. warning::
|
||||
|
||||
Capturing a LAMMPS exception in Python can still mean that the
|
||||
current LAMMPS process is in an illegal state and must be
|
||||
terminated. It is advised to save your data and terminate the Python
|
||||
instance as quickly as possible.
|
||||
|
||||
Using LAMMPS in IPython notebooks and Jupyter
|
||||
---------------------------------------------
|
||||
|
||||
If the LAMMPS Python package is installed for the same Python
|
||||
interpreter as IPython, you can use LAMMPS directly inside of an IPython
|
||||
notebook inside of Jupyter. Jupyter is a powerful integrated development
|
||||
environment (IDE) for many dynamic languages like Python, Julia and
|
||||
others, which operates inside of any web browser. Besides
|
||||
auto-completion and syntax highlighting it allows you to create
|
||||
formatted documents using Markup, mathematical formulas, graphics and
|
||||
animations intermixed with executable Python code. It is a great format
|
||||
for tutorials and showcasing your latest research.
|
||||
|
||||
To launch an instance of Jupyter simply run the following command inside your
|
||||
Python environment (this assumes you followed the Quick Start instructions):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
jupyter notebook
|
||||
|
||||
Interactive Python Examples
|
||||
---------------------------
|
||||
|
||||
Examples of IPython notebooks can be found in the ``python/examples/ipython``
|
||||
subdirectory. To open these notebooks launch ``jupyter notebook`` inside this
|
||||
directory and navigate to one of them. If you compiled and installed
|
||||
a LAMMPS shared library with PNG, JPEG and FFMPEG support
|
||||
you should be able to rerun all of these notebooks.
|
||||
|
||||
Validating a dihedral potential
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This example showcases how an IPython Notebook can be used to compare a simple
|
||||
LAMMPS simulation of a harmonic dihedral potential to its analytical solution.
|
||||
Four atoms are placed in the simulation and the dihedral potential is applied on
|
||||
them using a datafile. Then one of the atoms is rotated along the central axis by
|
||||
setting its position from Python, which changes the dihedral angle.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
phi = [d \* math.pi / 180 for d in range(360)]
|
||||
|
||||
pos = [(1.0, math.cos(p), math.sin(p)) for p in phi]
|
||||
|
||||
x = L.numpy.extract_atom("x")
|
||||
|
||||
pe = []
|
||||
for p in pos:
|
||||
x[3] = p
|
||||
L.cmd.run(0, "post", "no")
|
||||
pe.append(L.get_thermo("pe"))
|
||||
|
||||
By evaluating the potential energy for each position we can verify that
|
||||
trajectory with the analytical formula. To compare both solutions, we plot
|
||||
both trajectories over each other using matplotlib, which embeds the generated
|
||||
plot inside the IPython notebook.
|
||||
|
||||
.. image:: JPG/pylammps_dihedral.jpg
|
||||
:align: center
|
||||
|
||||
Running a Monte Carlo relaxation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This second example shows how to use the `lammps` Python interface to create a
|
||||
2D Monte Carlo Relaxation simulation, computing and plotting energy terms and
|
||||
even embedding video output.
|
||||
|
||||
Initially, a 2D system is created in a state with minimal energy.
|
||||
|
||||
.. image:: JPG/pylammps_mc_minimum.jpg
|
||||
:align: center
|
||||
|
||||
It is then disordered by moving each atom by a random delta.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
random.seed(27848)
|
||||
deltaperturb = 0.2
|
||||
x = L.numpy.extract_atom("x")
|
||||
natoms = x.shape[0]
|
||||
|
||||
for i in range(natoms):
|
||||
dx = deltaperturb \* random.uniform(-1, 1)
|
||||
dy = deltaperturb \* random.uniform(-1, 1)
|
||||
x[i][0] += dx
|
||||
x[i][1] += dy
|
||||
|
||||
L.cmd.run(0, "post", "no")
|
||||
|
||||
.. image:: JPG/pylammps_mc_disordered.jpg
|
||||
:align: center
|
||||
|
||||
Finally, the Monte Carlo algorithm is implemented in Python. It continuously
|
||||
moves random atoms by a random delta and only accepts certain moves.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
estart = L.get_thermo("pe")
|
||||
elast = estart
|
||||
|
||||
naccept = 0
|
||||
energies = [estart]
|
||||
|
||||
niterations = 3000
|
||||
deltamove = 0.1
|
||||
kT = 0.05
|
||||
|
||||
for i in range(niterations):
|
||||
x = L.numpy.extract_atom("x")
|
||||
natoms = x.shape[0]
|
||||
iatom = random.randrange(0, natoms)
|
||||
current_atom = x[iatom]
|
||||
|
||||
x0 = current_atom[0]
|
||||
y0 = current_atom[1]
|
||||
|
||||
dx = deltamove \* random.uniform(-1, 1)
|
||||
dy = deltamove \* random.uniform(-1, 1)
|
||||
|
||||
current_atom[0] = x0 + dx
|
||||
current_atom[1] = y0 + dy
|
||||
|
||||
L.cmd.run(1, "pre no post no")
|
||||
|
||||
e = L.get_thermo("pe")
|
||||
energies.append(e)
|
||||
|
||||
if e <= elast:
|
||||
naccept += 1
|
||||
elast = e
|
||||
elif random.random() <= math.exp(natoms\*(elast-e)/kT):
|
||||
naccept += 1
|
||||
elast = e
|
||||
else:
|
||||
current_atom[0] = x0
|
||||
current_atom[1] = y0
|
||||
|
||||
The energies of each iteration are collected in a Python list and finally plotted using matplotlib.
|
||||
|
||||
.. image:: JPG/pylammps_mc_energies_plot.jpg
|
||||
:align: center
|
||||
|
||||
The IPython notebook also shows how to use dump commands and embed video files
|
||||
inside of the IPython notebook.
|
||||
@ -131,16 +131,15 @@ run LAMMPS in serial mode.
|
||||
|
||||
.. _lammps_python_api:
|
||||
|
||||
LAMMPS Python APIs
|
||||
==================
|
||||
LAMMPS Python API
|
||||
=================
|
||||
|
||||
The LAMMPS Python module enables calling the LAMMPS C library API from
|
||||
Python by dynamically loading functions in the LAMMPS shared library through
|
||||
the `Python ctypes module <https://docs.python.org/3/library/ctypes.html>`_.
|
||||
Because of the dynamic loading, it is **required** that LAMMPS is compiled
|
||||
in :ref:`"shared" mode <exe>`. The Python interface is object-oriented, but
|
||||
otherwise tries to be very similar to the C library API. Three different
|
||||
Python classes to run LAMMPS are available and they build on each other.
|
||||
otherwise tries to be very similar to the C library API.
|
||||
More information on this is in the :doc:`Python_head`
|
||||
section of the manual. Use of the LAMMPS Python module is described in
|
||||
:doc:`Python_module`.
|
||||
|
||||
@ -208,20 +208,21 @@ Build system (strict)
|
||||
|
||||
LAMMPS currently supports two build systems: one that is based on
|
||||
:doc:`traditional Makefiles <Build_make>` and one that is based on
|
||||
:doc:`CMake <Build_cmake>`. Therefore, your contribution must be
|
||||
compatible with and support both build systems.
|
||||
:doc:`CMake <Build_cmake>`. As of fall 2024, it is no longer required
|
||||
to support the traditional make build system. New packages may choose
|
||||
to only support building with CMake. Additions to existing packages
|
||||
must follow the requirements set by that package.
|
||||
|
||||
For a single pair of header and implementation files that are an
|
||||
independent feature, it is usually only required to add them to
|
||||
``src/.gitignore``.
|
||||
|
||||
For traditional make, if your contributed files or package depend on
|
||||
other LAMMPS style files or packages also being installed
|
||||
(e.g. because your file is a derived class from the other LAMMPS
|
||||
class), then an ``Install.sh`` file is also needed to check for those
|
||||
dependencies and modifications to ``src/Depend.sh`` to trigger the checks.
|
||||
See other README and Install.sh files in other directories as
|
||||
examples.
|
||||
other LAMMPS style files or packages also being installed (e.g. because
|
||||
your file is a derived class from the other LAMMPS class), then an
|
||||
``Install.sh`` file is also needed to check for those dependencies and
|
||||
modifications to ``src/Depend.sh`` to trigger the checks. See other
|
||||
README and Install.sh files in other directories as examples.
|
||||
|
||||
Similarly, for CMake support, changes may need to be made to
|
||||
``cmake/CMakeLists.txt``, some of the files in ``cmake/presets``, and
|
||||
|
||||
@ -2,14 +2,8 @@ Per-atom properties
|
||||
===================
|
||||
|
||||
Similar to what is described in :doc:`Library_atoms`, the instances of
|
||||
:py:class:`lammps <lammps.lammps>`, :py:class:`PyLammps <lammps.PyLammps>`, or
|
||||
:py:class:`IPyLammps <lammps.IPyLammps>` can be used to extract atom quantities
|
||||
and modify some of them. The main difference between the interfaces is how the information
|
||||
is exposed.
|
||||
|
||||
While the :py:class:`lammps <lammps.lammps>` is just a thin layer that wraps C API calls,
|
||||
:py:class:`PyLammps <lammps.PyLammps>` and :py:class:`IPyLammps <lammps.IPyLammps>` expose
|
||||
information as objects and properties.
|
||||
:py:class:`lammps <lammps.lammps>` can be used to extract atom quantities
|
||||
and modify some of them.
|
||||
|
||||
In some cases the data returned is a direct reference to the original data
|
||||
inside LAMMPS cast to ``ctypes`` pointers. Where possible, the wrappers will
|
||||
@ -25,57 +19,41 @@ against invalid accesses.
|
||||
accordingly. These arrays can change sizes and order at every neighbor list
|
||||
rebuild and atom sort event as atoms are migrating between subdomains.
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: lammps API
|
||||
from lammps import lammps
|
||||
|
||||
.. code-block:: python
|
||||
lmp = lammps()
|
||||
lmp.file("in.sysinit")
|
||||
|
||||
from lammps import lammps
|
||||
|
||||
lmp = lammps()
|
||||
lmp.file("in.sysinit")
|
||||
# Read/Write access via ctypes
|
||||
nlocal = lmp.extract_global("nlocal")
|
||||
x = lmp.extract_atom("x")
|
||||
|
||||
nlocal = lmp.extract_global("nlocal")
|
||||
x = lmp.extract_atom("x")
|
||||
for i in range(nlocal):
|
||||
print("(x,y,z) = (", x[i][0], x[i][1], x[i][2], ")")
|
||||
|
||||
for i in range(nlocal):
|
||||
print("(x,y,z) = (", x[i][0], x[i][1], x[i][2], ")")
|
||||
# Read/Write access via NumPy arrays
|
||||
atom_id = L.numpy.extract_atom("id")
|
||||
atom_type = L.numpy.extract_atom("type")
|
||||
x = L.numpy.extract_atom("x")
|
||||
v = L.numpy.extract_atom("v")
|
||||
f = L.numpy.extract_atom("f")
|
||||
|
||||
lmp.close()
|
||||
# set position in 2D simulation
|
||||
x[0] = (1.0, 0.0)
|
||||
|
||||
**Methods**:
|
||||
# set position in 3D simulation
|
||||
x[0] = (1.0, 0.0, 1.)
|
||||
|
||||
* :py:meth:`extract_atom() <lammps.lammps.extract_atom()>`: extract a per-atom quantity
|
||||
lmp.close()
|
||||
|
||||
**Numpy Methods**:
|
||||
|
||||
* :py:meth:`numpy.extract_atom() <lammps.numpy_wrapper.numpy_wrapper.extract_atom()>`: extract a per-atom quantity as numpy array
|
||||
**Methods**:
|
||||
|
||||
.. tab:: PyLammps/IPyLammps API
|
||||
* :py:meth:`extract_atom() <lammps.lammps.extract_atom()>`: extract a per-atom quantity
|
||||
|
||||
All atoms in the current simulation can be accessed by using the :py:attr:`PyLammps.atoms <lammps.PyLammps.atoms>` property.
|
||||
Each element of this list is a :py:class:`Atom <lammps.Atom>` or :py:class:`Atom2D <lammps.Atom2D>` object. The attributes of
|
||||
these objects provide access to their data (id, type, position, velocity, force, etc.):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# access first atom
|
||||
L.atoms[0].id
|
||||
L.atoms[0].type
|
||||
|
||||
# access second atom
|
||||
L.atoms[1].position
|
||||
L.atoms[1].velocity
|
||||
L.atoms[1].force
|
||||
|
||||
Some attributes can be changed:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# set position in 2D simulation
|
||||
L.atoms[0].position = (1.0, 0.0)
|
||||
|
||||
# set position in 3D simulation
|
||||
L.atoms[0].position = (1.0, 0.0, 1.0)
|
||||
**Numpy Methods**:
|
||||
|
||||
* :py:meth:`numpy.extract_atom() <lammps.numpy_wrapper.numpy_wrapper.extract_atom()>`: extract a per-atom quantity as numpy array
|
||||
|
||||
@ -6,11 +6,10 @@ Creating or deleting a LAMMPS object
|
||||
====================================
|
||||
|
||||
With the Python interface the creation of a :cpp:class:`LAMMPS
|
||||
<LAMMPS_NS::LAMMPS>` instance is included in the constructors for the
|
||||
:py:class:`lammps <lammps.lammps>`, :py:class:`PyLammps <lammps.PyLammps>`,
|
||||
and :py:class:`IPyLammps <lammps.IPyLammps>` classes.
|
||||
Internally it will call either :cpp:func:`lammps_open` or :cpp:func:`lammps_open_no_mpi` from the C
|
||||
library API to create the class instance.
|
||||
<LAMMPS_NS::LAMMPS>` instance is included in the constructor for the
|
||||
:py:class:`lammps <lammps.lammps>` class. Internally it will call either
|
||||
:cpp:func:`lammps_open` or :cpp:func:`lammps_open_no_mpi` from the C library
|
||||
API to create the class instance.
|
||||
|
||||
All arguments are optional. The *name* argument allows loading a
|
||||
LAMMPS shared library that is named ``liblammps_machine.so`` instead of
|
||||
@ -26,108 +25,25 @@ to run the Python module like the library interface on a subset of the
|
||||
MPI ranks after splitting the communicator.
|
||||
|
||||
|
||||
Here are simple examples using all three Python interfaces:
|
||||
Here is a simple example using the LAMMPS Python interface:
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: lammps API
|
||||
from lammps import lammps
|
||||
|
||||
.. code-block:: python
|
||||
# NOTE: argv[0] is set by the lammps class constructor
|
||||
args = ["-log", "none"]
|
||||
|
||||
from lammps import lammps
|
||||
# create LAMMPS instance
|
||||
lmp = lammps(cmdargs=args)
|
||||
|
||||
# NOTE: argv[0] is set by the lammps class constructor
|
||||
args = ["-log", "none"]
|
||||
# get and print numerical version code
|
||||
print("LAMMPS Version: ", lmp.version())
|
||||
|
||||
# create LAMMPS instance
|
||||
lmp = lammps(cmdargs=args)
|
||||
# explicitly close and delete LAMMPS instance (optional)
|
||||
lmp.close()
|
||||
|
||||
# get and print numerical version code
|
||||
print("LAMMPS Version: ", lmp.version())
|
||||
|
||||
# explicitly close and delete LAMMPS instance (optional)
|
||||
lmp.close()
|
||||
|
||||
.. tab:: PyLammps API
|
||||
|
||||
The :py:class:`PyLammps <lammps.PyLammps>` class is a wrapper around the
|
||||
:py:class:`lammps <lammps.lammps>` class and all of its lower level functions.
|
||||
By default, it will create a new instance of :py:class:`lammps <lammps.lammps>` passing
|
||||
along all arguments to the constructor of :py:class:`lammps <lammps.lammps>`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import PyLammps
|
||||
|
||||
# NOTE: argv[0] is set by the lammps class constructor
|
||||
args = ["-log", "none"]
|
||||
|
||||
# create LAMMPS instance
|
||||
L = PyLammps(cmdargs=args)
|
||||
|
||||
# get and print numerical version code
|
||||
print("LAMMPS Version: ", L.version())
|
||||
|
||||
# explicitly close and delete LAMMPS instance (optional)
|
||||
L.close()
|
||||
|
||||
:py:class:`PyLammps <lammps.PyLammps>` objects can also be created on top of an existing
|
||||
:py:class:`lammps <lammps.lammps>` object:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import lammps, PyLammps
|
||||
...
|
||||
# create LAMMPS instance
|
||||
lmp = lammps(cmdargs=args)
|
||||
|
||||
# create PyLammps instance using previously created LAMMPS instance
|
||||
L = PyLammps(ptr=lmp)
|
||||
|
||||
This is useful if you have to create the :py:class:`lammps <lammps.lammps>`
|
||||
instance is a specific way, but want to take advantage of the
|
||||
:py:class:`PyLammps <lammps.PyLammps>` interface.
|
||||
|
||||
.. tab:: IPyLammps API
|
||||
|
||||
The :py:class:`IPyLammps <lammps.IPyLammps>` class is an extension of the
|
||||
:py:class:`PyLammps <lammps.PyLammps>` class. It has the same construction behavior. By
|
||||
default, it will create a new instance of :py:class:`lammps` passing
|
||||
along all arguments to the constructor of :py:class:`lammps`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import IPyLammps
|
||||
|
||||
# NOTE: argv[0] is set by the lammps class constructor
|
||||
args = ["-log", "none"]
|
||||
|
||||
# create LAMMPS instance
|
||||
L = IPyLammps(cmdargs=args)
|
||||
|
||||
# get and print numerical version code
|
||||
print("LAMMPS Version: ", L.version())
|
||||
|
||||
# explicitly close and delete LAMMPS instance (optional)
|
||||
L.close()
|
||||
|
||||
You can also initialize IPyLammps on top of an existing :py:class:`lammps` or :py:class:`PyLammps` object:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import lammps, IPyLammps
|
||||
...
|
||||
# create LAMMPS instance
|
||||
lmp = lammps(cmdargs=args)
|
||||
|
||||
# create PyLammps instance using previously created LAMMPS instance
|
||||
L = PyLammps(ptr=lmp)
|
||||
|
||||
This is useful if you have to create the :py:class:`lammps <lammps.lammps>`
|
||||
instance is a specific way, but want to take advantage of the
|
||||
:py:class:`IPyLammps <lammps.IPyLammps>` interface.
|
||||
|
||||
In all of the above cases, same as with the :ref:`C library API <lammps_c_api>`, this will use the
|
||||
Same as with the :ref:`C library API <lammps_c_api>`, this will use the
|
||||
``MPI_COMM_WORLD`` communicator for the MPI library that LAMMPS was
|
||||
compiled with.
|
||||
|
||||
|
||||
@ -1,127 +1,123 @@
|
||||
Executing commands
|
||||
==================
|
||||
|
||||
Once an instance of the :py:class:`lammps <lammps.lammps>`,
|
||||
:py:class:`PyLammps <lammps.PyLammps>`, or
|
||||
:py:class:`IPyLammps <lammps.IPyLammps>` class is created, there are
|
||||
Once an instance of the :py:class:`lammps <lammps.lammps>` class is created, there are
|
||||
multiple ways to "feed" it commands. In a way that is not very different from
|
||||
running a LAMMPS input script, except that Python has many more facilities
|
||||
for structured programming than the LAMMPS input script syntax. Furthermore
|
||||
it is possible to "compute" what the next LAMMPS command should be.
|
||||
|
||||
.. tabs::
|
||||
Same as in the equivalent :doc:`C library functions <Library_execute>`,
|
||||
commands can be read from a file, a single string, a list of strings and a
|
||||
block of commands in a single multi-line string. They are processed under the
|
||||
same boundary conditions as the C library counterparts. The example below
|
||||
demonstrates the use of :py:func:`lammps.file()`, :py:func:`lammps.command()`,
|
||||
:py:func:`lammps.commands_list()`, and :py:func:`lammps.commands_string()`:
|
||||
|
||||
.. tab:: lammps API
|
||||
.. code-block:: python
|
||||
|
||||
Same as in the equivalent
|
||||
:doc:`C library functions <Library_execute>`, commands can be read from a file, a
|
||||
single string, a list of strings and a block of commands in a single
|
||||
multi-line string. They are processed under the same boundary conditions
|
||||
as the C library counterparts. The example below demonstrates the use
|
||||
of :py:func:`lammps.file()`, :py:func:`lammps.command()`,
|
||||
:py:func:`lammps.commands_list()`, and :py:func:`lammps.commands_string()`:
|
||||
from lammps import lammps
|
||||
lmp = lammps()
|
||||
|
||||
.. code-block:: python
|
||||
# read commands from file 'in.melt'
|
||||
lmp.file('in.melt')
|
||||
|
||||
from lammps import lammps
|
||||
lmp = lammps()
|
||||
# issue a single command
|
||||
lmp.command('variable zpos index 1.0')
|
||||
|
||||
# read commands from file 'in.melt'
|
||||
lmp.file('in.melt')
|
||||
# create 10 groups with 10 atoms each
|
||||
cmds = [f"group g{i} id {10*i+1}:{10*(i+1)}" for i in range(10)]
|
||||
lmp.commands_list(cmds)
|
||||
|
||||
# issue a single command
|
||||
lmp.command('variable zpos index 1.0')
|
||||
# run commands from a multi-line string
|
||||
block = """
|
||||
clear
|
||||
region box block 0 2 0 2 0 2
|
||||
create_box 1 box
|
||||
create_atoms 1 single 1.0 1.0 ${zpos}
|
||||
"""
|
||||
lmp.commands_string(block)
|
||||
|
||||
# create 10 groups with 10 atoms each
|
||||
cmds = ["group g{} id {}:{}".format(i,10*i+1,10*(i+1)) for i in range(10)]
|
||||
lmp.commands_list(cmds)
|
||||
For convenience, the :py:class:`lammps <lammps.lammps>` class also provides a
|
||||
command wrapper ``cmd`` that turns any LAMMPS command into a regular function
|
||||
call.
|
||||
|
||||
# run commands from a multi-line string
|
||||
block = """
|
||||
clear
|
||||
region box block 0 2 0 2 0 2
|
||||
create_box 1 box
|
||||
create_atoms 1 single 1.0 1.0 ${zpos}
|
||||
"""
|
||||
lmp.commands_string(block)
|
||||
For instance, the following LAMMPS command
|
||||
|
||||
.. tab:: PyLammps/IPyLammps API
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
Unlike the lammps API, the PyLammps/IPyLammps APIs allow running LAMMPS
|
||||
commands by calling equivalent member functions of :py:class:`PyLammps <lammps.PyLammps>`
|
||||
and :py:class:`IPyLammps <lammps.IPyLammps>` instances.
|
||||
region box block 0 10 0 5 -0.5 0.5
|
||||
|
||||
For instance, the following LAMMPS command
|
||||
would normally be executed with the following Python code:
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
.. code-block:: python
|
||||
|
||||
region box block 0 10 0 5 -0.5 0.5
|
||||
from lammps import lammps
|
||||
|
||||
can be executed using with the lammps API with the following Python code if ``lmp`` is an
|
||||
instance of :py:class:`lammps <lammps.lammps>`:
|
||||
lmp = lammps()
|
||||
lmp.command("region box block 0 10 0 5 -0.5 0.5")
|
||||
|
||||
.. code-block:: python
|
||||
With the ``cmd`` wrapper, any LAMMPS command can be split up into arbitrary parts.
|
||||
These parts are then passed to a member function with the name of the :doc:`command <Commands_all>`.
|
||||
For the :doc:`region <region>` command that means the :code:`region()` method can be called.
|
||||
The arguments of the command can be passed as one string, or
|
||||
individually.
|
||||
|
||||
from lammps import lammps
|
||||
.. code-block:: python
|
||||
|
||||
lmp = lammps()
|
||||
lmp.command("region box block 0 10 0 5 -0.5 0.5")
|
||||
from lammps import lammps
|
||||
|
||||
With the PyLammps interface, any LAMMPS command can be split up into arbitrary parts.
|
||||
These parts are then passed to a member function with the name of the :doc:`command <Commands_all>`.
|
||||
For the :doc:`region <region>` command that means the :code:`region()` method can be called.
|
||||
The arguments of the command can be passed as one string, or
|
||||
individually.
|
||||
L = lammps()
|
||||
|
||||
.. code-block:: python
|
||||
# pass command parameters as one string
|
||||
L.cmd.region("box block 0 10 0 5 -0.5 0.5")
|
||||
|
||||
from lammps import PyLammps
|
||||
# OR pass them individually
|
||||
L.cmd.region("box block", 0, 10, 0, 5, -0.5, 0.5)
|
||||
|
||||
L = PyLammps()
|
||||
In the latter example, all parameters except the first are Python floating-point literals. The
|
||||
member function takes the entire parameter list and transparently merges it to a single command
|
||||
string.
|
||||
|
||||
# pass command parameters as one string
|
||||
L.region("box block 0 10 0 5 -0.5 0.5")
|
||||
The benefit of this approach is avoiding redundant command calls and easier
|
||||
parameterization. With `command`, `commands_list`, and `commands_string` the
|
||||
parameterization needed to be done manually by creating formatted command
|
||||
strings.
|
||||
|
||||
# OR pass them individually
|
||||
L.region("box block", 0, 10, 0, 5, -0.5, 0.5)
|
||||
.. code-block:: python
|
||||
|
||||
In the latter example, all parameters except the first are Python floating-point literals. The
|
||||
member function takes the entire parameter list and transparently merges it to a single command
|
||||
string.
|
||||
lmp.command("region box block %f %f %f %f %f %f" % (xlo, xhi, ylo, yhi, zlo, zhi))
|
||||
|
||||
The benefit of this approach is avoiding redundant command calls and easier
|
||||
parameterization. In the lammps API parameterization needed to be done
|
||||
manually by creating formatted command strings.
|
||||
In contrast, methods of the `cmd` wrapper accept parameters directly and will convert
|
||||
them automatically to a final command string.
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
lmp.command("region box block %f %f %f %f %f %f" % (xlo, xhi, ylo, yhi, zlo, zhi))
|
||||
L.cmd.region("box block", xlo, xhi, ylo, yhi, zlo, zhi)
|
||||
|
||||
In contrast, methods of PyLammps accept parameters directly and will convert
|
||||
them automatically to a final command string.
|
||||
.. note::
|
||||
|
||||
.. code-block:: python
|
||||
When running in IPython you can use Tab-completion after ``L.cmd.`` to see
|
||||
all available LAMMPS commands.
|
||||
|
||||
L.region("box block", xlo, xhi, ylo, yhi, zlo, zhi)
|
||||
Using these facilities, the previous example shown above can be rewritten as follows:
|
||||
|
||||
Using these facilities, the example shown for the lammps API can be rewritten as follows:
|
||||
.. code-block:: python
|
||||
|
||||
.. code-block:: python
|
||||
from lammps import lammps
|
||||
L = lammps()
|
||||
|
||||
from lammps import PyLammps
|
||||
L = PyLammps()
|
||||
# read commands from file 'in.melt'
|
||||
L.file('in.melt')
|
||||
|
||||
# read commands from file 'in.melt'
|
||||
L.file('in.melt')
|
||||
# issue a single command
|
||||
L.cmd.variable('zpos', 'index', 1.0)
|
||||
|
||||
# issue a single command
|
||||
L.variable('zpos', 'index', 1.0)
|
||||
# create 10 groups with 10 atoms each
|
||||
for i in range(10):
|
||||
L.cmd.group(f"g{i}", "id", f"{10*i+1}:{10*(i+1)}")
|
||||
|
||||
# create 10 groups with 10 atoms each
|
||||
for i in range(10):
|
||||
L.group(f"g{i}", "id", f"{10*i+1}:{10*(i+1)}")
|
||||
|
||||
L.clear()
|
||||
L.region("box block", 0, 2, 0, 2, 0, 2)
|
||||
L.create_box(1, "box")
|
||||
L.create_atoms(1, "single", 1.0, 1.0, "${zpos}")
|
||||
L.cmd.clear()
|
||||
L.cmd.region("box block", 0, 2, 0, 2, 0, 2)
|
||||
L.cmd.create_box(1, "box")
|
||||
L.cmd.create_atoms(1, "single", 1.0, 1.0, "${zpos}")
|
||||
|
||||
@ -15,6 +15,7 @@ together.
|
||||
Python_call
|
||||
Python_formats
|
||||
Python_examples
|
||||
Python_jupyter
|
||||
Python_error
|
||||
Python_trouble
|
||||
|
||||
|
||||
45
doc/src/Python_jupyter.rst
Normal file
45
doc/src/Python_jupyter.rst
Normal file
@ -0,0 +1,45 @@
|
||||
Using LAMMPS in IPython notebooks and Jupyter
|
||||
=============================================
|
||||
|
||||
If the LAMMPS Python package is installed for the same Python interpreter as
|
||||
`IPython <ipython>`_, you can use LAMMPS directly inside of an IPython notebook inside of
|
||||
Jupyter. `Jupyter <juypter>`_ is a powerful integrated development environment (IDE) for
|
||||
many dynamic languages like Python, Julia and others, which operates inside of
|
||||
any web browser. Besides auto-completion and syntax highlighting it allows you
|
||||
to create formatted documents using Markup, mathematical formulas, graphics and
|
||||
animations intermixed with executable Python code. It is a great format for
|
||||
tutorials and showcasing your latest research.
|
||||
|
||||
The easiest way to install it is via ``pip``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install --user jupyter
|
||||
|
||||
To launch an instance of Jupyter simply run the following command inside your
|
||||
Python environment:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
jupyter notebook
|
||||
|
||||
Interactive Python Examples
|
||||
---------------------------
|
||||
|
||||
Examples of IPython notebooks can be found in the ``python/examples/ipython``
|
||||
subdirectory. They require LAMMPS to be compiled as shared library with PYTHON,
|
||||
PNG, JPEG and FFMPEG support.
|
||||
|
||||
To open these notebooks launch ``jupyter notebook index.ipynb`` inside this
|
||||
directory. The opened file provides an overview of the available examples.
|
||||
|
||||
- Example 1: Using LAMMPS with Python (``simple.ipynb``)
|
||||
- Example 2: Analyzing LAMMPS thermodynamic data (``thermo.ipynb``)
|
||||
- Example 3: Working with Per-Atom Data (``atoms.ipynb``)
|
||||
- Example 4: Working with LAMMPS variables (``variables.ipynb``)
|
||||
- Example 5: Validating a dihedral potential (``dihedrals/dihedral.ipynb``)
|
||||
- Example 6: Running a Monte Carlo relaxation (``montecarlo/mc.ipynb``)
|
||||
|
||||
.. note::
|
||||
|
||||
Typically clicking a link in Jupyter will open a new tab, which might be blocked by your pop-up blocker.
|
||||
@ -10,19 +10,11 @@ be installed into a Python system folder or a user folder with ``make
|
||||
install-python``. Components of the module can then loaded into a Python
|
||||
session with the ``import`` command.
|
||||
|
||||
There are multiple Python interface classes in the :py:mod:`lammps` module:
|
||||
.. warning::
|
||||
|
||||
- the :py:class:`lammps <lammps.lammps>` class. This is a wrapper around
|
||||
the C-library interface and its member functions try to replicate the
|
||||
:ref:`C-library API <lammps_c_api>` closely. This is the most
|
||||
feature-complete Python API.
|
||||
- the :py:class:`PyLammps <lammps.PyLammps>` class. This is a more high-level
|
||||
and more Python style class implemented on top of the
|
||||
:py:class:`lammps <lammps.lammps>` class.
|
||||
- the :py:class:`IPyLammps <lammps.IPyLammps>` class is derived from
|
||||
:py:class:`PyLammps <lammps.PyLammps>` and adds embedded graphics
|
||||
features to conveniently include LAMMPS into `Jupyter
|
||||
<https://jupyter.org/>`_ notebooks.
|
||||
Alternative interfaces such as :py:class:`PyLammps <lammps.PyLammps>` and
|
||||
:py:class:`IPyLammps <lammps.IPyLammps>` classes have been deprecated and
|
||||
will be removed in a future version of LAMMPS.
|
||||
|
||||
.. _mpi4py_url: https://mpi4py.readthedocs.io
|
||||
|
||||
@ -49,7 +41,7 @@ The ``lammps`` class API
|
||||
========================
|
||||
|
||||
The :py:class:`lammps <lammps.lammps>` class is the core of the LAMMPS
|
||||
Python interfaces. It is a wrapper around the :ref:`LAMMPS C library
|
||||
Python interface. It is a wrapper around the :ref:`LAMMPS C library
|
||||
API <lammps_c_api>` using the `Python ctypes module
|
||||
<https://docs.python.org/3/library/ctypes.html>`_ and a shared library
|
||||
compiled from the LAMMPS sources code. The individual methods in this
|
||||
@ -64,40 +56,7 @@ functions. Below is a detailed documentation of the API.
|
||||
.. autoclass:: lammps.numpy_wrapper::numpy_wrapper
|
||||
:members:
|
||||
|
||||
----------
|
||||
|
||||
The ``PyLammps`` class API
|
||||
==========================
|
||||
|
||||
The :py:class:`PyLammps <lammps.PyLammps>` class is a wrapper that creates a
|
||||
simpler, more "Pythonic" interface to common LAMMPS functionality. LAMMPS
|
||||
data structures are exposed through objects and properties. This makes Python
|
||||
scripts shorter and more concise. See the :doc:`PyLammps Tutorial
|
||||
<Howto_pylammps>` for an introduction on how to use this interface.
|
||||
|
||||
.. autoclass:: lammps.PyLammps
|
||||
:members:
|
||||
|
||||
.. autoclass:: lammps.AtomList
|
||||
:members:
|
||||
|
||||
.. autoclass:: lammps.Atom
|
||||
:members:
|
||||
|
||||
.. autoclass:: lammps.Atom2D
|
||||
:members:
|
||||
|
||||
----------
|
||||
|
||||
The ``IPyLammps`` class API
|
||||
===========================
|
||||
|
||||
The :py:class:`IPyLammps <lammps.PyLammps>` class is an extension of
|
||||
:py:class:`PyLammps <lammps.PyLammps>`, adding additional functions to
|
||||
quickly display visualizations such as images and videos inside of IPython.
|
||||
See the :doc:`PyLammps Tutorial <Howto_pylammps>` for examples.
|
||||
|
||||
.. autoclass:: lammps.IPyLammps
|
||||
.. autoclass:: lammps.ipython::wrapper
|
||||
:members:
|
||||
|
||||
----------
|
||||
|
||||
@ -4,95 +4,52 @@ Compute, fixes, variables
|
||||
This section documents accessing or modifying data from objects like
|
||||
computes, fixes, or variables in LAMMPS using the :py:mod:`lammps` module.
|
||||
|
||||
.. tabs::
|
||||
For :py:meth:`lammps.extract_compute() <lammps.lammps.extract_compute()>` and
|
||||
:py:meth:`lammps.extract_fix() <lammps.lammps.extract_fix()>`, the global, per-atom,
|
||||
or local data calculated by the compute or fix can be accessed. What is returned
|
||||
depends on whether the compute or fix calculates a scalar or vector or array.
|
||||
For a scalar, a single double value is returned. If the compute or fix calculates
|
||||
a vector or array, a pointer to the internal LAMMPS data is returned, which you can
|
||||
use via normal Python subscripting.
|
||||
|
||||
.. tab:: lammps API
|
||||
The one exception is that for a fix that calculates a
|
||||
global vector or array, a single double value from the vector or array
|
||||
is returned, indexed by I (vector) or I and J (array). I,J are
|
||||
zero-based indices.
|
||||
See the :doc:`Howto output <Howto_output>` page for a discussion of
|
||||
global, per-atom, and local data, and of scalar, vector, and array
|
||||
data types. See the doc pages for individual :doc:`computes <compute>`
|
||||
and :doc:`fixes <fix>` for a description of what they calculate and
|
||||
store.
|
||||
|
||||
For :py:meth:`lammps.extract_compute() <lammps.lammps.extract_compute()>` and
|
||||
:py:meth:`lammps.extract_fix() <lammps.lammps.extract_fix()>`, the global, per-atom,
|
||||
or local data calculated by the compute or fix can be accessed. What is returned
|
||||
depends on whether the compute or fix calculates a scalar or vector or array.
|
||||
For a scalar, a single double value is returned. If the compute or fix calculates
|
||||
a vector or array, a pointer to the internal LAMMPS data is returned, which you can
|
||||
use via normal Python subscripting.
|
||||
For :py:meth:`lammps.extract_variable() <lammps.lammps.extract_variable()>`,
|
||||
an :doc:`equal-style or atom-style variable <variable>` is evaluated and
|
||||
its result returned.
|
||||
|
||||
The one exception is that for a fix that calculates a
|
||||
global vector or array, a single double value from the vector or array
|
||||
is returned, indexed by I (vector) or I and J (array). I,J are
|
||||
zero-based indices.
|
||||
See the :doc:`Howto output <Howto_output>` page for a discussion of
|
||||
global, per-atom, and local data, and of scalar, vector, and array
|
||||
data types. See the doc pages for individual :doc:`computes <compute>`
|
||||
and :doc:`fixes <fix>` for a description of what they calculate and
|
||||
store.
|
||||
For equal-style variables a single ``c_double`` value is returned and the
|
||||
group argument is ignored. For atom-style variables, a vector of
|
||||
``c_double`` is returned, one value per atom, which you can use via normal
|
||||
Python subscripting. The values will be zero for atoms not in the
|
||||
specified group.
|
||||
|
||||
For :py:meth:`lammps.extract_variable() <lammps.lammps.extract_variable()>`,
|
||||
an :doc:`equal-style or atom-style variable <variable>` is evaluated and
|
||||
its result returned.
|
||||
:py:meth:`lammps.numpy.extract_compute() <lammps.numpy_wrapper.numpy_wrapper.extract_compute()>`,
|
||||
:py:meth:`lammps.numpy.extract_fix() <lammps.numpy_wrapper.numpy_wrapper.extract_fix()>`, and
|
||||
:py:meth:`lammps.numpy.extract_variable() <lammps.numpy_wrapper.numpy_wrapper.extract_variable()>` are
|
||||
equivalent NumPy implementations that return NumPy arrays instead of ``ctypes`` pointers.
|
||||
|
||||
For equal-style variables a single ``c_double`` value is returned and the
|
||||
group argument is ignored. For atom-style variables, a vector of
|
||||
``c_double`` is returned, one value per atom, which you can use via normal
|
||||
Python subscripting. The values will be zero for atoms not in the
|
||||
specified group.
|
||||
The :py:meth:`lammps.set_variable() <lammps.lammps.set_variable()>` method sets an
|
||||
existing string-style variable to a new string value, so that subsequent LAMMPS
|
||||
commands can access the variable.
|
||||
|
||||
:py:meth:`lammps.numpy.extract_compute() <lammps.numpy_wrapper.numpy_wrapper.extract_compute()>`,
|
||||
:py:meth:`lammps.numpy.extract_fix() <lammps.numpy_wrapper.numpy_wrapper.extract_fix()>`, and
|
||||
:py:meth:`lammps.numpy.extract_variable() <lammps.numpy_wrapper.numpy_wrapper.extract_variable()>` are
|
||||
equivalent NumPy implementations that return NumPy arrays instead of ``ctypes`` pointers.
|
||||
**Methods**:
|
||||
|
||||
The :py:meth:`lammps.set_variable() <lammps.lammps.set_variable()>` method sets an
|
||||
existing string-style variable to a new string value, so that subsequent LAMMPS
|
||||
commands can access the variable.
|
||||
* :py:meth:`lammps.extract_compute() <lammps.lammps.extract_compute()>`: extract value(s) from a compute
|
||||
* :py:meth:`lammps.extract_fix() <lammps.lammps.extract_fix()>`: extract value(s) from a fix
|
||||
* :py:meth:`lammps.extract_variable() <lammps.lammps.extract_variable()>`: extract value(s) from a variable
|
||||
* :py:meth:`lammps.set_variable() <lammps.lammps.set_variable()>`: set existing named string-style variable to value
|
||||
|
||||
**Methods**:
|
||||
**NumPy Methods**:
|
||||
|
||||
* :py:meth:`lammps.extract_compute() <lammps.lammps.extract_compute()>`: extract value(s) from a compute
|
||||
* :py:meth:`lammps.extract_fix() <lammps.lammps.extract_fix()>`: extract value(s) from a fix
|
||||
* :py:meth:`lammps.extract_variable() <lammps.lammps.extract_variable()>`: extract value(s) from a variable
|
||||
* :py:meth:`lammps.set_variable() <lammps.lammps.set_variable()>`: set existing named string-style variable to value
|
||||
|
||||
**NumPy Methods**:
|
||||
|
||||
* :py:meth:`lammps.numpy.extract_compute() <lammps.numpy_wrapper.numpy_wrapper.extract_compute()>`: extract value(s) from a compute, return arrays as numpy arrays
|
||||
* :py:meth:`lammps.numpy.extract_fix() <lammps.numpy_wrapper.numpy_wrapper.extract_fix()>`: extract value(s) from a fix, return arrays as numpy arrays
|
||||
* :py:meth:`lammps.numpy.extract_variable() <lammps.numpy_wrapper.numpy_wrapper.extract_variable()>`: extract value(s) from a variable, return arrays as numpy arrays
|
||||
|
||||
|
||||
.. tab:: PyLammps/IPyLammps API
|
||||
|
||||
PyLammps and IPyLammps classes currently do not add any additional ways of
|
||||
retrieving information out of computes and fixes. This information can still be accessed by using the lammps API:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.lmp.extract_compute(...)
|
||||
L.lmp.extract_fix(...)
|
||||
# OR
|
||||
L.lmp.numpy.extract_compute(...)
|
||||
L.lmp.numpy.extract_fix(...)
|
||||
|
||||
LAMMPS variables can be both defined and accessed via the :py:class:`PyLammps <lammps.PyLammps>` interface.
|
||||
|
||||
To define a variable you can use the :doc:`variable <variable>` command:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
L.variable("a index 2")
|
||||
|
||||
A dictionary of all variables is returned by the :py:attr:`PyLammps.variables <lammps.PyLammps.variables>` property:
|
||||
|
||||
you can access an individual variable by retrieving a variable object from the
|
||||
``L.variables`` dictionary by name
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
a = L.variables['a']
|
||||
|
||||
The variable value can then be easily read and written by accessing the value
|
||||
property of this object.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
print(a.value)
|
||||
a.value = 4
|
||||
* :py:meth:`lammps.numpy.extract_compute() <lammps.numpy_wrapper.numpy_wrapper.extract_compute()>`: extract value(s) from a compute, return arrays as numpy arrays
|
||||
* :py:meth:`lammps.numpy.extract_fix() <lammps.numpy_wrapper.numpy_wrapper.extract_fix()>`: extract value(s) from a fix, return arrays as numpy arrays
|
||||
* :py:meth:`lammps.numpy.extract_variable() <lammps.numpy_wrapper.numpy_wrapper.extract_variable()>`: extract value(s) from a variable, return arrays as numpy arrays
|
||||
|
||||
@ -56,7 +56,7 @@ Below is an example output for Python version 3.8.5.
|
||||
|
||||
---------
|
||||
|
||||
LAMMPS can work together with Python in three ways. First, Python can
|
||||
LAMMPS can work together with Python in two ways. First, Python can
|
||||
wrap LAMMPS through the its :doc:`library interface <Library>`, so
|
||||
that a Python script can create one or more instances of LAMMPS and
|
||||
launch one or more simulations. In Python terms, this is referred to as
|
||||
@ -67,22 +67,7 @@ launch one or more simulations. In Python terms, this is referred to as
|
||||
|
||||
Launching LAMMPS via Python
|
||||
|
||||
|
||||
Second, the lower-level Python interface in the :py:class:`lammps Python
|
||||
class <lammps.lammps>` can be used indirectly through the provided
|
||||
:py:class:`PyLammps <lammps.PyLammps>` and :py:class:`IPyLammps
|
||||
<lammps.IPyLammps>` wrapper classes, also written in Python. These
|
||||
wrappers try to simplify the usage of LAMMPS in Python by providing a
|
||||
more object-based interface to common LAMMPS functionality. They also
|
||||
reduce the amount of code necessary to parameterize LAMMPS scripts
|
||||
through Python and make variables and computes directly accessible.
|
||||
|
||||
.. figure:: JPG/pylammps-invoke-lammps.png
|
||||
:figclass: align-center
|
||||
|
||||
Using the PyLammps / IPyLammps wrappers
|
||||
|
||||
Third, LAMMPS can use the Python interpreter, so that a LAMMPS input
|
||||
Second, LAMMPS can use the Python interpreter, so that a LAMMPS input
|
||||
script or styles can invoke Python code directly, and pass information
|
||||
back-and-forth between the input script and Python functions you write.
|
||||
This Python code can also call back to LAMMPS to query or change its
|
||||
|
||||
@ -2,14 +2,8 @@ System properties
|
||||
=================
|
||||
|
||||
Similar to what is described in :doc:`Library_properties`, the instances of
|
||||
:py:class:`lammps <lammps.lammps>`, :py:class:`PyLammps <lammps.PyLammps>`, or
|
||||
:py:class:`IPyLammps <lammps.IPyLammps>` can be used to extract different kinds
|
||||
of information about the active LAMMPS instance and also to modify some of it. The
|
||||
main difference between the interfaces is how the information is exposed.
|
||||
|
||||
While the :py:class:`lammps <lammps.lammps>` is just a thin layer that wraps C API calls,
|
||||
:py:class:`PyLammps <lammps.PyLammps>` and :py:class:`IPyLammps <lammps.IPyLammps>` expose
|
||||
information as objects and properties.
|
||||
:py:class:`lammps <lammps.lammps>` can be used to extract different kinds
|
||||
of information about the active LAMMPS instance and also to modify some of it.
|
||||
|
||||
In some cases the data returned is a direct reference to the original data
|
||||
inside LAMMPS cast to ``ctypes`` pointers. Where possible, the wrappers will
|
||||
@ -25,113 +19,38 @@ against invalid accesses.
|
||||
accordingly. These arrays can change sizes and order at every neighbor list
|
||||
rebuild and atom sort event as atoms are migrating between subdomains.
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: lammps API
|
||||
from lammps import lammps
|
||||
|
||||
.. code-block:: python
|
||||
lmp = lammps()
|
||||
lmp.file("in.sysinit")
|
||||
|
||||
from lammps import lammps
|
||||
natoms = lmp.get_natoms()
|
||||
print(f"running simulation with {natoms} atoms")
|
||||
|
||||
lmp = lammps()
|
||||
lmp.file("in.sysinit")
|
||||
lmp.command("run 1000 post no");
|
||||
|
||||
natoms = lmp.get_natoms()
|
||||
print(f"running simulation with {natoms} atoms")
|
||||
for i in range(10):
|
||||
lmp.command("run 100 pre no post no")
|
||||
pe = lmp.get_thermo("pe")
|
||||
ke = lmp.get_thermo("ke")
|
||||
print(f"PE = {pe}\nKE = {ke}")
|
||||
|
||||
lmp.command("run 1000 post no");
|
||||
lmp.close()
|
||||
|
||||
for i in range(10):
|
||||
lmp.command("run 100 pre no post no")
|
||||
pe = lmp.get_thermo("pe")
|
||||
ke = lmp.get_thermo("ke")
|
||||
print(f"PE = {pe}\nKE = {ke}")
|
||||
**Methods**:
|
||||
|
||||
lmp.close()
|
||||
* :py:meth:`version() <lammps.lammps.version()>`: return the numerical version id, e.g. LAMMPS 2 Sep 2015 -> 20150902
|
||||
* :py:meth:`get_thermo() <lammps.lammps.get_thermo()>`: return current value of a thermo keyword
|
||||
* :py:meth:`last_thermo() <lammps.lammps.last_thermo()>`: return a dictionary of the last thermodynamic output
|
||||
* :py:meth:`get_natoms() <lammps.lammps.get_natoms()>`: total # of atoms as int
|
||||
* :py:meth:`reset_box() <lammps.lammps.reset_box()>`: reset the simulation box size
|
||||
* :py:meth:`extract_setting() <lammps.lammps.extract_setting()>`: return a global setting
|
||||
* :py:meth:`extract_global() <lammps.lammps.extract_global()>`: extract a global quantity
|
||||
* :py:meth:`extract_box() <lammps.lammps.extract_box()>`: extract box info
|
||||
* :py:meth:`create_atoms() <lammps.lammps.create_atoms()>`: create N atoms with IDs, types, x, v, and image flags
|
||||
|
||||
**Methods**:
|
||||
**Properties**:
|
||||
|
||||
* :py:meth:`version() <lammps.lammps.version()>`: return the numerical version id, e.g. LAMMPS 2 Sep 2015 -> 20150902
|
||||
* :py:meth:`get_thermo() <lammps.lammps.get_thermo()>`: return current value of a thermo keyword
|
||||
* :py:meth:`last_thermo() <lammps.lammps.last_thermo()>`: return a dictionary of the last thermodynamic output
|
||||
* :py:meth:`get_natoms() <lammps.lammps.get_natoms()>`: total # of atoms as int
|
||||
* :py:meth:`reset_box() <lammps.lammps.reset_box()>`: reset the simulation box size
|
||||
* :py:meth:`extract_setting() <lammps.lammps.extract_setting()>`: return a global setting
|
||||
* :py:meth:`extract_global() <lammps.lammps.extract_global()>`: extract a global quantity
|
||||
* :py:meth:`extract_box() <lammps.lammps.extract_box()>`: extract box info
|
||||
* :py:meth:`create_atoms() <lammps.lammps.create_atoms()>`: create N atoms with IDs, types, x, v, and image flags
|
||||
|
||||
**Properties**:
|
||||
|
||||
* :py:attr:`last_thermo_step <lammps.lammps.last_thermo_step>`: the last timestep thermodynamic output was computed
|
||||
|
||||
.. tab:: PyLammps/IPyLammps API
|
||||
|
||||
In addition to the functions provided by :py:class:`lammps <lammps.lammps>`, :py:class:`PyLammps <lammps.PyLammps>` objects
|
||||
have several properties which allow you to query the system state:
|
||||
|
||||
L.system
|
||||
Is a dictionary describing the system such as the bounding box or number of atoms
|
||||
|
||||
L.system.xlo, L.system.xhi
|
||||
bounding box limits along x-axis
|
||||
|
||||
L.system.ylo, L.system.yhi
|
||||
bounding box limits along y-axis
|
||||
|
||||
L.system.zlo, L.system.zhi
|
||||
bounding box limits along z-axis
|
||||
|
||||
L.communication
|
||||
configuration of communication subsystem, such as the number of threads or processors
|
||||
|
||||
L.communication.nthreads
|
||||
number of threads used by each LAMMPS process
|
||||
|
||||
L.communication.nprocs
|
||||
number of MPI processes used by LAMMPS
|
||||
|
||||
L.fixes
|
||||
List of fixes in the current system
|
||||
|
||||
L.computes
|
||||
List of active computes in the current system
|
||||
|
||||
L.dump
|
||||
List of active dumps in the current system
|
||||
|
||||
L.groups
|
||||
List of groups present in the current system
|
||||
|
||||
**Retrieving the value of an arbitrary LAMMPS expressions**
|
||||
|
||||
LAMMPS expressions can be immediately evaluated by using the ``eval`` method. The
|
||||
passed string parameter can be any expression containing global :doc:`thermo` values,
|
||||
variables, compute or fix data (see :doc:`Howto_output`):
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
result = L.eval("ke") # kinetic energy
|
||||
result = L.eval("pe") # potential energy
|
||||
|
||||
result = L.eval("v_t/2.0")
|
||||
|
||||
**Example**
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import PyLammps
|
||||
|
||||
L = PyLammps()
|
||||
L.file("in.sysinit")
|
||||
|
||||
print(f"running simulation with {L.system.natoms} atoms")
|
||||
|
||||
L.run(1000, "post no");
|
||||
|
||||
for i in range(10):
|
||||
L.run(100, "pre no post no")
|
||||
pe = L.eval("pe")
|
||||
ke = L.eval("ke")
|
||||
print(f"PE = {pe}\nKE = {ke}")
|
||||
* :py:attr:`last_thermo_step <lammps.lammps.last_thermo_step>`: the last timestep thermodynamic output was computed
|
||||
|
||||
94
doc/src/angle_mwlc.rst
Normal file
94
doc/src/angle_mwlc.rst
Normal file
@ -0,0 +1,94 @@
|
||||
.. index:: angle_style mwlc
|
||||
|
||||
angle_style mwlc command
|
||||
==========================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
angle_style mwlc
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
angle_style mwlc
|
||||
angle_coeff * 25 1 10 1
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
The *mwlc* angle style models a meltable wormlike chain and can be used
|
||||
to model non-linear bending elasticity of polymers, e.g. DNA. *mwlc*
|
||||
uses a potential that is a canonical-ensemble superposition of a
|
||||
non-melted and a melted state :ref:`(Farrell) <Farrell>`. The potential
|
||||
is
|
||||
|
||||
.. math::
|
||||
|
||||
E = -k_{B}T\,\log [q + q^{m}] + E_{0},
|
||||
|
||||
where the non-melted and melted partition functions are
|
||||
|
||||
.. math::
|
||||
q = \exp [-k_{1}(1+\cos{\theta})/k_{B}T]; \\
|
||||
q^{m} = \exp [-(\mu+k_{2}(1+\cos{\theta}))/k_{B}T].
|
||||
|
||||
:math:`k_1` is the bending elastic constant of the non-melted state,
|
||||
:math:`k_2` is the bending elastic constant of the melted state,
|
||||
:math:`\mu` is the melting energy, and
|
||||
:math:`T` is the reference temperature.
|
||||
The reference energy,
|
||||
|
||||
.. math::
|
||||
E_{0} = -k_{B}T\,\log [1 + \exp[-\mu/k_{B}T]],
|
||||
|
||||
ensures that E is zero for a fully extended chain.
|
||||
|
||||
This potential is a continuous version of the two-state potential
|
||||
introduced by :ref:`(Yan) <Yan>`.
|
||||
|
||||
The following coefficients must be defined for each angle type via the
|
||||
:doc:`angle_coeff <angle_coeff>` command as in the example above, or in
|
||||
the data file or restart files read by the :doc:`read_data <read_data>`
|
||||
or :doc:`read_restart <read_restart>` commands:
|
||||
|
||||
* :math:`k_1` (energy)
|
||||
* :math:`k_2` (energy)
|
||||
* :math:`\mu` (energy)
|
||||
* :math:`T` (temperature)
|
||||
|
||||
----------
|
||||
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
|
||||
This angle style can only be used if LAMMPS was built with the
|
||||
EXTRA-MOLECULE package. See the :doc:`Build package <Build_package>`
|
||||
doc page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`angle_coeff <angle_coeff>`
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
none
|
||||
|
||||
----------
|
||||
|
||||
.. _Farrell:
|
||||
|
||||
**(Farrell)** `Farrell, Dobnikar, Podgornik, Curk, Phys Rev Lett, 133, 148101 (2024). <https://doi.org/10.1103/PhysRevLett.133.148101>`_
|
||||
|
||||
.. _Yan:
|
||||
|
||||
**(Yan)** `Yan, Marko, Phys Rev Lett, 93, 108108 (2004). <https://doi.org/10.1103/PhysRevLett.93.108108>`_
|
||||
@ -94,6 +94,7 @@ of (g,i,k,o,t) to indicate which accelerated styles exist.
|
||||
* :doc:`lepton <angle_lepton>` - angle potential from evaluating a string
|
||||
* :doc:`mesocnt <angle_mesocnt>` - piecewise harmonic and linear angle for bending-buckling of nanotubes
|
||||
* :doc:`mm3 <angle_mm3>` - anharmonic angle
|
||||
* :doc:`mwlc <angle_mwlc>` - meltable wormlike chain
|
||||
* :doc:`quartic <angle_quartic>` - angle with cubic and quartic terms
|
||||
* :doc:`spica <angle_spica>` - harmonic angle with repulsive SPICA pair style between 1-3 atoms
|
||||
* :doc:`table <angle_table>` - tabulated by angle
|
||||
|
||||
@ -406,6 +406,8 @@ sub-style name. The angle styles that currently work with fix adapt are:
|
||||
+--------------------------------------------------------------------+--------------------+-------------+
|
||||
| :doc:`mm3 <angle_mm3>` | k,theta0 | type angles |
|
||||
+--------------------------------------------------------------------+--------------------+-------------+
|
||||
| :doc:`mwlc <angle_mwlc>` | k1,k2,mu,T | type angles |
|
||||
+--------------------------------------------------------------------+--------------------+-------------+
|
||||
| :doc:`quartic <angle_quartic>` | k2,k3,k4,theta0 | type angles |
|
||||
+--------------------------------------------------------------------+--------------------+-------------+
|
||||
| :doc:`spica <angle_spica>` | k,theta0 | type angles |
|
||||
|
||||
@ -71,9 +71,9 @@ Syntax
|
||||
feature functions = is_available(category,feature), is_active(category,feature), is_defined(category,id)
|
||||
atom value = id[i], mass[i], type[i], mol[i], x[i], y[i], z[i], vx[i], vy[i], vz[i], fx[i], fy[i], fz[i], q[i]
|
||||
atom vector = id, mass, type, mol, radius, q, x, y, z, vx, vy, vz, fx, fy, fz
|
||||
custom atom property = i_name, d_name, i_name[i], d_name[i], i2_name[i], d2_name[i], i2_name[i][j], d_name[i][j]
|
||||
compute references = c_ID, c_ID[i], c_ID[i][j], C_ID, C_ID[i]
|
||||
fix references = f_ID, f_ID[i], f_ID[i][j], F_ID, F_ID[i]
|
||||
custom atom property = i_name, d_name, i_name[i], d_name[i], i2_name[i], d2_name[i], i2_name[i][j], d2_name[i][j]
|
||||
compute references = c_ID, c_ID[i], c_ID[i][j], C_ID, C_ID[i], C_ID[i][j]
|
||||
fix references = f_ID, f_ID[i], f_ID[i][j], F_ID, F_ID[i], F_ID[i][j]
|
||||
variable references = v_name, v_name[i]
|
||||
vector initialization = [1,3,7,10] (for *vector* variables only)
|
||||
|
||||
|
||||
@ -9,3 +9,4 @@ Pygments
|
||||
six
|
||||
pyyaml
|
||||
linkchecker
|
||||
ipython
|
||||
|
||||
@ -2116,6 +2116,7 @@ Marchi
|
||||
Mariella
|
||||
Marinica
|
||||
Markland
|
||||
Marko
|
||||
Marrink
|
||||
Marroquin
|
||||
Marsaglia
|
||||
@ -2198,6 +2199,7 @@ Meissner
|
||||
Melchor
|
||||
Meloni
|
||||
Melrose
|
||||
meltable
|
||||
mem
|
||||
Mem
|
||||
memalign
|
||||
@ -2408,6 +2410,7 @@ mV
|
||||
Mvapich
|
||||
mvh
|
||||
mvv
|
||||
mwlc
|
||||
MxN
|
||||
myCompute
|
||||
myIndex
|
||||
@ -2929,6 +2932,7 @@ Pmoltrans
|
||||
pN
|
||||
png
|
||||
podd
|
||||
Podgornik
|
||||
Podhorszki
|
||||
Poiseuille
|
||||
poisson
|
||||
@ -4113,6 +4117,7 @@ workflow
|
||||
workflows
|
||||
Workum
|
||||
Worley
|
||||
wormlike
|
||||
Wriggers
|
||||
writedata
|
||||
Wuppertal
|
||||
@ -4181,6 +4186,7 @@ yaff
|
||||
YAFF
|
||||
Yamada
|
||||
yaml
|
||||
Yan
|
||||
Yanxon
|
||||
Yaser
|
||||
Yazdani
|
||||
|
||||
@ -18,11 +18,11 @@ from install_helpers import fullpath, geturl, checkmd5sum, getfallback
|
||||
# settings
|
||||
|
||||
thisdir = fullpath('.')
|
||||
version ='v.2023.11.25.fix'
|
||||
version ='v.2023.11.25.fix2'
|
||||
|
||||
# known checksums for different PACE versions. used to validate the download.
|
||||
checksums = { \
|
||||
'v.2023.11.25.fix': 'b45de9a633f42ed65422567e3ce56f9f'
|
||||
'v.2023.11.25.fix2': 'a53bd87cfee8b07d9f44bc17aad69c3f'
|
||||
}
|
||||
|
||||
parser = ArgumentParser(prog='Install.py', description="LAMMPS library build wrapper script")
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
# PyLammps and Jupyter Notebooks
|
||||
# IPython and Jupyter Notebooks
|
||||
|
||||
This folder contains examples showcasing the usage of the PyLammps Python
|
||||
This folder contains examples showcasing the usage of the LAMMPS Python
|
||||
interface and Jupyter notebooks. To use this you will need LAMMPS compiled as
|
||||
a shared library and the LAMMPS Python package installed.
|
||||
|
||||
An extensive guide on how to achieve this is documented in the [LAMMPS manual](https://docs.lammps.org/Python_install.html). There is also a [PyLammps tutorial](https://docs.lammps.org/Howto_pylammps.html).
|
||||
An extensive guide on how to achieve this is documented in the [LAMMPS manual](https://docs.lammps.org/Python_install.html). There is also a [LAMMPS Python tutorial](https://docs.lammps.org/Howto_python.html).
|
||||
|
||||
The following will show one way of creating a Python virtual environment
|
||||
which has both LAMMPS and its Python package installed:
|
||||
@ -53,7 +53,7 @@ which has both LAMMPS and its Python package installed:
|
||||
```shell
|
||||
(myenv)$ cmake -C ../cmake/presets/basic.cmake \
|
||||
-D BUILD_SHARED_LIBS=on \
|
||||
-D LAMMPS_EXCEPTIONS=on -D PKG_PYTHON=on \
|
||||
-D PKG_PYTHON=on \
|
||||
-D CMAKE_INSTALL_PREFIX=$VIRTUAL_ENV \
|
||||
../cmake
|
||||
```
|
||||
@ -67,19 +67,19 @@ which has both LAMMPS and its Python package installed:
|
||||
8. Install LAMMPS and Python package into virtual environment
|
||||
|
||||
```shell
|
||||
(myenv)$ cmake --install .
|
||||
(myenv)$ make install-python
|
||||
```
|
||||
|
||||
9. Install other Python packages into virtual environment
|
||||
|
||||
```shell
|
||||
(myenv)$ pip install jupyter matplotlib mpi4py
|
||||
(myenv)$ pip install jupyter matplotlib pandas mpi4py
|
||||
```
|
||||
|
||||
10. Navigate to pylammps examples folder
|
||||
10. Navigate to ipython examples folder
|
||||
|
||||
```shell
|
||||
(myenv)$ cd ../python/examples/pylammmps
|
||||
(myenv)$ cd ../python/examples/ipython
|
||||
```
|
||||
|
||||
11. Launch Jupyter and work inside browser
|
||||
224
python/examples/ipython/atoms.ipynb
Normal file
224
python/examples/ipython/atoms.ipynb
Normal file
@ -0,0 +1,224 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div style=\"text-align: center\"><a href=\"index.ipynb\">LAMMPS Python Tutorials</a></div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Example 3: Working with Per-Atom Data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Author: [Richard Berger](mailto:richard.berger@outlook.com)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"2D circle of particles inside of box with LJ walls"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Setup system"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from lammps import lammps"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L = lammps()\n",
|
||||
"cmd = L.cmd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 2d circle of particles inside a box with LJ walls\n",
|
||||
"import math\n",
|
||||
"\n",
|
||||
"b = 0\n",
|
||||
"x = 50\n",
|
||||
"y = 20\n",
|
||||
"d = 20\n",
|
||||
"\n",
|
||||
"# careful not to slam into wall too hard\n",
|
||||
"\n",
|
||||
"v = 0.3\n",
|
||||
"w = 0.08\n",
|
||||
" \n",
|
||||
"cmd.units(\"lj\")\n",
|
||||
"cmd.dimension(2)\n",
|
||||
"cmd.atom_style(\"bond\")\n",
|
||||
"cmd.boundary(\"f f p\")\n",
|
||||
"\n",
|
||||
"cmd.lattice(\"hex\", 0.85)\n",
|
||||
"cmd.region(\"box\", \"block\", 0, x, 0, y, -0.5, 0.5)\n",
|
||||
"cmd.create_box(1, \"box\", \"bond/types\", 1, \"extra/bond/per/atom\", 6)\n",
|
||||
"cmd.region(\"circle\", \"sphere\", d/2.0+1.0, d/2.0/math.sqrt(3.0)+1, 0.0, d/2.0)\n",
|
||||
"cmd.create_atoms(1, \"region\", \"circle\")\n",
|
||||
"cmd.mass(1, 1.0)\n",
|
||||
"\n",
|
||||
"cmd.velocity(\"all create 0.5 87287 loop geom\")\n",
|
||||
"cmd.velocity(\"all set\", v, w, 0, \"sum yes\")\n",
|
||||
"\n",
|
||||
"cmd.pair_style(\"lj/cut\", 2.5)\n",
|
||||
"cmd.pair_coeff(1, 1, 10.0, 1.0, 2.5)\n",
|
||||
"\n",
|
||||
"cmd.bond_style(\"harmonic\")\n",
|
||||
"cmd.bond_coeff(1, 10.0, 1.2)\n",
|
||||
"\n",
|
||||
"cmd.create_bonds(\"many\", \"all\", \"all\", 1, 1.0, 1.5)\n",
|
||||
"\n",
|
||||
"cmd.neighbor(0.3, \"bin\")\n",
|
||||
"cmd.neigh_modify(\"delay\", 0, \"every\", 1, \"check yes\")\n",
|
||||
"\n",
|
||||
"cmd.fix(1, \"all\", \"nve\")\n",
|
||||
"\n",
|
||||
"cmd.fix(2, \"all wall/lj93 xlo 0.0 1 1 2.5 xhi\", x, \"1 1 2.5\")\n",
|
||||
"cmd.fix(3, \"all wall/lj93 ylo 0.0 1 1 2.5 yhi\", y, \"1 1 2.5\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Visualize initial state"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.ipython.image(zoom=1.8)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Run simulation and visualize new state"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"cmd.thermo_style(\"custom step temp epair press\")\n",
|
||||
"cmd.thermo(100)\n",
|
||||
"output = cmd.run(40000)\n",
|
||||
"L.ipython.image(zoom=1.8)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Accessing Atom data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.numpy.extract_atom(\"x\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.numpy.extract_atom(\"id\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.numpy.extract_atom(\"v\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.numpy.extract_atom(\"f\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.numpy.extract_atom(\"type\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.7"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@ -4,7 +4,14 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Validating a dihedral potential"
|
||||
"<div style=\"text-align: center\"><a href=\"../index.ipynb\">LAMMPS Python Tutorials</a></div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Example 4: Validating a dihedral potential"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -13,7 +20,8 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib notebook"
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"from lammps import lammps"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -22,25 +30,8 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from lammps import IPyLammps"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L = IPyLammps()"
|
||||
"L = lammps()\n",
|
||||
"cmd = L.cmd"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -51,13 +42,13 @@
|
||||
"source": [
|
||||
"import math\n",
|
||||
"\n",
|
||||
"L.units(\"real\")\n",
|
||||
"L.atom_style(\"molecular\")\n",
|
||||
"cmd.units(\"real\")\n",
|
||||
"cmd.atom_style(\"molecular\")\n",
|
||||
"\n",
|
||||
"L.boundary(\"f f f\")\n",
|
||||
"L.neighbor(0.3, \"bin\")\n",
|
||||
"cmd.boundary(\"f f f\")\n",
|
||||
"cmd.neighbor(0.3, \"bin\")\n",
|
||||
"\n",
|
||||
"L.dihedral_style(\"harmonic\")"
|
||||
"cmd.dihedral_style(\"harmonic\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -66,7 +57,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.read_data(\"data.dihedral\")"
|
||||
"cmd.read_data(\"data.dihedral\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -75,8 +66,8 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.pair_style(\"zero\", 5)\n",
|
||||
"L.pair_coeff(\"*\", \"*\")"
|
||||
"cmd.pair_style(\"zero\", 5)\n",
|
||||
"cmd.pair_coeff(\"*\", \"*\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -85,7 +76,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.mass(1, 1.0)"
|
||||
"cmd.mass(1, 1.0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -94,7 +85,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.velocity(\"all\", \"set\", 0.0, 0.0, 0.0)"
|
||||
"cmd.velocity(\"all\", \"set\", 0.0, 0.0, 0.0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -103,7 +94,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.run(0);"
|
||||
"cmd.run(0, \"post\", \"no\");"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -112,7 +103,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1.0)"
|
||||
"L.ipython.image(zoom=1.0,size=[320,320])"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -121,7 +112,8 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[3].position"
|
||||
"x = L.numpy.extract_atom(\"x\")\n",
|
||||
"print(x[3])"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -130,7 +122,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[3].position = (1.0, 0.0, 1.0)"
|
||||
"x[3] = (1.0, 0.0, 1.0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -139,7 +131,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1.0)"
|
||||
"L.ipython.image(zoom=1.0,size=[320,320])"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -148,7 +140,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.eval(\"pe\")"
|
||||
"L.get_thermo(\"pe\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -157,7 +149,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[3].position = (1.0, 0.0, -1.0)"
|
||||
"x[3] = (1.0, 0.0, -1.0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -166,7 +158,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.run(0);"
|
||||
"cmd.run(0, \"post\", \"no\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -207,9 +199,9 @@
|
||||
"source": [
|
||||
"pe = []\n",
|
||||
"for p in pos:\n",
|
||||
" L.atoms[3].position = p\n",
|
||||
" L.run(0);\n",
|
||||
" pe.append(L.eval(\"pe\"))"
|
||||
" x[3] = p\n",
|
||||
" cmd.run(0, \"post\", \"no\");\n",
|
||||
" pe.append(L.get_thermo(\"pe\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -233,7 +225,7 @@
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
@ -247,9 +239,9 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.2"
|
||||
"version": "3.12.7"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 1
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@ -158,7 +158,8 @@ def elastic():
|
||||
parser.add_argument("--up", type=float, default=1.0e-6, help="the deformation magnitude (in strain units)")
|
||||
args = parser.parse_args()
|
||||
|
||||
L = PyLammps()
|
||||
lmp = lammps()
|
||||
L = lmp.cmd
|
||||
|
||||
L.units("metal")
|
||||
|
||||
63
python/examples/ipython/index.ipynb
Normal file
63
python/examples/ipython/index.ipynb
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "666d3036-47d5-44d2-bc1a-ca4b00a9e9b8",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# LAMMPS Python Tutorials"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "f1422a43-f76b-456b-bf76-61ad92bd4ff0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Author: [Richard Berger](mailto:richard.berger@outlook.com)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "8f2ea92d-8cc3-4999-81a0-79aa55bb66ab",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Contents\n",
|
||||
"\n",
|
||||
"- [Example 1: Using LAMMPS with Python](simple.ipynb)\n",
|
||||
"- [Example 2: Analyzing LAMMPS thermodynamic data](thermo.ipynb)\n",
|
||||
"- [Example 3: Using Atom Data](atoms.ipynb)\n",
|
||||
"- [Example 4: Validating a dihedral potential](dihedrals/dihedral.ipynb)\n",
|
||||
"- [Example 5: Running a Monte Carlo relaxation](montecarlo/mc.ipynb)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b41dc533-be6d-4450-8ad7-7345e9f44ea3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.7"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@ -4,7 +4,14 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Monte Carlo Relaxation"
|
||||
"<div style=\"text-align: center\"><a href=\"../index.ipynb\">LAMMPS Python Tutorials</a></div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Example 5: Monte Carlo Relaxation"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -13,16 +20,6 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from __future__ import print_function"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"import matplotlib.pyplot as plt"
|
||||
]
|
||||
},
|
||||
@ -48,7 +45,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from lammps import IPyLammps"
|
||||
"from lammps import lammps"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -57,7 +54,8 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L = IPyLammps()"
|
||||
"L = lammps()\n",
|
||||
"cmd = L.cmd"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -66,25 +64,25 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.units(\"lj\")\n",
|
||||
"L.atom_style(\"atomic\")\n",
|
||||
"L.atom_modify(\"map array sort\", 0, 0.0)\n",
|
||||
"cmd.units(\"lj\")\n",
|
||||
"cmd.atom_style(\"atomic\")\n",
|
||||
"cmd.atom_modify(\"map array sort\", 0, 0.0)\n",
|
||||
"\n",
|
||||
"L.dimension(2)\n",
|
||||
"cmd.dimension(2)\n",
|
||||
"\n",
|
||||
"L.lattice(\"hex\", 1.0)\n",
|
||||
"L.region(\"box block\", 0, 10, 0, 5, -0.5, 0.5)\n",
|
||||
"cmd.lattice(\"hex\", 1.0)\n",
|
||||
"cmd.region(\"box block\", 0, 10, 0, 5, -0.5, 0.5)\n",
|
||||
"\n",
|
||||
"L.create_box(1, \"box\")\n",
|
||||
"L.create_atoms(1, \"box\")\n",
|
||||
"L.mass(1, 1.0)\n",
|
||||
"cmd.create_box(1, \"box\")\n",
|
||||
"cmd.create_atoms(1, \"box\")\n",
|
||||
"cmd.mass(1, 1.0)\n",
|
||||
"\n",
|
||||
"L.pair_style(\"lj/cut\", 2.5)\n",
|
||||
"L.pair_coeff(1, 1, 1.0, 1.0, 2.5)\n",
|
||||
"L.pair_modify(\"shift\", \"yes\")\n",
|
||||
"cmd.pair_style(\"lj/cut\", 2.5)\n",
|
||||
"cmd.pair_coeff(1, 1, 1.0, 1.0, 2.5)\n",
|
||||
"cmd.pair_modify(\"shift\", \"yes\")\n",
|
||||
"\n",
|
||||
"L.neighbor(0.3, \"bin\")\n",
|
||||
"L.neigh_modify(\"delay\", 0, \"every\", 1, \"check\", \"yes\")"
|
||||
"cmd.neighbor(0.3, \"bin\")\n",
|
||||
"cmd.neigh_modify(\"delay\", 0, \"every\", 1, \"check\", \"yes\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -93,7 +91,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1.6)"
|
||||
"L.ipython.image(zoom=1.6,size=[320,320])"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -102,7 +100,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.run(0);"
|
||||
"cmd.run(0, \"post\", \"no\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -111,7 +109,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"emin = L.eval(\"pe\")"
|
||||
"emin = L.get_thermo(\"pe\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -120,7 +118,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.dump(\"3 all movie 25 movie.mp4 type type zoom 1.6 adiam 1.0\")"
|
||||
"cmd.dump(\"3 all movie 25 movie.mp4 type type zoom 1.6 adiam 1.0\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -146,11 +144,12 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for i in range(L.system.natoms):\n",
|
||||
" x, y = L.atoms[i].position\n",
|
||||
"pos = L.numpy.extract_atom(\"x\")\n",
|
||||
"for i in range(len(pos)):\n",
|
||||
" x, y = pos[i][0], pos[i][1]\n",
|
||||
" dx = deltaperturb * random.uniform(-1, 1)\n",
|
||||
" dy = deltaperturb * random.uniform(-1, 1)\n",
|
||||
" L.atoms[i].position = (x+dx, y+dy)"
|
||||
" pos[i] = (x+dx, y+dy, 0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -159,7 +158,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.run(0);"
|
||||
"cmd.run(0, \"post\", \"no\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -168,7 +167,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1.6)"
|
||||
"L.ipython.image(zoom=1.6,size=[320,320])"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -184,7 +183,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"estart = L.eval(\"pe\")\n",
|
||||
"estart = L.get_thermo(\"pe\")\n",
|
||||
"elast = estart"
|
||||
]
|
||||
},
|
||||
@ -223,22 +222,23 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"natoms = L.system.natoms\n",
|
||||
"natoms = L.extract_global(\"natoms\")\n",
|
||||
"\n",
|
||||
"for i in range(niterations):\n",
|
||||
" pos = L.numpy.extract_atom(\"x\")\n",
|
||||
" iatom = random.randrange(0, natoms)\n",
|
||||
" current_atom = L.atoms[iatom]\n",
|
||||
" current_atom = pos[iatom]\n",
|
||||
" \n",
|
||||
" x0, y0 = current_atom.position\n",
|
||||
" x0, y0 = current_atom[0], current_atom[1]\n",
|
||||
" \n",
|
||||
" dx = deltamove * random.uniform(-1, 1)\n",
|
||||
" dy = deltamove * random.uniform(-1, 1)\n",
|
||||
" \n",
|
||||
" current_atom.position = (x0+dx, y0+dy)\n",
|
||||
" pos[iatom] = (x0+dx, y0+dy, 0)\n",
|
||||
" \n",
|
||||
" L.run(1, \"pre no post no\")\n",
|
||||
" cmd.run(1, \"pre no post no\")\n",
|
||||
" \n",
|
||||
" e = L.eval(\"pe\")\n",
|
||||
" e = L.get_thermo(\"pe\")\n",
|
||||
" energies.append(e)\n",
|
||||
" \n",
|
||||
" if e <= elast:\n",
|
||||
@ -248,7 +248,7 @@
|
||||
" naccept += 1\n",
|
||||
" elast = e\n",
|
||||
" else:\n",
|
||||
" current_atom.position = (x0, y0)"
|
||||
" pos[iatom] = (x0, y0, 0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -268,7 +268,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.eval(\"pe\")"
|
||||
"L.get_thermo(\"pe\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -304,7 +304,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1.6)"
|
||||
"L.ipython.image(zoom=1.6, size=[320,320])"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -314,7 +314,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# close dump file to access it\n",
|
||||
"L.undump(3)"
|
||||
"cmd.undump(3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -323,7 +323,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.video(\"movie.mp4\")"
|
||||
"L.ipython.video(\"movie.mp4\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -336,7 +336,7 @@
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
@ -350,9 +350,9 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.2"
|
||||
"version": "3.12.7"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 1
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
from mpi4py import MPI
|
||||
from lammps import PyLammps
|
||||
from lammps import lammps
|
||||
|
||||
L = PyLammps()
|
||||
L = lammps()
|
||||
L.file('in.melt')
|
||||
|
||||
|
||||
if MPI.COMM_WORLD.rank == 0:
|
||||
pe = L.eval("pe")
|
||||
pe = L.get_thermo("pe")
|
||||
print("Potential Energy:", pe)
|
||||
@ -4,14 +4,28 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Example 1: Using LAMMPS with PyLammps"
|
||||
"<div style=\"text-align: center\"><a href=\"index.ipynb\">LAMMPS Python Tutorials</a></div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The LAMMPS Python package provides multiple interfaces. The `PyLammps` interface is a high-level abstration of the low-level `lammps` interface. `IPyLammps` further extends this interface with functions that are useful for Jupyter notebooks to enable embedding generated graphics and videos."
|
||||
"# Example 1: Using LAMMPS with Python"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Author: [Richard Berger](mailto:richard.berger@outlook.com)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The LAMMPS Python package enables calling the LAMMPS C library API."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -20,7 +34,7 @@
|
||||
"source": [
|
||||
"## Prerequisites\n",
|
||||
"\n",
|
||||
"Before Running this example, make sure your Python environment can find the LAMMPS shared library (`liblammps.so`) and the LAMMPS Python package is installed. If you followed the [README](README.md) in this folder, this should already be the case. You can also find more information about how to compile LAMMPS and install the LAMMPS Python package in the [LAMMPS manual](https://docs.lammps.org/Python_install.html). There is also a dedicated [PyLammps HowTo](https://docs.lammps.org/Howto_pylammps.html)."
|
||||
"Before running this example, make sure your Python environment can find the LAMMPS shared library (`liblammps.so`) and the LAMMPS Python package is installed. If you followed the [README](README.md) in this folder, this should already be the case. You can also find more information about how to compile LAMMPS and install the LAMMPS Python package in the [LAMMPS manual](https://docs.lammps.org/Python_install.html). There is also a dedicated [LAMMPS Python HowTo](https://docs.lammps.org/Howto_python.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -38,17 +52,17 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from lammps import IPyLammps\n",
|
||||
"L = IPyLammps()"
|
||||
"from lammps import lammps\n",
|
||||
"L = lammps()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With `PyLammps`/`IPyLammps` you can write LAMMPS simulations similar to the input script language. Take the following LAMMPS input script:\n",
|
||||
"With the `lammps` class you can write LAMMPS simulations similar to the input script language. Take the following LAMMPS input script:\n",
|
||||
"\n",
|
||||
"```bash\n",
|
||||
"```lammps\n",
|
||||
"# 3d Lennard-Jones melt\n",
|
||||
"\n",
|
||||
"units lj\n",
|
||||
@ -72,7 +86,7 @@
|
||||
"\n",
|
||||
"thermo 50\n",
|
||||
"```\n",
|
||||
"The equivalent can be written with `PyLammps`/`IPyLammps`:"
|
||||
"The equivalent can be written in Python:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -83,35 +97,33 @@
|
||||
"source": [
|
||||
"# 3d Lennard-Jones melt\n",
|
||||
"\n",
|
||||
"L.units(\"lj\")\n",
|
||||
"L.atom_style(\"atomic\")\n",
|
||||
"L.cmd.units(\"lj\")\n",
|
||||
"L.cmd.atom_style(\"atomic\")\n",
|
||||
"\n",
|
||||
"L.lattice(\"fcc\", 0.8442)\n",
|
||||
"L.region(\"box\", \"block\", 0, 4, 0, 4, 0, 4)\n",
|
||||
"L.create_box(1, \"box\")\n",
|
||||
"L.create_atoms(1, \"box\")\n",
|
||||
"L.mass(1, 1.0)\n",
|
||||
"L.cmd.lattice(\"fcc\", 0.8442)\n",
|
||||
"L.cmd.region(\"box\", \"block\", 0, 4, 0, 4, 0, 4)\n",
|
||||
"L.cmd.create_box(1, \"box\")\n",
|
||||
"L.cmd.create_atoms(1, \"box\")\n",
|
||||
"L.cmd.mass(1, 1.0)\n",
|
||||
"\n",
|
||||
"L.velocity(\"all\", \"create\", 1.44, 87287, \"loop geom\")\n",
|
||||
"L.cmd.velocity(\"all\", \"create\", 1.44, 87287, \"loop geom\")\n",
|
||||
"\n",
|
||||
"L.pair_style(\"lj/cut\", 2.5)\n",
|
||||
"L.pair_coeff(1, 1, 1.0, 1.0, 2.5)\n",
|
||||
"L.cmd.pair_style(\"lj/cut\", 2.5)\n",
|
||||
"L.cmd.pair_coeff(1, 1, 1.0, 1.0, 2.5)\n",
|
||||
"\n",
|
||||
"L.neighbor(0.3, \"bin\")\n",
|
||||
"L.neigh_modify(\"delay\", 0, \"every\", 20, \"check no\")\n",
|
||||
"L.cmd.neighbor(0.3, \"bin\")\n",
|
||||
"L.cmd.neigh_modify(\"delay\", 0, \"every\", 20, \"check no\")\n",
|
||||
"\n",
|
||||
"L.fix(\"1\", \"all\", \"nve\")\n",
|
||||
"L.cmd.fix(\"1\", \"all\", \"nve\")\n",
|
||||
"\n",
|
||||
"L.thermo(50)"
|
||||
"L.cmd.thermo(50)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Visualizing the initial state\n",
|
||||
"\n",
|
||||
"`IPyLammps` allows you to visualize the current simulation state with the [image](https://docs.lammps.org/Python_module.html#lammps.IPyLammps.image) command. Here we use it to create an image of the initial state of the system."
|
||||
"Some LAMMPS commands will produce output that will be visible in the notebook. However, due to buffering, it might not be shown right away. Use the `flush_buffers` method to see all the output that has been written so far."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -120,7 +132,109 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1.0)"
|
||||
"L.flush_buffers()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"An alternative to this is to enable auto flushing after each command by setting `cmd.auto_flush` to `True`. Each command will then call `flush_buffers()` automatically."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.cmd.auto_flush = True\n",
|
||||
"L.cmd.info(\"system\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"In many cases the LAMMPS output will become excessive, which is why you may want to suppress it. For this purpose we provide a IPython extension in the `lammps.ipython` package. To load the extension, add a code cell with the following content:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%load_ext lammps.ipython"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Once the extension is loaded you have access to the `%%capture_lammps_output` magic. In its simplest form it can be used to supress LAMMPS output:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%%capture_lammps_output\n",
|
||||
"L.cmd.info(\"system\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"You can also use the same `%%capture_lammps_output` magic to store the output in a variable by providing a variable name:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%%capture_lammps_output out\n",
|
||||
"L.cmd.info(\"system\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"In this case we are storing the output in a `out` variable. Note the output is only available after the cell has been executed, not within the same cell."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"print(out)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Visualizing the initial state\n",
|
||||
"\n",
|
||||
"The `lammps` class also has an `ipython` attribute which provides some basic visualization capabilities in IPython Jupyter notebooks. E.g., you can visualize the current simulation state with the [image](https://docs.lammps.org/Python_module.html#lammps.ipython_wrapper.image) command. Here we use it to create an image of the initial state of the system."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.ipython.image()"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -129,7 +243,7 @@
|
||||
"source": [
|
||||
"## Running simulations\n",
|
||||
"\n",
|
||||
"Use the `run` command to start the simulation. In Jupyter the return value of the last command will be displayed. The `run` command will return the output of the simulation."
|
||||
"Use the `run` command to start the simulation. It will print the output of the simulation."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -138,23 +252,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.run(150)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"You can suppress it by adding a semicolon `;`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.run(100);"
|
||||
"L.cmd.run(250)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -170,127 +268,23 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1.0)"
|
||||
"L.ipython.image(zoom=1.0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Post-processing thermo output\n",
|
||||
"## Conclusion\n",
|
||||
"This covered the basics of creating an instance of LAMMPS from Python, passing commands to LAMMPS and potentially supressing or capturing its output, and visualizing the system. In the [following tutorial](thermo.ipynb) we will look at how to process thermodynamic output from LAMMPS.\n",
|
||||
"\n",
|
||||
"Independent of whether or not you suppress or show the output of the `run` command, `PyLammps` will record the output. Each `run` command creates a new entry in the `L.runs` list. So far our PyLammps instance `L` executed two `run` commands:"
|
||||
"<div style=\"text-align:right\"><a href=\"thermo.ipynb\">Next</a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"len(L.runs)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Each entry contains information about the simulation run, including the thermo output for the printed out time steps.\n",
|
||||
"\n",
|
||||
"```bash\n",
|
||||
"# thermo output of a LAMMPS simulation run\n",
|
||||
"Step Temp E_pair E_mol TotEng Press\n",
|
||||
" 0 1.44 -6.7733681 0 -4.6218056 -5.0244179\n",
|
||||
" 50 0.70303849 -5.6796164 0 -4.629178 0.50453907\n",
|
||||
" 100 0.72628044 -5.7150774 0 -4.6299123 0.29765862\n",
|
||||
" 150 0.78441711 -5.805142 0 -4.6331125 -0.086709661\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"`PyLammps` already parses this information and makes it available as dictionaries and arrays."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.runs[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.runs[1]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"For example, the first run was 150 time steps, with printing out a line every 50 steps. You can access the list of time steps using `{entry}.thermo.Step`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.runs[0].thermo.Step"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The corresponding values of each thermo quantity are also accessed this way:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.runs[0].thermo.TotEng"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Together you can use this information to run post-processing on these values or even plot it using `matplotlib`:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"plt.xlabel('time step')\n",
|
||||
"plt.ylabel('Total Energy')\n",
|
||||
"plt.plot(L.runs[0].thermo.Step, L.runs[0].thermo.TotEng)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
@ -304,9 +298,9 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.2"
|
||||
"version": "3.12.7"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 1
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
323
python/examples/ipython/thermo.ipynb
Normal file
323
python/examples/ipython/thermo.ipynb
Normal file
@ -0,0 +1,323 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Example 2: Analyzing LAMMPS thermodynamic data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Author: [Richard Berger](mailto:richard.berger@outlook.com)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This tutorial assumes you've completed the [first example](simple.ipynb) and understand the basics of running LAMMPS through Python. In this tutorial we will build on top of that example and look at how to extract thermodynamic data produced by LAMMPS into Python and visualize it. Let's first start by recreating our simple melt example:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%load_ext lammps.ipython"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from lammps import lammps\n",
|
||||
"L = lammps()\n",
|
||||
"L.cmd.auto_flush = True\n",
|
||||
"\n",
|
||||
"def init_melt_system(L):\n",
|
||||
" # 3d Lennard-Jones melt\n",
|
||||
" L.cmd.clear()\n",
|
||||
" L.cmd.units(\"lj\")\n",
|
||||
" L.cmd.atom_style(\"atomic\")\n",
|
||||
" \n",
|
||||
" L.cmd.lattice(\"fcc\", 0.8442)\n",
|
||||
" L.cmd.region(\"box\", \"block\", 0, 4, 0, 4, 0, 4)\n",
|
||||
" L.cmd.create_box(1, \"box\")\n",
|
||||
" L.cmd.create_atoms(1, \"box\")\n",
|
||||
" L.cmd.mass(1, 1.0)\n",
|
||||
" \n",
|
||||
" L.cmd.velocity(\"all\", \"create\", 1.44, 87287, \"loop geom\")\n",
|
||||
" \n",
|
||||
" L.cmd.pair_style(\"lj/cut\", 2.5)\n",
|
||||
" L.cmd.pair_coeff(1, 1, 1.0, 1.0, 2.5)\n",
|
||||
" \n",
|
||||
" L.cmd.neighbor(0.3, \"bin\")\n",
|
||||
" L.cmd.neigh_modify(\"delay\", 0, \"every\", 20, \"check no\")\n",
|
||||
" \n",
|
||||
" L.cmd.fix(\"1\", \"all\", \"nve\")\n",
|
||||
" \n",
|
||||
" L.cmd.thermo(50)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Here we take advantage of the fact that we can write regular Python functions to organize our LAMMPS simulation. This allows us to clear and initialize a new system by calling the `init_melt_system()` function. With this we can now go ahead an run this simulation for 100 steps."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"init_melt_system(L)\n",
|
||||
"L.cmd.run(100)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Extracting thermodynamic data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Looking at the above output we see that LAMMPS prints out thermodynamic data for steps 0, 50 and 100.\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
" Step Temp E_pair E_mol TotEng Press \n",
|
||||
" 0 1.44 -6.7733681 0 -4.6218056 -5.0244179 \n",
|
||||
" 50 0.70303849 -5.6796164 0 -4.629178 0.50453907 \n",
|
||||
" 100 0.72628044 -5.7150774 0 -4.6299123 0.29765862\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"We could parse the text output and extract the necessary information, but this has proven to be error-prone and clunky, especially in cases where other output gets interleaved with thermo output lines. Instead, we can make use of the Python integration within LAMMPS to execute arbitrary Python code during time steps using `fix python/invoke`. We can extract the thermodynamic data directly using the LAMMPS Python interface and process it in any way we want.\n",
|
||||
"\n",
|
||||
"For this we first define the data structure we want to use to store the data. For each column of the thermodynamic data we want to store a list of values for each time step. Let's use a Python `dict` with the following structure:\n",
|
||||
"\n",
|
||||
"```python\n",
|
||||
"{'Step': [0, 50, 100, ...], 'Temp': [...], 'E_pair': [...], 'E_mol': [...], 'TotEng': [...], 'Press': [...]}\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"To start, let's define an empty `dict` and call it `current_run`. As the simulation progresses, we append new data into this dictionary:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"current_run = {}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Next, let's define a function that should be executed every time step a thermodynamic output line would be written. This function takes a `lammps` class instance and through it can access LAMMPS state and data. We can use the [`last_thermo()`](https://docs.lammps.org/Python_module.html#lammps.lammps.last_thermo) function of the `lammps` class to get the latest thermodynamic data as a dictionary. This data is all we need to populate our `current_run` data structure."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def append_thermo_data(lmp):\n",
|
||||
" for k, v in lmp.last_thermo().items():\n",
|
||||
" current_run.setdefault(k, []).append(v)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With these two pieces in place, it is now time to tell LAMMPS about how we want to call this function.\n",
|
||||
"\n",
|
||||
"First, let's suppress any LAMMPS output via `%%capture_lammps_output` and reinitialize our system with `init_melt_system()` so our system is back in its initial state and the time step is back to 0.\n",
|
||||
"\n",
|
||||
"Next, we add a new fix `python/invoke` that should execute every 50 time steps, the same as our `thermo 50` command above. At the end of every 50 time steps (including the first one), it should call the `append_thermo_data` function we just defined. Notice we can just pass the function as parameter. Finally, we tell LAMMPS to run for 250 steps."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%%capture_lammps_output\n",
|
||||
"init_melt_system(L)\n",
|
||||
"L.cmd.fix(\"myfix\", \"all\", \"python/invoke\", 50, \"end_of_step\", append_thermo_data)\n",
|
||||
"L.cmd.run(250)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's inspect our `current_run` dictionary after the run has completed:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"current_run"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"As we can see, the time steps 0, 50, 100, 150, and 200 were added to dictionary. However, the last time step 250 is still missing. For this we need to manually add a final call to our `append_thermo_data()` helper function."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"append_thermo_data(L)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With this our `current_run` dictionary now has all the data of the completed run:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"current_run"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Plotting thermodynamic data with matplotlib\n",
|
||||
"\n",
|
||||
"Now that we have our data available as Python variables, we can easily use other libraries for visualization."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"plt.xlabel('time step')\n",
|
||||
"plt.ylabel('Total Energy')\n",
|
||||
"plt.plot(current_run['Step'], current_run['TotEng'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Using Pandas library\n",
|
||||
"\n",
|
||||
"Since we can call any Python code from LAMMPS, the above example can also be rewritten using the Pandas library:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%%capture_lammps_output\n",
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"current_run = pd.DataFrame()\n",
|
||||
"\n",
|
||||
"def append_thermo_data(lmp):\n",
|
||||
" global current_run\n",
|
||||
" current_time_step = pd.DataFrame.from_records([lmp.last_thermo()])\n",
|
||||
" current_run = pd.concat([current_run, current_time_step], ignore_index=True)\n",
|
||||
"\n",
|
||||
"init_melt_system(L)\n",
|
||||
"L.cmd.fix(\"myfix\", \"all\", \"python/invoke\", 50, \"end_of_step\", append_thermo_data)\n",
|
||||
"L.cmd.run(250)\n",
|
||||
"append_thermo_data(L)\n",
|
||||
"current_run"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"current_run.plot(x='Step', y='TotEng')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Conclusion\n",
|
||||
"\n",
|
||||
"The Python interface gives you a powerful way of invoking and extracting simulation data while the simulation is running. Next we'll look at how to extract information about the atoms in your system.\n",
|
||||
"\n",
|
||||
"<div style=\"text-align:right\"><a href=\"atoms.ipynb\">Next</a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.7"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@ -1,546 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Example 2: Using the PyLammps interface"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Prerequisites\n",
|
||||
"\n",
|
||||
"Before running this example, make sure your Python environment can find the LAMMPS shared library (`liblammps.so`) and the LAMMPS Python package is installed. If you followed the [README](README.md) in this folder, this should already be the case. You can also find more information about how to compile LAMMPS and install the LAMMPS Python package in the [LAMMPS manual](https://docs.lammps.org/Python_install.html). There is also a dedicated [PyLammps HowTo](https://docs.lammps.org/Howto_pylammps.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Setup system"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from lammps import IPyLammps"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L = IPyLammps()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 3d Lennard-Jones melt\n",
|
||||
"L.units(\"lj\")\n",
|
||||
"L.atom_style(\"atomic\")\n",
|
||||
"L.atom_modify(\"map array\")\n",
|
||||
"\n",
|
||||
"L.lattice(\"fcc\", 0.8442)\n",
|
||||
"L.region(\"box block\", 0, 4, 0, 4, 0, 4)\n",
|
||||
"L.create_box(1, \"box\")\n",
|
||||
"L.create_atoms(1, \"box\")\n",
|
||||
"L.mass(1, 1.0)\n",
|
||||
"\n",
|
||||
"L.velocity(\"all create\", 1.44, 87287, \"loop geom\")\n",
|
||||
"\n",
|
||||
"L.pair_style(\"lj/cut\", 2.5)\n",
|
||||
"L.pair_coeff(1, 1, 1.0, 1.0, 2.5)\n",
|
||||
"\n",
|
||||
"L.neighbor(0.3, \"bin\")\n",
|
||||
"L.neigh_modify(\"delay 0 every 20 check no\")\n",
|
||||
"\n",
|
||||
"L.fix(\"1 all nve\")\n",
|
||||
"\n",
|
||||
"L.variable(\"fx atom fx\")\n",
|
||||
"\n",
|
||||
"L.run(10)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Visualize the initial state"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Queries about LAMMPS simulation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.system"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.system.natoms"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.communication"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.fixes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.computes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.dumps"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.groups"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Working with LAMMPS Variables"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variable(\"a index 2\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variable(\"t equal temp\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"if sys.version_info < (3, 0):\n",
|
||||
" # In Python 2 'print' is a restricted keyword, which is why you have to use the lmp_print function instead.\n",
|
||||
" x = float(L.lmp_print('\"${a}\"'))\n",
|
||||
"else:\n",
|
||||
" # In Python 3 the print function can be redefined.\n",
|
||||
" # x = float(L.print('\"${a}\"')\")\n",
|
||||
" \n",
|
||||
" # To avoid a syntax error in Python 2 executions of this notebook, this line is packed into an eval statement\n",
|
||||
" x = float(eval(\"L.print('\\\"${a}\\\"')\"))\n",
|
||||
"x"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['t'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.eval(\"v_t/2.0\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variable(\"b index a b c\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['b'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.eval(\"v_b\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['b'].definition"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.lmp.command('variable i loop 10')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variable(\"i loop 10\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['i'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.next(\"i\")\n",
|
||||
"L.variables['i'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.eval(\"ke\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Accessing Atom data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"dir(L.atoms[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].position"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].velocity"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].force"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['fx'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Accessing thermo data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.runs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.runs[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.runs[0].thermo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.runs[0].thermo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"dir(L.runs[0].thermo)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Saving session to as LAMMPS input file"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"PyLammps can keep track of all LAMMPS commands that are executed. This allows you to prototype a script and then later on save it as a regular input script:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L = IPyLammps()\n",
|
||||
"\n",
|
||||
"# enable command history\n",
|
||||
"L.enable_cmd_history = True\n",
|
||||
"\n",
|
||||
"# 3d Lennard-Jones melt\n",
|
||||
"L.units(\"lj\")\n",
|
||||
"L.atom_style(\"atomic\")\n",
|
||||
"L.atom_modify(\"map array\")\n",
|
||||
"\n",
|
||||
"L.lattice(\"fcc\", 0.8442)\n",
|
||||
"L.region(\"box block\", 0, 4, 0, 4, 0, 4)\n",
|
||||
"L.create_box(1, \"box\")\n",
|
||||
"L.create_atoms(1, \"box\")\n",
|
||||
"L.mass(1, 1.0)\n",
|
||||
"\n",
|
||||
"L.velocity(\"all create\", 1.44, 87287, \"loop geom\")\n",
|
||||
"\n",
|
||||
"L.pair_style(\"lj/cut\", 2.5)\n",
|
||||
"L.pair_coeff(1, 1, 1.0, 1.0, 2.5)\n",
|
||||
"\n",
|
||||
"L.neighbor(0.3, \"bin\")\n",
|
||||
"L.neigh_modify(\"delay 0 every 20 check no\")\n",
|
||||
"\n",
|
||||
"L.fix(\"1 all nve\")\n",
|
||||
"\n",
|
||||
"L.run(10)\n",
|
||||
"\n",
|
||||
"# write LAMMPS input script with all commands executed so far (including implicit ones)\n",
|
||||
"L.write_script(\"in.output\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!cat in.output"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.2"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 1
|
||||
}
|
||||
@ -1,471 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Example 3: 2D circle of particles inside of box with LJ walls"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Prerequisites\n",
|
||||
"\n",
|
||||
"Before running this example, make sure your Python environment can find the LAMMPS shared library (`liblammps.so`) and the LAMMPS Python package is installed. If you followed the [README](README.md) in this folder, this should already be the case. You can also find more information about how to compile LAMMPS and install the LAMMPS Python package in the [LAMMPS manual](https://docs.lammps.org/Python_install.html). There is also a dedicated [PyLammps HowTo](https://docs.lammps.org/Howto_pylammps.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Setup system"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from lammps import IPyLammps"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L = IPyLammps()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 2d circle of particles inside a box with LJ walls\n",
|
||||
"import math\n",
|
||||
"\n",
|
||||
"b = 0\n",
|
||||
"x = 50\n",
|
||||
"y = 20\n",
|
||||
"d = 20\n",
|
||||
"\n",
|
||||
"# careful not to slam into wall too hard\n",
|
||||
"\n",
|
||||
"v = 0.3\n",
|
||||
"w = 0.08\n",
|
||||
" \n",
|
||||
"L.units(\"lj\")\n",
|
||||
"L.dimension(2)\n",
|
||||
"L.atom_style(\"bond\")\n",
|
||||
"L.boundary(\"f f p\")\n",
|
||||
"\n",
|
||||
"L.lattice(\"hex\", 0.85)\n",
|
||||
"L.region(\"box\", \"block\", 0, x, 0, y, -0.5, 0.5)\n",
|
||||
"L.create_box(1, \"box\", \"bond/types\", 1, \"extra/bond/per/atom\", 6)\n",
|
||||
"L.region(\"circle\", \"sphere\", d/2.0+1.0, d/2.0/math.sqrt(3.0)+1, 0.0, d/2.0)\n",
|
||||
"L.create_atoms(1, \"region\", \"circle\")\n",
|
||||
"L.mass(1, 1.0)\n",
|
||||
"\n",
|
||||
"L.velocity(\"all create 0.5 87287 loop geom\")\n",
|
||||
"L.velocity(\"all set\", v, w, 0, \"sum yes\")\n",
|
||||
"\n",
|
||||
"L.pair_style(\"lj/cut\", 2.5)\n",
|
||||
"L.pair_coeff(1, 1, 10.0, 1.0, 2.5)\n",
|
||||
"\n",
|
||||
"L.bond_style(\"harmonic\")\n",
|
||||
"L.bond_coeff(1, 10.0, 1.2)\n",
|
||||
"\n",
|
||||
"L.create_bonds(\"many\", \"all\", \"all\", 1, 1.0, 1.5)\n",
|
||||
"\n",
|
||||
"L.neighbor(0.3, \"bin\")\n",
|
||||
"L.neigh_modify(\"delay\", 0, \"every\", 1, \"check yes\")\n",
|
||||
"\n",
|
||||
"L.fix(1, \"all\", \"nve\")\n",
|
||||
"\n",
|
||||
"L.fix(2, \"all wall/lj93 xlo 0.0 1 1 2.5 xhi\", x, \"1 1 2.5\")\n",
|
||||
"L.fix(3, \"all wall/lj93 ylo 0.0 1 1 2.5 yhi\", y, \"1 1 2.5\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Visualize initial state"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.image(zoom=1.8)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Run simulation and visualize new state"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.thermo_style(\"custom step temp epair press\")\n",
|
||||
"L.thermo(100)\n",
|
||||
"output = L.run(40000)\n",
|
||||
"L.image(zoom=1.8)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Queries about LAMMPS simulation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.system"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.system.natoms"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.system.nbonds"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.system.nbondtypes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.communication"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.fixes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.computes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.dumps"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.groups"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Working with LAMMPS Variables"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variable(\"a index 2\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variable(\"t equal temp\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"if sys.version_info < (3, 0):\n",
|
||||
" # In Python 2 'print' is a restricted keyword, which is why you have to use the lmp_print function instead.\n",
|
||||
" x = float(L.lmp_print('\"${a}\"'))\n",
|
||||
"else:\n",
|
||||
" # In Python 3 the print function can be redefined.\n",
|
||||
" # x = float(L.print('\"${a}\"')\")\n",
|
||||
" \n",
|
||||
" # To avoid a syntax error in Python 2 executions of this notebook, this line is packed into an eval statement\n",
|
||||
" x = float(eval(\"L.print('\\\"${a}\\\"')\"))\n",
|
||||
"x"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['t'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.eval(\"v_t/2.0\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variable(\"b index a b c\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['b'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.eval(\"v_b\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['b'].definition"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variable(\"i loop 10\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.variables['i'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.next(\"i\")\n",
|
||||
"L.variables['i'].value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.eval(\"ke\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Accessing Atom data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"dir(L.atoms[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].position"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].velocity"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].force"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"L.atoms[0].type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.2"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 1
|
||||
}
|
||||
@ -59,6 +59,87 @@ class ExceptionCheck:
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
class command_wrapper(object):
|
||||
def __init__(self, lmp):
|
||||
self.lmp = lmp
|
||||
self.auto_flush = False
|
||||
|
||||
def lmp_print(self, s):
|
||||
""" needed for Python2 compatibility, since print is a reserved keyword """
|
||||
return self.__getattr__("print")(s)
|
||||
|
||||
def __dir__(self):
|
||||
return sorted(set(['angle_coeff', 'angle_style', 'atom_modify', 'atom_style', 'atom_style',
|
||||
'bond_coeff', 'bond_style', 'boundary', 'change_box', 'communicate', 'compute',
|
||||
'create_atoms', 'create_box', 'delete_atoms', 'delete_bonds', 'dielectric',
|
||||
'dihedral_coeff', 'dihedral_style', 'dimension', 'dump', 'fix', 'fix_modify',
|
||||
'group', 'improper_coeff', 'improper_style', 'include', 'kspace_modify',
|
||||
'kspace_style', 'lattice', 'mass', 'minimize', 'min_style', 'neighbor',
|
||||
'neigh_modify', 'newton', 'nthreads', 'pair_coeff', 'pair_modify',
|
||||
'pair_style', 'processors', 'read', 'read_data', 'read_restart', 'region',
|
||||
'replicate', 'reset_timestep', 'restart', 'run', 'run_style', 'thermo',
|
||||
'thermo_modify', 'thermo_style', 'timestep', 'undump', 'unfix', 'units',
|
||||
'variable', 'velocity', 'write_restart'] + self.lmp.available_styles("command")))
|
||||
|
||||
def _wrap_args(self, x):
|
||||
if callable(x):
|
||||
if sys.version_info < (3,):
|
||||
raise Exception("Passing functions or lambdas directly as arguments is only supported in Python 3 or newer")
|
||||
import hashlib
|
||||
import __main__
|
||||
sha = hashlib.sha256()
|
||||
sha.update(str(x).encode())
|
||||
func_name = f"_lmp_cb_{sha.hexdigest()}"
|
||||
def handler(*args, **kwargs):
|
||||
args = list(args)
|
||||
args[0] = lammps(ptr=args[0])
|
||||
x(*args)
|
||||
setattr(__main__, func_name, handler)
|
||||
return func_name
|
||||
return x
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""
|
||||
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()`.
|
||||
|
||||
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
|
||||
parameter list, only a subset of LAMMPS commands can be used with this
|
||||
syntax.
|
||||
|
||||
LAMMPS commands that accept callback functions (such as fix python/invoke)
|
||||
can be passed functions and lambdas directly. The first argument of such
|
||||
callbacks will be an lammps object constructed from the passed LAMMPS
|
||||
pointer.
|
||||
|
||||
:return: line or list of lines of output, None if no output
|
||||
:rtype: list or string
|
||||
"""
|
||||
def handler(*args, **kwargs):
|
||||
cmd_args = [name] + [str(self._wrap_args(x)) for x in args]
|
||||
|
||||
if len(kwargs) > 0 and sys.version_info < (3,6):
|
||||
raise Exception("Keyword arguments are only supported in Python 3.6 or newer")
|
||||
|
||||
# Python 3.6+ maintains ordering of kwarg keys
|
||||
for k in kwargs.keys():
|
||||
cmd_args.append(k)
|
||||
if type(kwargs[k]) == bool:
|
||||
cmd_args.append("true" if kwargs[k] else "false")
|
||||
else:
|
||||
cmd_args.append(str(self._wrap_args(kwargs[k])))
|
||||
|
||||
cmd = ' '.join(cmd_args)
|
||||
self.lmp.command(cmd)
|
||||
if self.auto_flush:
|
||||
self.lmp.flush_buffers()
|
||||
return handler
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
class lammps(object):
|
||||
"""Create an instance of the LAMMPS Python class.
|
||||
|
||||
@ -103,6 +184,8 @@ class lammps(object):
|
||||
winpath = os.environ.get("LAMMPSDLLPATH")
|
||||
self.lib = None
|
||||
self.lmp = None
|
||||
self._cmd = None
|
||||
self._ipython = None
|
||||
|
||||
# if a pointer to a LAMMPS object is handed in
|
||||
# when being called from a Python interpreter
|
||||
@ -509,6 +592,61 @@ class lammps(object):
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@property
|
||||
def cmd(self):
|
||||
""" Return object that acts as LAMMPS command wrapper
|
||||
|
||||
It provides alternative to :py:meth:`lammps.command` to call LAMMPS
|
||||
commands as if they were regular Python functions and enables auto-complete
|
||||
in interactive Python sessions.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import lammps
|
||||
|
||||
# melt example
|
||||
L = lammps()
|
||||
L.cmd.units("lj")
|
||||
L.cmd.atom_style("atomic")
|
||||
L.cmd.lattice("fcc", 0.8442)
|
||||
L.cmd.region("box block", 0, 10, 0, 10, 0, 10)
|
||||
L.cmd.create_box(1, "box")
|
||||
L.cmd.create_atoms(1, "box")
|
||||
L.cmd.mass(1, 1.0)
|
||||
L.cmd.velocity("all create", 3.0, 87287, "loop geom")
|
||||
L.cmd.pair_style("lj/cut", 2.5)
|
||||
L.cmd.pair_coeff(1, 1, 1.0, 1.0, 2.5)
|
||||
L.cmd.neighbor(0.3, "bin")
|
||||
L.cmd.neigh_modify(every=20, delay=0, check=False)
|
||||
L.cmd.fix(1, "all nve")
|
||||
L.cmd.thermo(50)
|
||||
L.cmd.run(250)
|
||||
|
||||
:return: instance of command_wrapper object
|
||||
:rtype: command_wrapper
|
||||
"""
|
||||
if not self._cmd:
|
||||
self._cmd = command_wrapper(self)
|
||||
return self._cmd
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@property
|
||||
def ipython(self):
|
||||
""" Return object to access ipython extensions
|
||||
|
||||
Adds commands for visualization in IPython and Jupyter Notebooks.
|
||||
|
||||
:return: instance of ipython wrapper object
|
||||
:rtype: ipython.wrapper
|
||||
"""
|
||||
if not self._ipython:
|
||||
from .ipython import wrapper
|
||||
self._ipython = wrapper(self)
|
||||
return self._ipython
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def close(self):
|
||||
"""Explicitly delete a LAMMPS instance through the C-library interface.
|
||||
|
||||
|
||||
23
python/lammps/ipython/__init__.py
Normal file
23
python/lammps/ipython/__init__.py
Normal file
@ -0,0 +1,23 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
# https://www.lammps.org/ Sandia National Laboratories
|
||||
# LAMMPS Development team: developers@lammps.org
|
||||
#
|
||||
# Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
# certain rights in this software. This software is distributed under
|
||||
# the GNU General Public License.
|
||||
#
|
||||
# See the README file in the top-level LAMMPS directory.
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
################################################################################
|
||||
# IPython/Jupyter Notebook additions
|
||||
# Written by Richard Berger <richard.berger@outlook.com>
|
||||
################################################################################
|
||||
|
||||
from .wrapper import wrapper
|
||||
from .magics import LammpsMagics
|
||||
|
||||
def load_ipython_extension(ipython):
|
||||
ipython.register_magics(LammpsMagics)
|
||||
75
python/lammps/ipython/magics.py
Normal file
75
python/lammps/ipython/magics.py
Normal file
@ -0,0 +1,75 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
# https://www.lammps.org/ Sandia National Laboratories
|
||||
# LAMMPS Development team: developers@lammps.org
|
||||
#
|
||||
# Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
# certain rights in this software. This software is distributed under
|
||||
# the GNU General Public License.
|
||||
#
|
||||
# See the README file in the top-level LAMMPS directory.
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
################################################################################
|
||||
# IPython/Jupyter Notebook additions
|
||||
# Written by Richard Berger <richard.berger@outlook.com>
|
||||
################################################################################
|
||||
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
from IPython.core.magic import (Magics, magics_class, cell_magic)
|
||||
import IPython.core.magic_arguments as magic_arguments
|
||||
|
||||
class OutputCapture(object):
|
||||
""" Utility class to capture LAMMPS library output """
|
||||
def __init__(self):
|
||||
self.stdout_fd = 1
|
||||
self.captured_output = ""
|
||||
|
||||
def __enter__(self):
|
||||
self.tmpfile = tempfile.TemporaryFile(mode='w+b')
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
# make copy of original stdout
|
||||
self.stdout_orig = os.dup(self.stdout_fd)
|
||||
|
||||
# replace stdout and redirect to temp file
|
||||
os.dup2(self.tmpfile.fileno(), self.stdout_fd)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
os.dup2(self.stdout_orig, self.stdout_fd)
|
||||
os.close(self.stdout_orig)
|
||||
self.tmpfile.close()
|
||||
|
||||
@property
|
||||
def output(self):
|
||||
sys.stdout.flush()
|
||||
self.tmpfile.flush()
|
||||
self.tmpfile.seek(0, io.SEEK_SET)
|
||||
self.captured_output = self.tmpfile.read().decode('utf-8')
|
||||
return self.captured_output
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@magics_class
|
||||
class LammpsMagics(Magics):
|
||||
@magic_arguments.magic_arguments()
|
||||
@magic_arguments.argument('output', type=str, default='', nargs='?',
|
||||
help="""The name of the variable in which to store output.
|
||||
|
||||
If unspecified, captured output is discarded.
|
||||
"""
|
||||
)
|
||||
@cell_magic
|
||||
def capture_lammps_output(self, line, cell):
|
||||
"""run the cell, capturing LAMMPS stdout and stderr."""
|
||||
args = magic_arguments.parse_argstring(self.capture_lammps_output, line)
|
||||
with OutputCapture() as capture:
|
||||
self.shell.run_cell(cell)
|
||||
if args.output:
|
||||
self.shell.user_ns[args.output] = capture.output
|
||||
113
python/lammps/ipython/wrapper.py
Normal file
113
python/lammps/ipython/wrapper.py
Normal file
@ -0,0 +1,113 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
# https://www.lammps.org/ Sandia National Laboratories
|
||||
# LAMMPS Development team: developers@lammps.org
|
||||
#
|
||||
# Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
# certain rights in this software. This software is distributed under
|
||||
# the GNU General Public License.
|
||||
#
|
||||
# See the README file in the top-level LAMMPS directory.
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
################################################################################
|
||||
# IPython/Jupyter Notebook additions
|
||||
# Written by Richard Berger <richard.berger@outlook.com>
|
||||
################################################################################
|
||||
|
||||
class wrapper(object):
|
||||
"""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
|
||||
that allow create and/or embed visualizations created by native LAMMPS
|
||||
commands.
|
||||
|
||||
There is no need to explicitly instantiate this class. Each instance
|
||||
of :py:class:`lammps` has a :py:attr:`ipython <lammps.ipython>` property
|
||||
that returns an instance.
|
||||
|
||||
:param lmp: instance of the :py:class:`lammps` class
|
||||
:type lmp: lammps
|
||||
"""
|
||||
def __init__(self, lmp):
|
||||
self.lmp = lmp
|
||||
|
||||
def image(self, filename="snapshot.png", group="all", color="type", diameter="type",
|
||||
size=None, view=None, center=None, up=None, zoom=1.0, background_color="white"):
|
||||
""" Generate image using write_dump command and display it
|
||||
|
||||
See :doc:`dump image <dump_image>` for more information.
|
||||
|
||||
:param filename: Name of the image file that should be generated. The extension determines whether it is PNG or JPEG
|
||||
:type filename: string
|
||||
:param group: the group of atoms write_image should use
|
||||
:type group: string
|
||||
:param color: name of property used to determine color
|
||||
:type color: string
|
||||
:param diameter: name of property used to determine atom diameter
|
||||
:type diameter: string
|
||||
:param size: dimensions of image
|
||||
:type size: tuple (width, height)
|
||||
:param view: view parameters
|
||||
:type view: tuple (theta, phi)
|
||||
:param center: center parameters
|
||||
:type center: tuple (flag, center_x, center_y, center_z)
|
||||
:param up: vector pointing to up direction
|
||||
:type up: tuple (up_x, up_y, up_z)
|
||||
:param zoom: zoom factor
|
||||
:type zoom: float
|
||||
:param background_color: background color of scene
|
||||
:type background_color: string
|
||||
|
||||
:return: Image instance used to display image in notebook
|
||||
:rtype: :py:class:`IPython.core.display.Image`
|
||||
"""
|
||||
cmd_args = [group, "image", filename, color, diameter]
|
||||
|
||||
if size is not None:
|
||||
width = size[0]
|
||||
height = size[1]
|
||||
cmd_args += ["size", width, height]
|
||||
|
||||
if view is not None:
|
||||
theta = view[0]
|
||||
phi = view[1]
|
||||
cmd_args += ["view", theta, phi]
|
||||
|
||||
if center is not None:
|
||||
flag = center[0]
|
||||
Cx = center[1]
|
||||
Cy = center[2]
|
||||
Cz = center[3]
|
||||
cmd_args += ["center", flag, Cx, Cy, Cz]
|
||||
|
||||
if up is not None:
|
||||
Ux = up[0]
|
||||
Uy = up[1]
|
||||
Uz = up[2]
|
||||
cmd_args += ["up", Ux, Uy, Uz]
|
||||
|
||||
if zoom is not None:
|
||||
cmd_args += ["zoom", zoom]
|
||||
|
||||
cmd_args.append("modify backcolor " + background_color)
|
||||
|
||||
self.lmp.cmd.write_dump(*cmd_args)
|
||||
from IPython.core.display import Image
|
||||
return Image(filename)
|
||||
|
||||
def video(self, filename):
|
||||
"""
|
||||
Load video from file
|
||||
|
||||
Can be used to visualize videos from :doc:`dump movie <dump_image>`.
|
||||
|
||||
:param filename: Path to video file
|
||||
:type filename: string
|
||||
:return: HTML Video Tag used by notebook to embed a video
|
||||
:rtype: :py:class:`IPython.display.HTML`
|
||||
"""
|
||||
from IPython.display import HTML
|
||||
return HTML("<video controls><source src=\"" + filename + "\"></video>")
|
||||
@ -428,6 +428,8 @@ class PyLammps(object):
|
||||
lower-level interface. The original interface can still be accessed via
|
||||
:py:attr:`PyLammps.lmp`.
|
||||
|
||||
.. deprecated:: TBA
|
||||
|
||||
:param name: "machine" name of the shared LAMMPS library ("mpi" loads ``liblammps_mpi.so``, "" loads ``liblammps.so``)
|
||||
:type name: string
|
||||
:param cmdargs: list of command line arguments to be passed to the :cpp:func:`lammps_open` function. The executable name is automatically added.
|
||||
@ -468,6 +470,12 @@ class PyLammps(object):
|
||||
self.comm_nprocs = self.lmp.extract_setting("world_size")
|
||||
self.comm_me = self.lmp.extract_setting("world_rank")
|
||||
if self.comm_me == 0:
|
||||
print("\nWARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING")
|
||||
print("WARNING:")
|
||||
print("WARNING: The PyLammps class is obsolete and will be removed from LAMMPS soon.")
|
||||
print("WARNING: Please use the lammps Python class instead.")
|
||||
print("WARNING:")
|
||||
print("WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING\n")
|
||||
print("LAMMPS output is captured by PyLammps wrapper")
|
||||
if self.comm_nprocs > 1:
|
||||
print("WARNING: Using PyLammps with multiple MPI ranks is experimental. Not all functionality is supported.")
|
||||
|
||||
@ -26,7 +26,7 @@ class BinaryDistribution(Distribution):
|
||||
return True
|
||||
|
||||
if version_info.major >= 3:
|
||||
pkgs = ['lammps', 'lammps.mliap']
|
||||
pkgs = ['lammps', 'lammps.mliap', 'lammps.ipython']
|
||||
else:
|
||||
pkgs = ['lammps']
|
||||
|
||||
|
||||
2
src/.gitignore
vendored
2
src/.gitignore
vendored
@ -507,6 +507,8 @@
|
||||
/angle_harmonic.h
|
||||
/angle_mm3.cpp
|
||||
/angle_mm3.h
|
||||
/angle_mwlc.cpp
|
||||
/angle_mwlc.h
|
||||
/angle_quartic.cpp
|
||||
/angle_quartic.h
|
||||
/angle_spica.cpp
|
||||
|
||||
@ -9,6 +9,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
The ATC package will be removed from LAMMPS in Summer 2025 due to lack of
|
||||
maintenance and use of code constructs that conflict with modern C++ compilers
|
||||
and standards. Please contact developers@lammps.org if you have any concerns
|
||||
about this step.
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
action () {
|
||||
if (test $mode = 0) then
|
||||
rm -f ../$1
|
||||
|
||||
@ -9,6 +9,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
The AWPMD package will be removed from LAMMPS in Summer 2025 due to lack of
|
||||
maintenance and use of code constructs that conflict with modern C++ compilers
|
||||
and standards. Please contact developers@lammps.org if you have any concerns
|
||||
about this step.
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
action () {
|
||||
if (test $mode = 0) then
|
||||
rm -f ../$1
|
||||
|
||||
@ -9,6 +9,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the COLVARS package with the legacy build system using GNU
|
||||
make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
action () {
|
||||
if (test $mode = 0) then
|
||||
rm -f ../$1
|
||||
|
||||
@ -7,6 +7,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the COMPRESS package with the legacy build system using
|
||||
GNU make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
action () {
|
||||
|
||||
@ -11,6 +11,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the ELECTRODE package with the legacy build system using
|
||||
GNU make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
action () {
|
||||
|
||||
326
src/EXTRA-MOLECULE/angle_mwlc.cpp
Normal file
326
src/EXTRA-MOLECULE/angle_mwlc.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: James D. Farrell (IoP CAS) j.d.farrell at gmail.com
|
||||
[ based on angle_cosine.cpp ]
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "angle_mwlc.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "domain.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "math_const.h"
|
||||
#include "memory.h"
|
||||
#include "neighbor.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using MathConst::MY_PI;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleMWLC::AngleMWLC(LAMMPS *_lmp) : Angle(_lmp)
|
||||
{
|
||||
born_matrix_enable = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleMWLC::~AngleMWLC()
|
||||
{
|
||||
if (allocated && !copymode) {
|
||||
memory->destroy(setflag);
|
||||
memory->destroy(k1);
|
||||
memory->destroy(k2);
|
||||
memory->destroy(mu);
|
||||
memory->destroy(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleMWLC::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1, i2, i3, n, type;
|
||||
double delx1, dely1, delz1, delx2, dely2, delz2;
|
||||
double eangle, f1[3], f3[3];
|
||||
double rsq1, rsq2, r1, r2, c, a, a11, a12, a22;
|
||||
double q, qm, Q;
|
||||
|
||||
eangle = 0.0;
|
||||
ev_init(eflag, vflag);
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **anglelist = neighbor->anglelist;
|
||||
int nanglelist = neighbor->nanglelist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
double kbt, v_min;
|
||||
|
||||
for (n = 0; n < nanglelist; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
kbt = temp[type] * force->boltz;
|
||||
v_min = -kbt * log(1 + exp(-mu[type] / kbt));
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1 * delx1 + dely1 * dely1 + delz1 * delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2 * delx2 + dely2 * dely2 + delz2 * delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// c = cosine of angle
|
||||
|
||||
c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2;
|
||||
c /= r1 * r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
|
||||
q = exp(-k1[type] * (1.0 + c) / kbt);
|
||||
qm = exp((-k2[type] * (1.0 + c) - mu[type]) / kbt);
|
||||
Q = q + qm;
|
||||
|
||||
if (eflag) eangle = -kbt * log(Q) - v_min;
|
||||
|
||||
a = (k1[type] * q + k2[type] * qm) / Q;
|
||||
a11 = a * c / rsq1;
|
||||
a12 = -a / (r1 * r2);
|
||||
a22 = a * c / rsq2;
|
||||
|
||||
f1[0] = a11 * delx1 + a12 * delx2;
|
||||
f1[1] = a11 * dely1 + a12 * dely2;
|
||||
f1[2] = a11 * delz1 + a12 * delz2;
|
||||
f3[0] = a22 * delx2 + a12 * delx1;
|
||||
f3[1] = a22 * dely2 + a12 * dely1;
|
||||
f3[2] = a22 * delz2 + a12 * delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (evflag)
|
||||
ev_tally(i1, i2, i3, nlocal, newton_bond, eangle, f1, f3, delx1, dely1, delz1, delx2, dely2,
|
||||
delz2);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleMWLC::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
const int np1 = atom->nangletypes + 1;
|
||||
|
||||
memory->create(k1, np1, "angle:k1");
|
||||
memory->create(k2, np1, "angle:k2");
|
||||
memory->create(mu, np1, "angle:mu");
|
||||
memory->create(temp, np1, "angle:temp");
|
||||
memory->create(setflag, np1, "angle:setflag");
|
||||
for (int i = 1; i < np1; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleMWLC::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 5) error->all(FLERR, "Incorrect args for angle coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo, ihi;
|
||||
utils::bounds(FLERR, arg[0], 1, atom->nangletypes, ilo, ihi, error);
|
||||
|
||||
double k1_one = utils::numeric(FLERR, arg[1], false, lmp);
|
||||
double k2_one = utils::numeric(FLERR, arg[2], false, lmp);
|
||||
double mu_one = utils::numeric(FLERR, arg[3], false, lmp);
|
||||
double temp_one = utils::numeric(FLERR, arg[4], false, lmp);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k1[i] = k1_one;
|
||||
k2[i] = k2_one;
|
||||
mu[i] = mu_one;
|
||||
temp[i] = temp_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all(FLERR, "Incorrect args for angle coefficients");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleMWLC::equilibrium_angle(int /*i*/)
|
||||
{
|
||||
return MY_PI;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleMWLC::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k1[1], sizeof(double), atom->nangletypes, fp);
|
||||
fwrite(&k2[1], sizeof(double), atom->nangletypes, fp);
|
||||
fwrite(&mu[1], sizeof(double), atom->nangletypes, fp);
|
||||
fwrite(&temp[1], sizeof(double), atom->nangletypes, fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleMWLC::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
utils::sfread(FLERR, &k1[1], sizeof(double), atom->nangletypes, fp, nullptr, error);
|
||||
utils::sfread(FLERR, &k2[1], sizeof(double), atom->nangletypes, fp, nullptr, error);
|
||||
utils::sfread(FLERR, &mu[1], sizeof(double), atom->nangletypes, fp, nullptr, error);
|
||||
utils::sfread(FLERR, &temp[1], sizeof(double), atom->nangletypes, fp, nullptr, error);
|
||||
}
|
||||
MPI_Bcast(&k1[1], atom->nangletypes, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&k2[1], atom->nangletypes, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&mu[1], atom->nangletypes, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&temp[1], atom->nangletypes, MPI_DOUBLE, 0, world);
|
||||
|
||||
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to data file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleMWLC::write_data(FILE *fp)
|
||||
{
|
||||
for (int i = 1; i <= atom->nangletypes; i++)
|
||||
fprintf(fp, "%d %g %g %g %g\n", i, k1[i], k2[i], mu[i], temp[i]);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleMWLC::single(int type, int i1, int i2, int i3)
|
||||
{
|
||||
double **x = atom->x;
|
||||
|
||||
double kbt = temp[type] * force->boltz;
|
||||
double v_min = -kbt * log(1 + exp(-mu[type] / kbt));
|
||||
double delx1 = x[i1][0] - x[i2][0];
|
||||
double dely1 = x[i1][1] - x[i2][1];
|
||||
double delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(delx1, dely1, delz1);
|
||||
double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1);
|
||||
|
||||
double delx2 = x[i3][0] - x[i2][0];
|
||||
double dely2 = x[i3][1] - x[i2][1];
|
||||
double delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(delx2, dely2, delz2);
|
||||
double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2);
|
||||
|
||||
double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2;
|
||||
c /= r1 * r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
double q = exp(-k1[type] * (1.0 + c) / kbt);
|
||||
double qm = exp((-k2[type] * (1.0 + c) - mu[type]) / kbt);
|
||||
return -kbt * log(q + qm) - v_min;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleMWLC::born_matrix(int type, int i1, int i2, int i3, double &du, double &du2)
|
||||
{
|
||||
double **x = atom->x;
|
||||
double kbt = temp[type] * force->boltz;
|
||||
|
||||
double delx1 = x[i1][0] - x[i2][0];
|
||||
double dely1 = x[i1][1] - x[i2][1];
|
||||
double delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(delx1, dely1, delz1);
|
||||
|
||||
double delx2 = x[i3][0] - x[i2][0];
|
||||
double dely2 = x[i3][1] - x[i2][1];
|
||||
double delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(delx2, dely2, delz2);
|
||||
|
||||
double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2;
|
||||
c /= sqrt((delx1 * delx1 + dely1 * dely1 + delz1 * delz1) *
|
||||
(delx2 * delx2 + dely2 * dely2 + delz2 * delz2));
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
const double q = exp(-k1[type] * (1.0 + c) / kbt);
|
||||
const double qm = exp((-k2[type] * (1.0 + c) - mu[type]) / kbt);
|
||||
const double Q = q + qm;
|
||||
|
||||
du = (k1[type] * q + k2[type] * qm) / Q;
|
||||
du2 = (k1[type] - k2[type]) / Q;
|
||||
du2 *= -du2 * q * qm / kbt;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return ptr to internal members upon request
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
void *AngleMWLC::extract(const char *str, int &dim)
|
||||
{
|
||||
dim = 1;
|
||||
if (strcmp(str, "k1") == 0) return (void *) k1;
|
||||
if (strcmp(str, "k2") == 0) return (void *) k2;
|
||||
if (strcmp(str, "mu") == 0) return (void *) mu;
|
||||
if (strcmp(str, "temp") == 0) return (void *) temp;
|
||||
return nullptr;
|
||||
}
|
||||
53
src/EXTRA-MOLECULE/angle_mwlc.h
Normal file
53
src/EXTRA-MOLECULE/angle_mwlc.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
// clang-format off
|
||||
AngleStyle(mwlc,AngleMWLC);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_MWLC_H
|
||||
#define LMP_ANGLE_MWLC_H
|
||||
|
||||
#include "angle.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleMWLC : public Angle {
|
||||
public:
|
||||
AngleMWLC(class LAMMPS *);
|
||||
~AngleMWLC() override;
|
||||
void compute(int, int) override;
|
||||
void coeff(int, char **) override;
|
||||
double equilibrium_angle(int) override;
|
||||
void write_restart(FILE *) override;
|
||||
void read_restart(FILE *) override;
|
||||
void write_data(FILE *) override;
|
||||
double single(int, int, int, int) override;
|
||||
void born_matrix(int type, int i1, int i2, int i3, double &du, double &du2) override;
|
||||
void *extract(const char *, int &) override;
|
||||
|
||||
protected:
|
||||
double *k1;
|
||||
double *k2;
|
||||
double *mu;
|
||||
double *temp;
|
||||
|
||||
virtual void allocate();
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@ -7,6 +7,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the GPU package with the legacy build system using GNU
|
||||
make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
action () {
|
||||
|
||||
@ -7,6 +7,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the KOKKOS package with the legacy build system using GNU
|
||||
make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
action () {
|
||||
|
||||
@ -9,6 +9,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the LEPTON package with the legacy build system using GNU
|
||||
make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
action () {
|
||||
if (test $mode = 0) then
|
||||
rm -f ../$1
|
||||
|
||||
@ -7,12 +7,12 @@ SHELL = /bin/sh
|
||||
# specify flags and libraries needed for your compiler
|
||||
|
||||
CC = mpicxx
|
||||
CCFLAGS = -g -O3 -std=c++11
|
||||
CCFLAGS = -g -O3 # -std=c++17
|
||||
SHFLAGS = -fPIC
|
||||
DEPFLAGS = -M
|
||||
|
||||
LINK = mpicxx
|
||||
LINKFLAGS = -g -O3 -std=c++11
|
||||
LINKFLAGS = -g -O3 # -std=c++17
|
||||
LIB =
|
||||
SIZE = size
|
||||
|
||||
@ -28,7 +28,7 @@ SHLIBFLAGS = -shared -rdynamic
|
||||
# LAMMPS ifdef settings
|
||||
# see possible settings in Section 3.5 of the manual
|
||||
|
||||
LMP_INC = -DLAMMPS_GZIP -DLAMMPS_MEMALIGN=64 # -DLAMMPS_CXX98
|
||||
LMP_INC = -DLAMMPS_GZIP -DLAMMPS_MEMALIGN=64 # -DLAMMPS_CXX11
|
||||
|
||||
# MPI library
|
||||
# see discussion in Section 3.4 of the manual
|
||||
|
||||
@ -7,12 +7,12 @@ SHELL = /bin/sh
|
||||
# specify flags and libraries needed for your compiler
|
||||
|
||||
CC = g++
|
||||
CCFLAGS = -g -O3 -std=c++11
|
||||
CCFLAGS = -g -O3 # -std=c++17
|
||||
SHFLAGS = -fPIC
|
||||
DEPFLAGS = -M
|
||||
|
||||
LINK = g++
|
||||
LINKFLAGS = -g -O -std=c++11
|
||||
LINKFLAGS = -g -O # -std=c++17
|
||||
LIB =
|
||||
SIZE = size
|
||||
|
||||
@ -28,7 +28,7 @@ SHLIBFLAGS = -shared -rdynamic
|
||||
# LAMMPS ifdef settings
|
||||
# see possible settings in Section 3.5 of the manual
|
||||
|
||||
LMP_INC = -DLAMMPS_GZIP -DLAMMPS_MEMALIGN=64 # -DLAMMPS_CXX98
|
||||
LMP_INC = -DLAMMPS_GZIP -DLAMMPS_MEMALIGN=64 # -DLAMMPS_CXX11
|
||||
|
||||
# MPI library
|
||||
# see discussion in Section 3.4 of the manual
|
||||
|
||||
@ -438,7 +438,7 @@ void FixIPI::final_integrate()
|
||||
char header[MSGLEN+1];
|
||||
double vir[9], pot=0.0;
|
||||
double forceconv, potconv, posconv, pressconv, posconv3;
|
||||
char retstr[1024];
|
||||
char retstr[1024] = { '\0' };
|
||||
|
||||
// conversions from LAMMPS units to atomic units, which are used by i-PI
|
||||
potconv=3.1668152e-06/force->boltz;
|
||||
@ -488,7 +488,7 @@ void FixIPI::final_integrate()
|
||||
vir[1] = comp_p->vector[3]*pressconv*myvol;
|
||||
vir[2] = comp_p->vector[4]*pressconv*myvol;
|
||||
vir[5] = comp_p->vector[5]*pressconv*myvol;
|
||||
retstr[0]=0;
|
||||
retstr[0] = '\0';
|
||||
}
|
||||
|
||||
if (master) {
|
||||
@ -511,7 +511,8 @@ void FixIPI::final_integrate()
|
||||
writebuffer(ipisock,(char*) &nat,4, error);
|
||||
writebuffer(ipisock,(char*) buffer, bsize*8, error);
|
||||
writebuffer(ipisock,(char*) vir,9*8, error);
|
||||
nat=strlen(retstr); writebuffer(ipisock,(char*) &nat,4, error);
|
||||
nat=strlen(retstr);
|
||||
writebuffer(ipisock,(char*) &nat,4, error);
|
||||
writebuffer(ipisock,(char*) retstr, nat, error);
|
||||
}
|
||||
else
|
||||
|
||||
@ -7,6 +7,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the ML-POD package with the legacy build system using GNU
|
||||
make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
action () {
|
||||
|
||||
@ -639,8 +639,8 @@ void DumpNetCDFMPIIO::write()
|
||||
nme = count();
|
||||
int *block_sizes = new int[comm->nprocs];
|
||||
MPI_Allgather(&nme, 1, MPI_INT, block_sizes, 1, MPI_INT, world);
|
||||
blocki = 0;
|
||||
for (int i = 0; i < comm->me; i++) blocki += block_sizes[i];
|
||||
blocki = (MPI_Offset) 0;
|
||||
for (int i = 0; i < comm->me; i++) blocki += (MPI_Offset) (block_sizes[i]);
|
||||
delete[] block_sizes;
|
||||
|
||||
// ensure buf is sized for packing and communicating
|
||||
|
||||
@ -49,11 +49,11 @@ class DumpNetCDFMPIIO : public DumpCustom {
|
||||
int quantity; // type of the quantity
|
||||
};
|
||||
|
||||
int framei; // current frame index
|
||||
int blocki; // current block index
|
||||
MPI_Offset framei; // current frame index
|
||||
MPI_Offset blocki; // current block index
|
||||
int ndata; // number of data blocks to expect
|
||||
|
||||
bigint ntotalgr; // # of atoms
|
||||
MPI_Offset ntotalgr; // # of atoms
|
||||
|
||||
int n_perat; // # of netcdf per-atom properties
|
||||
nc_perat_t *perat; // per-atom properties
|
||||
|
||||
@ -7,6 +7,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the PLUMED package with the legacy build system using GNU
|
||||
make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
action () {
|
||||
|
||||
@ -9,6 +9,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
The POEMS package will be removed from LAMMPS in Summer 2025 due to lack of
|
||||
maintenance and use of code constructs that conflict with modern C++ compilers
|
||||
and standards. Please contact developers@lammps.org if you have any concerns
|
||||
about this step.
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
action () {
|
||||
if (test $mode = 0) then
|
||||
rm -f ../$1
|
||||
|
||||
@ -261,7 +261,8 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) :
|
||||
posflag = 1;
|
||||
posfreq = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
if (posfreq < nfreq || (posfreq % nfreq != 0))
|
||||
error->all(FLERR, "Incompatible fix reaxff/species postion frequency {}", posfreq);
|
||||
error->all(FLERR, "Incompatible fix reaxff/species position frequency {}",
|
||||
posfreq);
|
||||
|
||||
filepos = new char[255];
|
||||
strcpy(filepos, arg[iarg + 2]);
|
||||
|
||||
@ -7,6 +7,19 @@ mode=$1
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
cat <<EOF
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
|
||||
Support for building the VTK package with the legacy build system using GNU
|
||||
make will be removed in Summer 2025. Please switch to using CMake to build
|
||||
LAMMPS as soon as possible and report any problems to developers@lammps.org
|
||||
or post a bug report issue at https://github.com/lammps/lammps/issues
|
||||
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING-WARNING
|
||||
EOF
|
||||
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
action () {
|
||||
|
||||
@ -107,7 +107,7 @@ static constexpr int DELTA = 1048576;
|
||||
DumpVTK::DumpVTK(LAMMPS *lmp, int narg, char **arg) :
|
||||
DumpCustom(lmp, narg, arg)
|
||||
{
|
||||
if (narg == 5) error->all(FLERR,"No dump vtk arguments specified");
|
||||
if (narg < 6) utils::missing_cmd_args(FLERR,"dump vtk", error);
|
||||
|
||||
pack_choice.clear();
|
||||
vtype.clear();
|
||||
@ -214,17 +214,18 @@ void DumpVTK::init_style()
|
||||
// check that fix frequency is acceptable
|
||||
|
||||
for (int i = 0; i < ncompute; i++) {
|
||||
int icompute = modify->find_compute(id_compute[i]);
|
||||
if (icompute < 0) error->all(FLERR,"Could not find dump vtk compute ID");
|
||||
compute[i] = modify->compute[icompute];
|
||||
compute[i] = modify->get_compute_by_id(id_compute[i]);
|
||||
if (!compute[i]) error->all(FLERR,"Could not find dump vtk compute ID {}", id_compute[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < nfix; i++) {
|
||||
int ifix = modify->find_fix(id_fix[i]);
|
||||
if (ifix < 0) error->all(FLERR,"Could not find dump vtk fix ID");
|
||||
fix[i] = modify->fix[ifix];
|
||||
if (nevery % modify->fix[ifix]->peratom_freq)
|
||||
error->all(FLERR,"Dump vtk and fix not computed at compatible times");
|
||||
fix[i] = modify->get_fix_by_id(id_fix[i]);
|
||||
if (!fix[i]) {
|
||||
error->all(FLERR,"Could not find dump vtk fix ID {}", id_fix[i]);
|
||||
} else {
|
||||
if (nevery % fix[i]->peratom_freq)
|
||||
error->all(FLERR,"Dump vtk and fix ID {} not called at compatible times", id_fix[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nvariable; i++) {
|
||||
@ -359,8 +360,7 @@ int DumpVTK::count()
|
||||
nstride = 1;
|
||||
} else if (thresh_array[ithresh] == MOL) {
|
||||
if (!atom->molecule_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR, "Threshold for an atom property that isn't allocated");
|
||||
tagint *molecule = atom->molecule;
|
||||
for (i = 0; i < nlocal; i++) dchoose[i] = molecule[i];
|
||||
ptr = dchoose;
|
||||
@ -654,64 +654,54 @@ int DumpVTK::count()
|
||||
|
||||
} else if (thresh_array[ithresh] == RADIUS) {
|
||||
if (!atom->radius_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = atom->radius;
|
||||
nstride = 1;
|
||||
} else if (thresh_array[ithresh] == DIAMETER) {
|
||||
if (!atom->radius_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
double *radius = atom->radius;
|
||||
for (i = 0; i < nlocal; i++) dchoose[i] = 2.0*radius[i];
|
||||
ptr = dchoose;
|
||||
nstride = 1;
|
||||
} else if (thresh_array[ithresh] == OMEGAX) {
|
||||
if (!atom->omega_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = &atom->omega[0][0];
|
||||
nstride = 3;
|
||||
} else if (thresh_array[ithresh] == OMEGAY) {
|
||||
if (!atom->omega_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = &atom->omega[0][1];
|
||||
nstride = 3;
|
||||
} else if (thresh_array[ithresh] == OMEGAZ) {
|
||||
if (!atom->omega_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = &atom->omega[0][2];
|
||||
nstride = 3;
|
||||
} else if (thresh_array[ithresh] == ANGMOMX) {
|
||||
if (!atom->angmom_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = &atom->angmom[0][0];
|
||||
nstride = 3;
|
||||
} else if (thresh_array[ithresh] == ANGMOMY) {
|
||||
if (!atom->angmom_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = &atom->angmom[0][1];
|
||||
nstride = 3;
|
||||
} else if (thresh_array[ithresh] == ANGMOMZ) {
|
||||
if (!atom->angmom_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = &atom->angmom[0][2];
|
||||
nstride = 3;
|
||||
} else if (thresh_array[ithresh] == TQX) {
|
||||
if (!atom->torque_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = &atom->torque[0][0];
|
||||
nstride = 3;
|
||||
} else if (thresh_array[ithresh] == TQY) {
|
||||
if (!atom->torque_flag)
|
||||
error->all(FLERR,
|
||||
"Threshold for an atom property that isn't allocated");
|
||||
error->all(FLERR,"Threshold for an atom property that isn't allocated");
|
||||
ptr = &atom->torque[0][1];
|
||||
nstride = 3;
|
||||
} else if (thresh_array[ithresh] == TQZ) {
|
||||
@ -928,7 +918,7 @@ void DumpVTK::write()
|
||||
|
||||
if (nmax > maxbuf) {
|
||||
if ((bigint) nmax * size_one > MAXSMALLINT)
|
||||
error->all(FLERR,"Too much per-proc info for dump");
|
||||
error->all(FLERR,"Too much per processor data info for dump");
|
||||
maxbuf = nmax;
|
||||
memory->destroy(buf);
|
||||
memory->create(buf,maxbuf*size_one,"dump:buf");
|
||||
@ -983,9 +973,10 @@ void DumpVTK::write()
|
||||
void DumpVTK::pack(tagint *ids)
|
||||
{
|
||||
int n = 0;
|
||||
for (std::map<int,FnPtrPack>::iterator it=pack_choice.begin(); it!=pack_choice.end(); ++it, ++n) {
|
||||
current_pack_choice_key = it->first; // work-around for pack_compute, pack_fix, pack_variable
|
||||
(this->*(it->second))(n);
|
||||
for (auto &choice : pack_choice) {
|
||||
current_pack_choice_key = choice.first; // work-around for pack_compute, pack_fix, pack_variable
|
||||
(this->*(choice.second))(n);
|
||||
++n;
|
||||
}
|
||||
|
||||
if (ids) {
|
||||
@ -1108,10 +1099,10 @@ void DumpVTK::buf2arrays(int n, double *mybuf)
|
||||
pid[0] = points->InsertNextPoint(mybuf[iatom*size_one],mybuf[iatom*size_one+1],mybuf[iatom*size_one+2]);
|
||||
|
||||
int j=3; // 0,1,2 = x,y,z handled just above
|
||||
for (std::map<int, vtkSmartPointer<vtkAbstractArray> >::iterator it=myarrays.begin(); it!=myarrays.end(); ++it) {
|
||||
vtkAbstractArray *paa = it->second;
|
||||
if (it->second->GetNumberOfComponents() == 3) {
|
||||
switch (vtype[it->first]) {
|
||||
for (auto &it : myarrays) {
|
||||
vtkAbstractArray *paa = it.second;
|
||||
if (it.second->GetNumberOfComponents() == 3) {
|
||||
switch (vtype[it.first]) {
|
||||
case Dump::INT:
|
||||
{
|
||||
int iv3[3] = { static_cast<int>(mybuf[iatom*size_one+j ]),
|
||||
@ -1130,7 +1121,7 @@ void DumpVTK::buf2arrays(int n, double *mybuf)
|
||||
}
|
||||
j+=3;
|
||||
} else {
|
||||
switch (vtype[it->first]) {
|
||||
switch (vtype[it.first]) {
|
||||
case Dump::INT:
|
||||
{
|
||||
vtkIntArray *pia = static_cast<vtkIntArray*>(paa);
|
||||
@ -1317,8 +1308,8 @@ void DumpVTK::write_vtk(int n, double *mybuf)
|
||||
unstructuredGrid->SetPoints(points);
|
||||
unstructuredGrid->SetCells(VTK_VERTEX, pointsCells);
|
||||
|
||||
for (std::map<int, vtkSmartPointer<vtkAbstractArray> >::iterator it=myarrays.begin(); it!=myarrays.end(); ++it) {
|
||||
unstructuredGrid->GetPointData()->AddArray(it->second);
|
||||
for (const auto & it : myarrays) {
|
||||
unstructuredGrid->GetPointData()->AddArray(it.second);
|
||||
}
|
||||
|
||||
vtkSmartPointer<vtkUnstructuredGridWriter> writer = vtkSmartPointer<vtkUnstructuredGridWriter>::New();
|
||||
@ -1327,8 +1318,8 @@ void DumpVTK::write_vtk(int n, double *mybuf)
|
||||
polyData->SetPoints(points);
|
||||
polyData->SetVerts(pointsCells);
|
||||
|
||||
for (std::map<int, vtkSmartPointer<vtkAbstractArray> >::iterator it=myarrays.begin(); it!=myarrays.end(); ++it) {
|
||||
polyData->GetPointData()->AddArray(it->second);
|
||||
for (auto &it : myarrays) {
|
||||
polyData->GetPointData()->AddArray(it.second);
|
||||
}
|
||||
|
||||
vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New();
|
||||
@ -1384,8 +1375,8 @@ void DumpVTK::write_vtp(int n, double *mybuf)
|
||||
polyData->SetPoints(points);
|
||||
polyData->SetVerts(pointsCells);
|
||||
|
||||
for (std::map<int, vtkSmartPointer<vtkAbstractArray> >::iterator it=myarrays.begin(); it!=myarrays.end(); ++it) {
|
||||
polyData->GetPointData()->AddArray(it->second);
|
||||
for (auto &it : myarrays) {
|
||||
polyData->GetPointData()->AddArray(it.second);
|
||||
}
|
||||
|
||||
vtkSmartPointer<vtkXMLPolyDataWriter> writer = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
|
||||
@ -1448,8 +1439,8 @@ void DumpVTK::write_vtu(int n, double *mybuf)
|
||||
unstructuredGrid->SetPoints(points);
|
||||
unstructuredGrid->SetCells(VTK_VERTEX, pointsCells);
|
||||
|
||||
for (std::map<int, vtkSmartPointer<vtkAbstractArray> >::iterator it=myarrays.begin(); it!=myarrays.end(); ++it) {
|
||||
unstructuredGrid->GetPointData()->AddArray(it->second);
|
||||
for (auto &it : myarrays) {
|
||||
unstructuredGrid->GetPointData()->AddArray(it.second);
|
||||
}
|
||||
|
||||
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer = vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
|
||||
@ -1540,9 +1531,8 @@ int DumpVTK::parse_fields(int narg, char **arg)
|
||||
name[Z] = "z";
|
||||
|
||||
// customize by adding to if statement
|
||||
int i;
|
||||
for (int iarg = 5; iarg < narg; iarg++) {
|
||||
i = iarg-5;
|
||||
|
||||
for (int iarg = 0; iarg < narg; iarg++) {
|
||||
|
||||
if (strcmp(arg[iarg],"id") == 0) {
|
||||
pack_choice[ID] = &DumpVTK::pack_id;
|
||||
@ -1550,7 +1540,7 @@ int DumpVTK::parse_fields(int narg, char **arg)
|
||||
name[ID] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"mol") == 0) {
|
||||
if (!atom->molecule_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property 'mol' that isn't allocated");
|
||||
pack_choice[MOL] = &DumpVTK::pack_molecule;
|
||||
vtype[MOL] = Dump::INT;
|
||||
name[MOL] = arg[iarg];
|
||||
@ -1665,98 +1655,97 @@ int DumpVTK::parse_fields(int narg, char **arg)
|
||||
name[FZ] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"q") == 0) {
|
||||
if (!atom->q_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[Q] = &DumpVTK::pack_q;
|
||||
vtype[Q] = Dump::DOUBLE;
|
||||
name[Q] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"mux") == 0) {
|
||||
if (!atom->mu_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[MUX] = &DumpVTK::pack_mux;
|
||||
vtype[MUX] = Dump::DOUBLE;
|
||||
name[MUX] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"muy") == 0) {
|
||||
if (!atom->mu_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[MUY] = &DumpVTK::pack_muy;
|
||||
vtype[MUY] = Dump::DOUBLE;
|
||||
name[MUY] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"muz") == 0) {
|
||||
if (!atom->mu_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[MUZ] = &DumpVTK::pack_muz;
|
||||
vtype[MUZ] = Dump::DOUBLE;
|
||||
name[MUZ] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"mu") == 0) {
|
||||
if (!atom->mu_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[MU] = &DumpVTK::pack_mu;
|
||||
vtype[MU] = Dump::DOUBLE;
|
||||
name[MU] = arg[iarg];
|
||||
|
||||
} else if (strcmp(arg[iarg],"radius") == 0) {
|
||||
if (!atom->radius_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[RADIUS] = &DumpVTK::pack_radius;
|
||||
vtype[RADIUS] = Dump::DOUBLE;
|
||||
name[RADIUS] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"diameter") == 0) {
|
||||
if (!atom->radius_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[DIAMETER] = &DumpVTK::pack_diameter;
|
||||
vtype[DIAMETER] = Dump::DOUBLE;
|
||||
name[DIAMETER] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"omegax") == 0) {
|
||||
if (!atom->omega_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[OMEGAX] = &DumpVTK::pack_omegax;
|
||||
vtype[OMEGAX] = Dump::DOUBLE;
|
||||
name[OMEGAX] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"omegay") == 0) {
|
||||
if (!atom->omega_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[OMEGAY] = &DumpVTK::pack_omegay;
|
||||
vtype[OMEGAY] = Dump::DOUBLE;
|
||||
name[OMEGAY] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"omegaz") == 0) {
|
||||
if (!atom->omega_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[OMEGAZ] = &DumpVTK::pack_omegaz;
|
||||
vtype[OMEGAZ] = Dump::DOUBLE;
|
||||
name[OMEGAZ] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"angmomx") == 0) {
|
||||
if (!atom->angmom_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[ANGMOMX] = &DumpVTK::pack_angmomx;
|
||||
vtype[ANGMOMX] = Dump::DOUBLE;
|
||||
name[ANGMOMX] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"angmomy") == 0) {
|
||||
if (!atom->angmom_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[ANGMOMY] = &DumpVTK::pack_angmomy;
|
||||
vtype[ANGMOMY] = Dump::DOUBLE;
|
||||
name[ANGMOMY] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"angmomz") == 0) {
|
||||
if (!atom->angmom_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[ANGMOMZ] = &DumpVTK::pack_angmomz;
|
||||
vtype[ANGMOMZ] = Dump::DOUBLE;
|
||||
name[ANGMOMZ] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"tqx") == 0) {
|
||||
if (!atom->torque_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[TQX] = &DumpVTK::pack_tqx;
|
||||
vtype[TQX] = Dump::DOUBLE;
|
||||
name[TQX] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"tqy") == 0) {
|
||||
if (!atom->torque_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[TQY] = &DumpVTK::pack_tqy;
|
||||
vtype[TQY] = Dump::DOUBLE;
|
||||
name[TQY] = arg[iarg];
|
||||
} else if (strcmp(arg[iarg],"tqz") == 0) {
|
||||
if (!atom->torque_flag)
|
||||
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||
error->all(FLERR,"Dumping atom property '{}' that isn't allocated", arg[iarg]);
|
||||
pack_choice[TQZ] = &DumpVTK::pack_tqz;
|
||||
vtype[TQZ] = Dump::DOUBLE;
|
||||
name[TQZ] = arg[iarg];
|
||||
@ -1766,7 +1755,7 @@ int DumpVTK::parse_fields(int narg, char **arg)
|
||||
int n,flag,cols;
|
||||
ArgInfo argi(arg[iarg],ArgInfo::COMPUTE|ArgInfo::FIX|ArgInfo::VARIABLE
|
||||
|ArgInfo::DNAME|ArgInfo::INAME);
|
||||
argindex[ATTRIBUTES+i] = argi.get_index1();
|
||||
argindex[ATTRIBUTES+iarg] = argi.get_index1();
|
||||
auto aname = argi.get_name();
|
||||
|
||||
switch (argi.get_type()) {
|
||||
@ -1779,107 +1768,114 @@ int DumpVTK::parse_fields(int narg, char **arg)
|
||||
// if no trailing [], then arg is set to 0, else arg is int between []
|
||||
|
||||
case ArgInfo::COMPUTE:
|
||||
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_compute;
|
||||
vtype[ATTRIBUTES+i] = Dump::DOUBLE;
|
||||
{
|
||||
pack_choice[ATTRIBUTES+iarg] = &DumpVTK::pack_compute;
|
||||
vtype[ATTRIBUTES+iarg] = Dump::DOUBLE;
|
||||
|
||||
n = modify->find_compute(aname);
|
||||
if (n < 0) error->all(FLERR,"Could not find dump vtk compute ID: {}",aname);
|
||||
if (modify->compute[n]->peratom_flag == 0)
|
||||
error->all(FLERR,"Dump vtk compute {} does not compute per-atom info",aname);
|
||||
if (argi.get_dim() == 0 && modify->compute[n]->size_peratom_cols > 0)
|
||||
error->all(FLERR,"Dump vtk compute {} does not calculate per-atom vector",aname);
|
||||
if (argi.get_dim() > 0 && modify->compute[n]->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Dump vtk compute {} does not calculate per-atom array",aname);
|
||||
if (argi.get_dim() > 0 &&
|
||||
argi.get_index1() > modify->compute[n]->size_peratom_cols)
|
||||
error->all(FLERR,"Dump vtk compute {} vector is accessed out-of-range",aname);
|
||||
|
||||
field2index[ATTRIBUTES+i] = add_compute(aname);
|
||||
name[ATTRIBUTES+i] = arg[iarg];
|
||||
auto icompute = modify->get_compute_by_id(aname);
|
||||
if (!icompute) {
|
||||
error->all(FLERR,"Could not find dump vtk compute ID: {}",aname);
|
||||
} else {
|
||||
if (icompute->peratom_flag == 0)
|
||||
error->all(FLERR,"Dump vtk compute {} does not compute per-atom info",aname);
|
||||
if (argi.get_dim() == 0 && icompute->size_peratom_cols > 0)
|
||||
error->all(FLERR,"Dump vtk compute {} does not calculate per-atom vector",aname);
|
||||
if (argi.get_dim() > 0 && icompute->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Dump vtk compute {} does not calculate per-atom array",aname);
|
||||
if (argi.get_dim() > 0 && argi.get_index1() > icompute->size_peratom_cols)
|
||||
error->all(FLERR,"Dump vtk compute {} vector is accessed out-of-range",aname);
|
||||
field2index[ATTRIBUTES+iarg] = add_compute(aname);
|
||||
name[ATTRIBUTES+iarg] = arg[iarg];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// fix value = f_ID
|
||||
// if no trailing [], then arg is set to 0, else arg is between []
|
||||
|
||||
case ArgInfo::FIX:
|
||||
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_fix;
|
||||
vtype[ATTRIBUTES+i] = Dump::DOUBLE;
|
||||
{
|
||||
pack_choice[ATTRIBUTES+iarg] = &DumpVTK::pack_fix;
|
||||
vtype[ATTRIBUTES+iarg] = Dump::DOUBLE;
|
||||
|
||||
n = modify->find_fix(aname);
|
||||
if (n < 0) error->all(FLERR,"Could not find dump vtk fix ID: {}",aname);
|
||||
if (modify->fix[n]->peratom_flag == 0)
|
||||
error->all(FLERR,"Dump vtk fix {} does not compute per-atom info",aname);
|
||||
if (argi.get_dim() == 0 && modify->fix[n]->size_peratom_cols > 0)
|
||||
error->all(FLERR,"Dump vtk fix {} does not compute per-atom vector",aname);
|
||||
if (argi.get_dim() > 0 && modify->fix[n]->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Dump vtk fix {} does not compute per-atom array",aname);
|
||||
if (argi.get_dim() > 0 &&
|
||||
argi.get_index1() > modify->fix[n]->size_peratom_cols)
|
||||
error->all(FLERR,"Dump vtk fix {} vector is accessed out-of-range",aname);
|
||||
auto ifix = modify->get_fix_by_id(aname);
|
||||
if (!ifix) {
|
||||
error->all(FLERR,"Could not find dump vtk fix ID: {}",aname);
|
||||
} else {
|
||||
if (ifix->peratom_flag == 0)
|
||||
error->all(FLERR,"Dump vtk fix {} does not compute per-atom info",aname);
|
||||
if (argi.get_dim() == 0 && ifix->size_peratom_cols > 0)
|
||||
error->all(FLERR,"Dump vtk fix {} does not compute per-atom vector",aname);
|
||||
if (argi.get_dim() > 0 && ifix->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Dump vtk fix {} does not compute per-atom array",aname);
|
||||
if (argi.get_dim() > 0 && argi.get_index1() > ifix->size_peratom_cols)
|
||||
error->all(FLERR,"Dump vtk fix {} vector is accessed out-of-range",aname);
|
||||
|
||||
field2index[ATTRIBUTES+i] = add_fix(aname);
|
||||
name[ATTRIBUTES+i] = arg[iarg];
|
||||
field2index[ATTRIBUTES+iarg] = add_fix(aname);
|
||||
name[ATTRIBUTES+iarg] = arg[iarg];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// variable value = v_name
|
||||
|
||||
case ArgInfo::VARIABLE:
|
||||
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_variable;
|
||||
vtype[ATTRIBUTES+i] = Dump::DOUBLE;
|
||||
pack_choice[ATTRIBUTES+iarg] = &DumpVTK::pack_variable;
|
||||
vtype[ATTRIBUTES+iarg] = Dump::DOUBLE;
|
||||
|
||||
n = input->variable->find(aname);
|
||||
if (n < 0) error->all(FLERR,"Could not find dump vtk variable name {}",aname);
|
||||
if (input->variable->atomstyle(n) == 0)
|
||||
error->all(FLERR,"Dump vtk variable {} is not atom-style variable",aname);
|
||||
|
||||
field2index[ATTRIBUTES+i] = add_variable(aname);
|
||||
name[ATTRIBUTES+i] = arg[iarg];
|
||||
field2index[ATTRIBUTES+iarg] = add_variable(aname);
|
||||
name[ATTRIBUTES+iarg] = arg[iarg];
|
||||
break;
|
||||
|
||||
// custom per-atom floating point vector or array = d_ID d2_ID
|
||||
|
||||
case ArgInfo::DNAME:
|
||||
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom;
|
||||
vtype[ATTRIBUTES+i] = Dump::DOUBLE;
|
||||
pack_choice[ATTRIBUTES+iarg] = &DumpVTK::pack_custom;
|
||||
vtype[ATTRIBUTES+iarg] = Dump::DOUBLE;
|
||||
|
||||
n = atom->find_custom(aname,flag,cols);
|
||||
|
||||
if (n < 0)
|
||||
error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
|
||||
if (argindex[ATTRIBUTES+i] == 0) {
|
||||
if (argindex[ATTRIBUTES+iarg] == 0) {
|
||||
if (!flag || cols)
|
||||
error->all(FLERR,"Property double vector {} for dump vtk does not exist",aname);
|
||||
} else {
|
||||
if (!flag || !cols)
|
||||
error->all(FLERR,"Property double array {} for dump vtk does not exist",aname);
|
||||
if (argindex[ATTRIBUTES+i] > atom->dcols[n])
|
||||
if (argindex[ATTRIBUTES+iarg] > atom->dcols[n])
|
||||
error->all(FLERR,"Dump vtk property array {} is accessed out-of-range",aname);
|
||||
}
|
||||
field2index[ATTRIBUTES+i] = add_custom(aname,1);
|
||||
name[ATTRIBUTES+i] = arg[iarg];
|
||||
field2index[ATTRIBUTES+iarg] = add_custom(aname,1);
|
||||
name[ATTRIBUTES+iarg] = arg[iarg];
|
||||
break;
|
||||
|
||||
// custom per-atom integer vector or array = i_ID or i2_ID
|
||||
|
||||
case ArgInfo::INAME:
|
||||
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom;
|
||||
vtype[ATTRIBUTES+i] = Dump::INT;
|
||||
pack_choice[ATTRIBUTES+iarg] = &DumpVTK::pack_custom;
|
||||
vtype[ATTRIBUTES+iarg] = Dump::INT;
|
||||
|
||||
n = atom->find_custom(aname,flag,cols);
|
||||
|
||||
if (n < 0)
|
||||
error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
|
||||
if (argindex[ATTRIBUTES+i] == 0) {
|
||||
if (argindex[ATTRIBUTES+iarg] == 0) {
|
||||
if (flag || cols)
|
||||
error->all(FLERR,"Property integer vector {} for dump vtk does not exist",aname);
|
||||
} else {
|
||||
if (flag || !cols)
|
||||
error->all(FLERR,"Property integer array {} for dump vtk does not exist",aname);
|
||||
if (argindex[ATTRIBUTES+i] > atom->icols[n])
|
||||
if (argindex[ATTRIBUTES+iarg] > atom->icols[n])
|
||||
error->all(FLERR,"Dump vtk property array {} is accessed out-of-range",aname);
|
||||
}
|
||||
field2index[ATTRIBUTES+i] = add_custom(aname,0);
|
||||
name[ATTRIBUTES+i] = arg[iarg];
|
||||
field2index[ATTRIBUTES+iarg] = add_custom(aname,0);
|
||||
name[ATTRIBUTES+iarg] = arg[iarg];
|
||||
break;
|
||||
|
||||
// no match
|
||||
@ -2232,42 +2228,50 @@ int DumpVTK::modify_param(int narg, char **arg)
|
||||
// if no trailing [], then arg is set to 0, else arg is between []
|
||||
|
||||
case ArgInfo::COMPUTE:
|
||||
{
|
||||
thresh_array[nthresh] = COMPUTE;
|
||||
n = modify->find_compute(aname);
|
||||
if (n < 0) error->all(FLERR,"Could not find dump modify compute ID: {}",aname);
|
||||
auto icompute = modify->get_compute_by_id(aname);
|
||||
if (!icompute) {
|
||||
error->all(FLERR,"Could not find dump modify compute ID: {}",aname);
|
||||
} else {
|
||||
if (modify->compute[n]->peratom_flag == 0)
|
||||
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom info",aname);
|
||||
if (argi.get_dim() == 0 && icompute->size_peratom_cols > 0)
|
||||
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom vector",aname);
|
||||
if (argi.get_index1() > 0 && icompute->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom array",aname);
|
||||
if (argi.get_index1() > 0 &&
|
||||
argi.get_index1() > icompute->size_peratom_cols)
|
||||
error->all(FLERR,"Dump modify compute ID {} vector is not large enough",aname);
|
||||
|
||||
if (modify->compute[n]->peratom_flag == 0)
|
||||
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom info",aname);
|
||||
if (argi.get_dim() == 0 && modify->compute[n]->size_peratom_cols > 0)
|
||||
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom vector",aname);
|
||||
if (argi.get_index1() > 0 && modify->compute[n]->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom array",aname);
|
||||
if (argi.get_index1() > 0 &&
|
||||
argi.get_index1() > modify->compute[n]->size_peratom_cols)
|
||||
error->all(FLERR,"Dump modify compute ID {} vector is not large enough",aname);
|
||||
|
||||
field2index[ATTRIBUTES+nfield+nthresh] = add_compute(aname);
|
||||
field2index[ATTRIBUTES+nfield+nthresh] = add_compute(aname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// fix value = f_ID
|
||||
// if no trailing [], then arg is set to 0, else arg is between []
|
||||
|
||||
case ArgInfo::FIX:
|
||||
{
|
||||
thresh_array[nthresh] = FIX;
|
||||
n = modify->find_fix(aname);
|
||||
if (n < 0) error->all(FLERR,"Could not find dump modify fix ID: {}",aname);
|
||||
auto ifix = modify->get_fix_by_id(aname);
|
||||
if (!ifix) {
|
||||
error->all(FLERR,"Could not find dump modify fix ID: {}",aname);
|
||||
} else {
|
||||
if (ifix->peratom_flag == 0)
|
||||
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom info",aname);
|
||||
if (argi.get_dim() == 0 && ifix->size_peratom_cols > 0)
|
||||
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom vector",aname);
|
||||
if (argi.get_index1() > 0 && ifix->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom array",aname);
|
||||
if (argi.get_index1() > 0 && argi.get_index1() > ifix->size_peratom_cols)
|
||||
error->all(FLERR,"Dump modify fix ID {} vector is not large enough",aname);
|
||||
|
||||
if (modify->fix[n]->peratom_flag == 0)
|
||||
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom info",aname);
|
||||
if (argi.get_dim() == 0 && modify->fix[n]->size_peratom_cols > 0)
|
||||
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom vector",aname);
|
||||
if (argi.get_index1() > 0 && modify->fix[n]->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom array",aname);
|
||||
if (argi.get_index1() > 0 && argi.get_index1() > modify->fix[n]->size_peratom_cols)
|
||||
error->all(FLERR,"Dump modify fix ID {} vector is not large enough",aname);
|
||||
|
||||
field2index[ATTRIBUTES+nfield+nthresh] = add_fix(aname);
|
||||
field2index[ATTRIBUTES+nfield+nthresh] = add_fix(aname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// variable value = v_ID
|
||||
|
||||
|
||||
@ -34,6 +34,13 @@
|
||||
#error LAMMPS requires a C++11 (or later) compliant compiler. Enable C++11 compatibility or upgrade the compiler.
|
||||
#endif
|
||||
|
||||
// C++17 check
|
||||
#ifndef LAMMPS_CXX11
|
||||
#if __cplusplus < 201703L
|
||||
#error LAMMPS is planning to transition to requiring C++17. To disable this error please use a C++17 compliant compiler, enable C++17 support, or define -DLAMMPS_CXX11 in your makefile or when running cmake
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
|
||||
@ -55,30 +55,31 @@ index 0000000..b4f0fe6
|
||||
+ TYPE DOC
|
||||
+ PERMISSIONS OWNER_READ GROUP_READ WORLD_READ
|
||||
+)
|
||||
diff --git a/wham/wham.c b/wham/wham.c
|
||||
index 487871b..526908e 100644
|
||||
--- a/wham/wham.c
|
||||
+++ b/wham/wham.c
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "wham.h"
|
||||
diff --git a/wham-2d/wham-2d.c b/wham-2d/wham-2d.c
|
||||
index fb6e059..2c5594f 100644
|
||||
--- a/wham-2d/wham-2d.c
|
||||
+++ b/wham-2d/wham-2d.c
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <time.h>
|
||||
#include "wham-2d.h"
|
||||
|
||||
|
||||
-#define COMMAND_LINE "Command line: wham [P|Ppi|Pval] hist_min hist_max num_bins tol temperature numpad metadatafile freefile [num_MC_trials randSeed]\n"
|
||||
+#define COMMAND_LINE "Command line: wham [P|Ppi|Pval] [units <real|metal|lj|...>] hist_min hist_max num_bins tol temperature numpad metadatafile freefile [num_MC_trials randSeed]\n"
|
||||
|
||||
double HIST_MAX,HIST_MIN,BIN_WIDTH,TOL;
|
||||
double *HISTOGRAM;
|
||||
@@ -29,6 +29,7 @@ double kT;
|
||||
int NUM_BINS;
|
||||
int PERIODIC;
|
||||
double PERIOD;
|
||||
-#define COMMAND_LINE "Command line: wham-2d Px[=0|pi|val] hist_min_x hist_max_x num_bins_x Py[=0|pi|val] hist_min_y hist_max_y num_bins_y tol temperature numpad metadatafile freefile use_mask\n"
|
||||
+#define COMMAND_LINE "Command line: wham-2d [units <real|metal|lj|...>] Px[=0|pi|val] hist_min_x hist_max_x num_bins_x Py[=0|pi|val] hist_min_y hist_max_y num_bins_y tol temperature numpad metadatafile freefile use_mask\n"
|
||||
double HIST_MAXx,HIST_MINx,BIN_WIDTHx;
|
||||
double HIST_MAXy,HIST_MINy,BIN_WIDTHy;
|
||||
double TOL;
|
||||
@@ -35,7 +35,7 @@ int NUM_BINSx, NUM_BINSy;
|
||||
int PERIODICx, PERIODICy;
|
||||
double PERIODx, PERIODy;
|
||||
double *data1,**num,***bias;
|
||||
-
|
||||
+double k_B = k_B_DEFAULT;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@@ -117,6 +118,61 @@ else
|
||||
PERIODIC = 0;
|
||||
@@ -76,6 +76,61 @@ for (i=0; i<argc; i++)
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
+// set k_B according to LAMMPS units settings
|
||||
+if (strcmp(argv[1],"units") == 0)
|
||||
@ -135,9 +136,116 @@ index 487871b..526908e 100644
|
||||
+ argv += 2;
|
||||
+ }
|
||||
+
|
||||
// Parse command line arguments
|
||||
if (argc != 9 && argc !=11)
|
||||
PERIODICx = parse_periodic(argv[1], &PERIODx);
|
||||
if (PERIODICx)
|
||||
{
|
||||
diff --git a/wham-2d/wham-2d.h b/wham-2d/wham-2d.h
|
||||
index b17e4bd..5fc17ff 100644
|
||||
--- a/wham-2d/wham-2d.h
|
||||
+++ b/wham-2d/wham-2d.h
|
||||
@@ -20,15 +20,15 @@ extern int NUM_BINSy;
|
||||
|
||||
extern int PERIODICx,PERIODICy; // flags to turn on periodicity
|
||||
extern double PERIODx, PERIODy; // flags to control periodic interval
|
||||
+extern double k_B;
|
||||
|
||||
// A couple of predefined periodic units
|
||||
#define DEGREES 360.0
|
||||
#define RADIANS 6.28318530717959
|
||||
|
||||
-#define k_B 0.001982923700 // Boltzmann's constant in kcal/mol K
|
||||
-//#define k_B 0.0083144621 // Boltzmann's constant kJ/mol-K
|
||||
-//#define k_B 1.0 // Boltzmann's constant in reduced units
|
||||
-
|
||||
+#define k_B_DEFAULT 0.001982923700 // Boltzmann's constant in kcal/mol K
|
||||
+//#define k_B_DEFAULT 0.0083144621 // Boltzmann's constant kJ/mol-K
|
||||
+//#define k_B_DEFAULT 1.0 // Boltzmann's constant in reduced units
|
||||
|
||||
|
||||
// Value inserted for the free energy of masked values
|
||||
diff --git a/wham/wham.c b/wham/wham.c
|
||||
index 487871b..1496eed 100644
|
||||
--- a/wham/wham.c
|
||||
+++ b/wham/wham.c
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "wham.h"
|
||||
|
||||
|
||||
-#define COMMAND_LINE "Command line: wham [P|Ppi|Pval] hist_min hist_max num_bins tol temperature numpad metadatafile freefile [num_MC_trials randSeed]\n"
|
||||
+#define COMMAND_LINE "Command line: wham [units <real|metal|lj|...>] [P|Ppi|Pval] hist_min hist_max num_bins tol temperature numpad metadatafile freefile [num_MC_trials randSeed]\n"
|
||||
|
||||
double HIST_MAX,HIST_MIN,BIN_WIDTH,TOL;
|
||||
double *HISTOGRAM;
|
||||
@@ -29,6 +29,7 @@ double kT;
|
||||
int NUM_BINS;
|
||||
int PERIODIC;
|
||||
double PERIOD;
|
||||
+double k_B = k_B_DEFAULT;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@@ -82,6 +83,61 @@ for (i=0; i<argc; i++)
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
+// set k_B according to LAMMPS units settings
|
||||
+if (strcmp(argv[1],"units") == 0)
|
||||
+ {
|
||||
+ if (argc < 3)
|
||||
+ {
|
||||
+ printf( COMMAND_LINE );
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(argv[2], "lj") == 0)
|
||||
+ {
|
||||
+ k_B = 1.0;
|
||||
+ }
|
||||
+ else if (strcmp(argv[2], "real") == 0)
|
||||
+ {
|
||||
+ k_B = 0.0019872067;
|
||||
+ }
|
||||
+ else if (strcmp(argv[2], "metal") == 0)
|
||||
+ {
|
||||
+ k_B = 8.617343e-5;
|
||||
+ }
|
||||
+ else if (strcmp(argv[2], "si") == 0)
|
||||
+ {
|
||||
+ k_B = 1.3806504e-23;
|
||||
+ }
|
||||
+ else if (strcmp(argv[2], "cgs") == 0)
|
||||
+ {
|
||||
+ k_B = 1.3806504e-16;
|
||||
+ }
|
||||
+ else if (strcmp(argv[2], "electron") == 0)
|
||||
+ {
|
||||
+ k_B = 3.16681534e-6;
|
||||
+ }
|
||||
+ else if (strcmp(argv[2], "micro") == 0)
|
||||
+ {
|
||||
+ k_B = 1.3806504e-8;
|
||||
+ }
|
||||
+ else if (strcmp(argv[2], "nano") == 0)
|
||||
+ {
|
||||
+ k_B = 0.013806504;
|
||||
+ }
|
||||
+ else if (strcmp(argv[2], "default") == 0)
|
||||
+ {
|
||||
+ k_B = k_B_DEFAULT;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ printf("Unknown unit style: %s\n%s", argv[2], COMMAND_LINE);
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+ printf("# Setting value of k_B to = %.15g\n", k_B);
|
||||
+ argc -= 2;
|
||||
+ argv += 2;
|
||||
+ }
|
||||
+
|
||||
if (toupper(argv[1][0]) == 'P')
|
||||
{
|
||||
PERIODIC = 1;
|
||||
diff --git a/wham/wham.h b/wham/wham.h
|
||||
index aacc1e8..7d509f2 100644
|
||||
--- a/wham/wham.h
|
||||
|
||||
89
unittest/force-styles/tests/angle-mwlc.yaml
Normal file
89
unittest/force-styles/tests/angle-mwlc.yaml
Normal file
@ -0,0 +1,89 @@
|
||||
---
|
||||
lammps_version: 19 Nov 2024
|
||||
tags: generated
|
||||
date_generated: Fri Jan 10 13:54:41 2025
|
||||
epsilon: 2.5e-13
|
||||
skip_tests:
|
||||
prerequisites: ! |
|
||||
atom full
|
||||
angle mwlc
|
||||
pre_commands: ! ""
|
||||
post_commands: ! ""
|
||||
input_file: in.fourmol
|
||||
angle_style: mwlc
|
||||
angle_coeff: ! |
|
||||
* 6.0 0.6 15.0 300.0
|
||||
equilibrium: 4 3.141592653589793 3.141592653589793 3.141592653589793 3.141592653589793
|
||||
extract: ! |
|
||||
k1 1
|
||||
k2 1
|
||||
mu 1
|
||||
temp 1
|
||||
natoms: 29
|
||||
init_energy: 115.97311255470154
|
||||
init_stress: ! |2-
|
||||
1.0785144954758131e+01 -5.1561329771224154e+00 -5.6290119776357184e+00 1.7509753155291005e+01 8.4620050528315804e+00 5.4460179571966592e+00
|
||||
init_forces: ! |2
|
||||
1 2.0049292277552344e+00 -3.4967838538707023e+00 -7.7679149207041780e+00
|
||||
2 5.2379550897725657e-01 4.2410446627574743e+00 3.4103186723411198e+00
|
||||
3 -2.6364713466403744e+00 1.7646356480410195e+00 6.7422761915790446e+00
|
||||
4 5.9780828166032607e-01 -1.0977711474862293e+00 -1.2762851805838284e+00
|
||||
5 2.7519993963547762e-02 -1.3655215729181727e+00 -4.0557483263144212e-01
|
||||
6 -1.4407532935169898e-01 -1.5931923885520087e+00 -1.8663167177332292e+00
|
||||
7 -4.1794796128320089e-01 4.1379756743889873e-01 -9.9274508603132139e-02
|
||||
8 8.6885282425298183e-01 2.9273693794680500e-01 3.9875384936490477e+00
|
||||
9 -7.4989162989673552e-01 1.9120936074864758e-02 1.6480002237326197e-01
|
||||
10 4.5851731938743301e+00 5.1383619725146579e-01 -7.8986229128522627e+00
|
||||
11 -1.3361238263371962e+00 -1.6154590769980759e+00 1.3132946273952864e+00
|
||||
12 -9.8353444089007258e-01 5.7660344986117273e-01 -1.6760444984003993e+00
|
||||
13 4.8213326840430115e-02 7.5476102608997231e-02 9.7662630040726750e-01
|
||||
14 1.7020627463903515e-01 -4.9418713351985666e-02 -6.9510195676192543e-02
|
||||
15 5.7466130382222369e-01 -3.0791486600816609e-01 9.0601148952989252e-01
|
||||
16 -5.6604535775268596e+00 5.0708111379184277e+00 1.7013150451815964e+00
|
||||
17 2.5273381761407760e+00 -3.4420010207137852e+00 1.8573629247281453e+00
|
||||
18 2.0828420935010161e-01 2.1765636018344789e+00 -8.8331994782253780e+00
|
||||
19 -2.5502877667816710e+00 -3.1771408888391202e+00 3.7828819753880119e+00
|
||||
20 2.3420035574315694e+00 1.0005772870046410e+00 5.0503175028373661e+00
|
||||
21 2.2520112617177057e+00 2.8191460010961373e+00 -8.4251146760580085e+00
|
||||
22 -4.0101778142198494e+00 -2.7341370977288624e+00 2.9783951433938527e+00
|
||||
23 1.7581665525021437e+00 -8.5008903367275068e-02 5.4467195326641562e+00
|
||||
24 -1.9792115156439898e+00 7.6933124498060685e+00 -4.5803031378051688e+00
|
||||
25 -1.5876110942732853e+00 -5.3190980720841390e+00 8.6990568523236744e-01
|
||||
26 3.5668226099172751e+00 -2.3742143777219300e+00 3.7103974525728014e+00
|
||||
27 -1.0535801895693373e+00 8.6490680045193269e+00 -2.9461596365031912e+00
|
||||
28 -2.3037157984215133e+00 -5.1714048596555164e+00 1.2013129729191907e-01
|
||||
29 3.3572959879908506e+00 -3.4776631448638109e+00 2.8260283392112724e+00
|
||||
run_energy: 115.88929660500146
|
||||
run_stress: ! |2-
|
||||
1.0741962021125900e+01 -5.1494210571452070e+00 -5.5925409639806976e+00 1.7499135911989786e+01 8.4401379697723158e+00 5.4365488644723161e+00
|
||||
run_forces: ! |2
|
||||
1 2.0024084967323734e+00 -3.4852712888973301e+00 -7.7681384109278948e+00
|
||||
2 5.1802520314744682e-01 4.2290273746409701e+00 3.4156643023763298e+00
|
||||
3 -2.6176139409651311e+00 1.7481727755506558e+00 6.7276571726932186e+00
|
||||
4 5.9646423832275675e-01 -1.0896302596160039e+00 -1.2658946496090273e+00
|
||||
5 2.0626395368878558e-02 -1.3553597325783064e+00 -4.0428709993242351e-01
|
||||
6 -1.5043849290340794e-01 -1.6020934387436645e+00 -1.8709909377854954e+00
|
||||
7 -4.1644858135120844e-01 4.1712949378864117e-01 -1.0014611176127630e-01
|
||||
8 8.7761514222742898e-01 2.9932822072179732e-01 3.9914298835888857e+00
|
||||
9 -7.5185528312840066e-01 1.9244616790871305e-02 1.6542886887136499e-01
|
||||
10 4.5736254271229742e+00 4.9828467262363496e-01 -7.8986022120685373e+00
|
||||
11 -1.3323136450232624e+00 -1.6103729207690813e+00 1.3097303435864336e+00
|
||||
12 -1.0040757700004965e+00 5.7836875530999343e-01 -1.6448472694236678e+00
|
||||
13 4.8392108795294986e-02 7.7447222505411639e-02 9.6494421976551426e-01
|
||||
14 1.8086042252760026e-01 -5.1422366669672037e-02 -7.3717779732260791e-02
|
||||
15 5.8324025586810402e-01 -3.0468600966273196e-01 8.9577956208287191e-01
|
||||
16 -5.6548207755179911e+00 5.0752603376691656e+00 1.6979261789431477e+00
|
||||
17 2.5263087987770385e+00 -3.4434274526643489e+00 1.8580639393328193e+00
|
||||
18 2.1733330742608858e-01 2.1830182266117371e+00 -8.8242777257965024e+00
|
||||
19 -2.5415995943828809e+00 -3.1730376716173803e+00 3.7883421709467422e+00
|
||||
20 2.3242662869567923e+00 9.9001944500564321e-01 5.0359355548497611e+00
|
||||
21 2.2580025853773256e+00 2.8068061574356138e+00 -8.4373139893370634e+00
|
||||
22 -4.0070465500208554e+00 -2.7223210888728504e+00 2.9888102357206301e+00
|
||||
23 1.7490439646435296e+00 -8.4485068562763388e-02 5.4485037536164329e+00
|
||||
24 -1.9860712475490458e+00 7.7098710540424751e+00 -4.5855114458364374e+00
|
||||
25 -1.5787959452376497e+00 -5.3290411597315357e+00 8.7215941857315382e-01
|
||||
26 3.5648671927866955e+00 -2.3808298943109389e+00 3.7133520272632836e+00
|
||||
27 -1.0631738916816893e+00 8.6588340987013801e+00 -2.9324082303496679e+00
|
||||
28 -2.2973201808293515e+00 -5.1771902142248960e+00 1.1264225202087563e-01
|
||||
29 3.3604940725110408e+00 -3.4816438844764841e+00 2.8197659783287921e+00
|
||||
...
|
||||
@ -105,6 +105,11 @@ if(Python_EXECUTABLE)
|
||||
set_tests_properties(PythonPyLammps PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
|
||||
endif()
|
||||
|
||||
add_test(NAME PythonCmdWrapper
|
||||
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-cmdwrapper.py -v
|
||||
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
|
||||
set_tests_properties(PythonCmdWrapper PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
|
||||
|
||||
add_test(NAME PythonFormats
|
||||
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-formats.py -v
|
||||
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
|
||||
|
||||
97
unittest/python/python-cmdwrapper.py
Normal file
97
unittest/python/python-cmdwrapper.py
Normal file
@ -0,0 +1,97 @@
|
||||
import os,unittest
|
||||
from lammps import lammps
|
||||
|
||||
try:
|
||||
import numpy
|
||||
NUMPY_INSTALLED = True
|
||||
except ImportError:
|
||||
NUMPY_INSTALLED = False
|
||||
|
||||
@unittest.skipIf(not NUMPY_INSTALLED, "numpy is not available")
|
||||
class PythonCmdWrapper(unittest.TestCase):
|
||||
def setUp(self):
|
||||
machine = None
|
||||
if 'LAMMPS_MACHINE_NAME' in os.environ:
|
||||
machine=os.environ['LAMMPS_MACHINE_NAME']
|
||||
self.lmp = lammps(name=machine, cmdargs=['-nocite', '-log','none', '-echo', 'screen'])
|
||||
self.lmp.cmd.units("lj")
|
||||
self.lmp.cmd.atom_style("atomic")
|
||||
self.lmp.cmd.atom_modify("map array")
|
||||
|
||||
if 'LAMMPS_CMAKE_CACHE' in os.environ:
|
||||
self.cmake_cache = {}
|
||||
|
||||
with open(os.environ['LAMMPS_CMAKE_CACHE'], 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#') or line.startswith('//'): continue
|
||||
parts = line.split('=')
|
||||
key, value_type = parts[0].split(':')
|
||||
if len(parts) > 1:
|
||||
value = parts[1]
|
||||
if value_type == "BOOL":
|
||||
value = (value.upper() == "ON")
|
||||
else:
|
||||
value = None
|
||||
self.cmake_cache[key] = value
|
||||
|
||||
def tearDown(self):
|
||||
self.lmp.close()
|
||||
del self.lmp
|
||||
|
||||
def test_version(self):
|
||||
self.assertGreaterEqual(self.lmp.version(), 20200824)
|
||||
|
||||
def test_create_atoms(self):
|
||||
self.lmp.cmd.region("box block", 0, 2, 0, 2, 0, 2)
|
||||
self.lmp.cmd.create_box(1, "box")
|
||||
|
||||
x = [
|
||||
1.0, 1.0, 1.0,
|
||||
1.0, 1.0, 1.5
|
||||
]
|
||||
|
||||
types = [1, 1]
|
||||
|
||||
self.assertEqual(self.lmp.create_atoms(2, id=None, type=types, x=x), 2)
|
||||
self.assertEqual(self.lmp.extract_global("natoms"), 2)
|
||||
pos = self.lmp.numpy.extract_atom("x")
|
||||
self.assertEqual(pos.shape[0], 2)
|
||||
numpy.testing.assert_array_equal(pos[0], tuple(x[0:3]))
|
||||
numpy.testing.assert_array_equal(pos[1], tuple(x[3:6]))
|
||||
|
||||
def test_thermo_capture(self):
|
||||
self.lmp.cmd.lattice("fcc", 0.8442),
|
||||
self.lmp.cmd.region("box block", 0, 4, 0, 4, 0, 4)
|
||||
self.lmp.cmd.create_box(1, "box")
|
||||
self.lmp.cmd.create_atoms(1, "box")
|
||||
self.lmp.cmd.mass(1, 1.0)
|
||||
self.lmp.cmd.velocity("all create", 1.44, 87287, "loop geom")
|
||||
self.lmp.cmd.pair_style("lj/cut", 2.5)
|
||||
self.lmp.cmd.pair_coeff(1, 1, 1.0, 1.0, 2.5)
|
||||
self.lmp.cmd.neighbor(0.3, "bin")
|
||||
self.lmp.cmd.neigh_modify("delay 0 every 20 check no")
|
||||
self.lmp.cmd.fix("1 all nve")
|
||||
|
||||
current_run = {}
|
||||
|
||||
def append_thermo_data(lmp):
|
||||
for k, v in lmp.last_thermo().items():
|
||||
current_run.setdefault(k, []).append(v)
|
||||
|
||||
# thermo data is only captured during a run if PYTHON package is enabled
|
||||
# without it, it will only capture the final thermo at completion
|
||||
nvalues = 1
|
||||
if self.lmp.has_package("PYTHON"):
|
||||
self.lmp.cmd.fix("myfix", "all", "python/invoke", 10, "end_of_step", append_thermo_data)
|
||||
nvalues = 2
|
||||
|
||||
self.lmp.cmd.run(10)
|
||||
append_thermo_data(self.lmp)
|
||||
|
||||
for k in ('Step', 'Temp', 'E_pair', 'E_mol', 'TotEng', 'Press'):
|
||||
self.assertIn(k, current_run)
|
||||
self.assertEqual(len(current_run[k]), nvalues)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user