Merge branch 'develop' into patch-2

This commit is contained in:
Evangelos Voyiatzis
2025-02-15 17:15:33 +01:00
committed by GitHub
70 changed files with 2090 additions and 507 deletions

View File

@ -28,14 +28,14 @@ Create a 'next\_release' branch off 'develop' and make the following changes:
..versionadded:: or ..versionchanged:: are missing and need to be ..versionadded:: or ..versionchanged:: are missing and need to be
added added
Submit this pull request, rebase if needed. This is the last pull Submit this pull request. This is the last pull request merged for the
request merged for the release and should not contain any other release and should not contain any other changes. (Exceptions: this
changes. (Exceptions: this document, last minute trivial(!) changes). document, last minute trivial(!) changes).
This PR shall not be merged before **all** pending tests have completed This PR shall not be merged before **all** pending tests have completed
and cleared. We currently use a mix of automated tests running on and cleared. We currently use a mix of automated tests running on
either Temple's Jenkins cluster or GitHub workflows. Those include time either Temple's Jenkins cluster or GitHub workflows. Those include time
consuming tests not run on pull requests. If needed, a bugfix pull consuming tests not run on pull requests. If needed, a bug-fix pull
request should be created and merged to clear all tests. request should be created and merged to clear all tests.
### Create release on GitHub ### Create release on GitHub
@ -56,7 +56,7 @@ git pull
git checkout release git checkout release
git pull git pull
git merge --ff-only develop git merge --ff-only develop
git tag -s -m "LAMMPS feature release 19 November 2024" patch_19Nov2024 git tag -s -m "LAMMPS feature release 4 February 2025" patch_4Feb2025
git push git@github.com:lammps/lammps.git --tags develop release git push git@github.com:lammps/lammps.git --tags develop release
``` ```
@ -77,7 +77,7 @@ release page with a summary of all the changes included and references
to the pull requests they were merged from or check the existing draft to the pull requests they were merged from or check the existing draft
for any necessary changes from pull requests that were merged but are for any necessary changes from pull requests that were merged but are
not listed. Then select the applied tag for the release in the "Choose not listed. Then select the applied tag for the release in the "Choose
a tag" dropdown list. Go to the bottom of the list and select the "Set a tag" drop-down list. Go to the bottom of the list and select the "Set
as pre-release" checkbox. The "Set as the latest release" button is as pre-release" checkbox. The "Set as the latest release" button is
reserved for stable releases and updates to them. reserved for stable releases and updates to them.
@ -87,12 +87,18 @@ you can return to edit the release page and publish it.
### Prepare pre-compiled packages, update packages to GitHub ### Prepare pre-compiled packages, update packages to GitHub
Build a fully static LAMMPS installation using a musl-libc
cross-compiler, install into a lammps-static folder, and create a
tarball called lammps-linux-x86_64-19Nov2024.tar.gz (or using a
corresponding date with a future release) from the lammps-static folder.
A suitable build environment is provided with the A suitable build environment is provided with the
https://download.lammps.org/static/fedora37_musl.sif container image. https://download.lammps.org/static/fedora41_musl_mingw.sif container
image. The corresponding container build definition file is maintained
in the tools/singularity folder of the LAMMPS source distribution.
#### Fully portable static Linux x86_64 non-MPI binaries
The following commands use the Fedora container to build a fully static
LAMMPS installation using a musl-libc cross-compiler, install it into a
`lammps-static` folder, and create a tarball called
`lammps-linux-x86_64-4Feb2025.tar.gz` (or using a corresponding date
with a future release) from the `lammps-static` folder.
``` sh ``` sh
rm -rf release-packages rm -rf release-packages
@ -105,49 +111,173 @@ cmake -S lammps-release/cmake -B build-release -G Ninja -D CMAKE_INSTALL_PREFIX=
cmake --build build-release --target all cmake --build build-release --target all
cmake --build build-release --target install cmake --build build-release --target install
/usr/musl/bin/x86_64-linux-musl-strip lammps-static/bin/* /usr/musl/bin/x86_64-linux-musl-strip lammps-static/bin/*
tar -czvvf lammps-linux-x86_64-19Nov2024.tar.gz lammps-static tar -czvvf ../lammps-linux-x86_64-4Feb2025.tar.gz lammps-static
exit # fedora 41 container exit # fedora 41 container
cd ..
``` ```
The resulting tar archive can be uploaded to the GitHub release page with: The resulting tar archive can be uploaded to the GitHub release page with:
``` ``` sh
gh release upload patch_19Nov2024 lammps-linux-x86_64-19Nov2024.tar.gz gh release upload patch_4Feb2025 lammps-linux-x86_64-4Feb2025.tar.gz
``` ```
#### Linux x86_64 Flatpak bundle with GUI included
Make sure you have the `flatpak` and `flatpak-builder` packages Make sure you have the `flatpak` and `flatpak-builder` packages
installed locally (they cannot be used from the container) and build a installed locally (they require binaries that run with elevated
privileges and thus cannot be used from the container) and build a
LAMMPS and LAMMPS-GUI flatpak bundle in the `release-packages` folder LAMMPS and LAMMPS-GUI flatpak bundle in the `release-packages` folder
with: with:
``` sh ``` sh
cd release-packages
flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak-builder --force-clean --verbose --repo=$PWD/flatpak-repo --install-deps-from=flathub --state-dir=$PWD --user --ccache --default-branch=release flatpak-build lammps-release/tools/lammps-gui/org.lammps.lammps-gui.yml flatpak-builder --force-clean --verbose --repo=$PWD/flatpak-repo --install-deps-from=flathub --state-dir=$PWD --user --ccache --default-branch=release flatpak-build lammps-release/tools/lammps-gui/org.lammps.lammps-gui.yml
flatpak build-bundle --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo --verbose $PWD/flatpak-repo LAMMPS-Linux-x86_64-GUI-19Nov2024.flatpak org.lammps.lammps-gui release flatpak build-bundle --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo --verbose $PWD/flatpak-repo ../LAMMPS-Linux-x86_64-GUI-4Feb2025.flatpak org.lammps.lammps-gui release
cd ..
``` ```
The resulting flatpak bundle file can be uploaded to the GitHub release page with: The resulting flatpak bundle file can be uploaded to the GitHub release page with:
``` ``` sh
gh release upload patch_19Nov2024 LAMMPS-Linux-x86_64-GUI-19Nov2024.flatpak gh release upload patch_4Feb2025 LAMMPS-Linux-x86_64-GUI-4Feb2025.flatpak
``` ```
Also build serial executable packages that also include LAMMPS-GUI for #### LAMMPS Source tarball
Linux, macOS, and Windows, and upload them to the GitHub release.
Clean up: The container for the static binary can also be used to prepare the source
tarball including the HTML and PDF manual (this is currently done automatically
when the releases is created and the tarball uploaded to https://download.lammps.org/tars/).
The steps are as follows:
``` sh
cd release-packages
apptainer shell fedora41_musl_mingw.sif
cd lammps-release
rm -f ../release.tar*
git archive --output=../release.tar --prefix=lammps-4Feb2025/ HEAD
cd doc
make clean-all
make html pdf
tar -rf ../../release.tar --transform 's,^,lammps-4Feb2025/doc/,' html Manual.pdf
gzip -9v ../../release.tar
mv ../../release.tar.gz ../../lammps-src-4Feb2025.tar.gz
exit # fedora41 container
cd ..
```
The resulting source tarball can be uploaded to the GitHub release page with:
``` sh
gh release upload patch_4Feb2025 lammps-src-4Feb2025.tar.gz
```
#### Build Windows Installer Packages with MinGW Linux-to-Windows Cross-compiler
The various Windows installer packages can also be built with
apptainer container image.
``` sh
cd release-packages
apptainer shell fedora41_musl_mingw.sif
git clone --depth 10 https://github.com/lammps/lammps-packages.git lammps-packages
cd lammps-packages/mingw-cross
ln -sf ../../lammps-release lammps
./buildall.sh release >& mk.log & less +F mk.log
```
The installer with the GUI included can be uploaded to the GitHub release page with:
``` sh
ln -sf LAMMPS-64bit-GUI-4Feb2025.exe LAMMPS-Win10-64bit-GUI-4Feb2025.exe
gh release upload patch_4Feb2025 LAMMPS-Win10-64bit-GUI-4Feb2025.exe
```
The symbolic link is used to have a consistent naming scheme for the packages
attached to the GitHub release page.
#### Clean up:
``` sh ``` sh
cd .. cd ..
rm -r release-packages rm -r release-packages
``` ```
TODO: #### Build Multi-arch App-bundle for macOS
- add detailed commands for building GUI packages on Ubuntu 20.04LTS (move to 22.04LTS?),
macOS, and Windows cross-compiler and upload to GitHub
- build all Windows cross-compiled installer packages using lammps-packages repo
### Update download website Building app-bundles for macOS is not as easily automated and portable
as some of the other steps. It requires a machine actually running
macOS. In that machine the Xcode compiler package needs to be
installed. This also includes tools for building and manipulating disk
images. This compiler supports building executables for both, the
x86_64 and the arm64 architectures. This requires building with CMake
and using the CMake settings:
``` sh
-D CMAKE_OSX_ARCHITECTURES=arm64;x86_64
-D CMAKE_OSX_DEPLOYMENT_TARGER=11.0
```
This will add the compiler flags `-arch arm64 -arch x86_64
-mmacosx-version-min=11.0` and thus produce object for both
architectures and support for macOS versions back to version 11 (aka Big
Sur). With these settings the following libraries should be compiled
and installed (e.g. to `$HOME/.local`) as static libraries only:
- libomp taken from the LLVM/Clang source distribution (to support OpenMP)
- jpeg
- zlib
- png
- Qt (for LAMMPS-GUI)
When configuring LAMMPS the `cmake/presets/clang.cmake` should be used
and as many packages as possible enabled. For LAMMPS-GUI, MPI should be
disabled with `-D BUILD_MPI=OFF` and LAMMPS-GUI enabled with
`-D BUILD_LAMMPS_GUI=ON`. If the CMake configuration is successful,
settings for building a macOS app-bundle are enabled and with `cmake
--build build --target dmg` extra steps will be executed that will build
a macOS application installer image under the name
`LAMMPS_GUI-macOS-multiarch-4Feb2025.dmg`
The application image can be uploaded to the GitHub release page with:
``` sh
ln -sf LAMMPS_GUI-macOS-multiarch-4Feb2025.dmg LAMMPS-macOS-multiarch-GUI-4Feb2025.dmg
gh release upload patch_4Feb2025 LAMMPS-macOS-multiarch-GUI-4Feb2025.dmg
```
The symbolic link is used to have a consistent naming scheme for the packages
attached to the GitHub release page.
We are currently building the application images on macOS 12 (aka Monterey).
#### Build Linux x86_64 binary tarball on Ubuntu 20.04LTS
While the flatpak Linux version uses portable runtime libraries provided
by the flatpak environment, we also build regular Linux executables that
use a wrapper script and matching shared libraries in a tarball. To be
compatible with many Linux distributions, one has to build this on a
very old Linux distribution, since most Linux system libraries are
usually backward compatible but not forward compatible. This is
currently done on an Ubuntu 20.04LTS system. Once LAMMPS moves to
require CMake 3.20 and C++17, we will have to move to Ubuntu 22.04LTS.
This installation (either on a real or a virtual machine) should have
the packages installed that are indicated in
`tools/singularity/ubuntu20.04.def` plus Qt version 5.x with development
headers, so that LAMMPS-GUI can be compiled.
Also the building of the binary tarball and setup of the bundled
libraries and wrapper scripts is automated and can executed with `cmake
--build build --target tgz`. This should produce a file
`LAMMPS_GUI-Linux-amd64-4Feb2025.tar.gz` which can be uploaded to the
GitHub release page with:
``` sh
ln -sf LAMMPS_GUI-Linux-amd64-4Feb2025.tar.gz LAMMPS-Linux-x86_64-GUI-4Feb2025.tar.gz
gh release upload patch_4Feb2025 LAMMPS-Linux-x86_64-GUI-4Feb2025.tar.gz
```
### Update download page on LAMMPS website
Check out the LAMMPS website repo Check out the LAMMPS website repo
https://github.com/lammps/lammps-website.git and edit the file https://github.com/lammps/lammps-website.git and edit the file
@ -156,7 +286,7 @@ html` and review `html/download.html` Then add and commit to git and
push the changes to GitHub. The Temple Jenkis cluster will push the changes to GitHub. The Temple Jenkis cluster will
automatically update https://www.lammps.org/download.html accordingly. automatically update https://www.lammps.org/download.html accordingly.
Notify Steve of the release so he can update `src/bug.txt` on the Also notify Steve of the release so he can update `src/bug.txt` on the
website from the available release notes. website from the available release notes.
## LAMMPS Stable Release ## LAMMPS Stable Release

View File

@ -77,7 +77,7 @@ jobs:
-D PKG_MDI=on \ -D PKG_MDI=on \
-D PKG_MANIFOLD=on \ -D PKG_MANIFOLD=on \
-D PKG_ML-PACE=on \ -D PKG_ML-PACE=on \
-D PKG_ML-RANN=off \ -D PKG_ML-RANN=on \
-D PKG_MOLFILE=on \ -D PKG_MOLFILE=on \
-D PKG_RHEO=on \ -D PKG_RHEO=on \
-D PKG_PTM=on \ -D PKG_PTM=on \

15
README
View File

@ -23,17 +23,20 @@ more information about the code and its uses.
The LAMMPS distribution includes the following files and directories: The LAMMPS distribution includes the following files and directories:
README this file README this file
LICENSE the GNU General Public License (GPL) LICENSE the GNU General Public License (GPLv2)
bench benchmark problems CITATION.cff Citation information for LAMMPS in CFF format
bench benchmark inputs
cmake CMake build files cmake CMake build files
doc documentation doc documentation
examples simple test problems examples example inputs for many LAMMPS commands
fortran Fortran wrapper for LAMMPS fortran Fortran 2003 module for LAMMPS
lib additional provided or external libraries lib additional provided or external libraries
potentials interatomic potential files potentials interatomic potential files
python Python wrappers for LAMMPS python Python module for LAMMPS
src source files src source files
tools pre- and post-processing tools tools pre- and post-processing tools
unittest test programs for use with CTest
.github Git and GitHub related files and tools
Point your browser at any of these files to get started: Point your browser at any of these files to get started:
@ -42,6 +45,8 @@ https://docs.lammps.org/Intro.html hi-level introduction
https://docs.lammps.org/Build.html how to build LAMMPS https://docs.lammps.org/Build.html how to build LAMMPS
https://docs.lammps.org/Run_head.html how to run LAMMPS https://docs.lammps.org/Run_head.html how to run LAMMPS
https://docs.lammps.org/Commands_all.html Table of available commands https://docs.lammps.org/Commands_all.html Table of available commands
https://docs.lammps.org/Howto.html Short tutorials and HowTo discussions
https://docs.lammps.org/Errors.html How to interpret and debug errors
https://docs.lammps.org/Library.html LAMMPS library interfaces https://docs.lammps.org/Library.html LAMMPS library interfaces
https://docs.lammps.org/Modify.html how to modify and extend LAMMPS https://docs.lammps.org/Modify.html how to modify and extend LAMMPS
https://docs.lammps.org/Developer.html LAMMPS developer info https://docs.lammps.org/Developer.html LAMMPS developer info

View File

@ -209,7 +209,7 @@ endif()
######################################################################## ########################################################################
# User input options # # User input options #
######################################################################## ########################################################################
# backward compatibility with CMake before 3.12 and older LAMMPS documentation # backward compatibility with older LAMMPS documentation
if (PYTHON_EXECUTABLE) if (PYTHON_EXECUTABLE)
set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}") set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
endif() endif()
@ -225,6 +225,12 @@ if(DEFINED ENV{VIRTUAL_ENV} AND NOT Python_EXECUTABLE)
" Setting Python interpreter to: ${Python_EXECUTABLE}") " Setting Python interpreter to: ${Python_EXECUTABLE}")
endif() endif()
find_package(Python COMPONENTS Interpreter QUIET)
# NOTE: RHEL 8.0 and Ubuntu 18.04LTS ship with Python 3.6, Python 3.8 was EOL in 2024
if(Python_VERSION VERSION_LESS 3.6)
message(FATAL_ERROR "LAMMPS requires Python 3.6 or later")
endif()
set(LAMMPS_MACHINE "" CACHE STRING "Suffix to append to lmp binary (WON'T enable any features automatically") set(LAMMPS_MACHINE "" CACHE STRING "Suffix to append to lmp binary (WON'T enable any features automatically")
mark_as_advanced(LAMMPS_MACHINE) mark_as_advanced(LAMMPS_MACHINE)
if(LAMMPS_MACHINE) if(LAMMPS_MACHINE)
@ -930,7 +936,7 @@ endif()
include(Testing) include(Testing)
include(CodeCoverage) include(CodeCoverage)
include(CodingStandard) include(CodingStandard)
find_package(ClangFormat 11.0) find_package(ClangFormat 11.0 QUIET)
if(ClangFormat_FOUND) if(ClangFormat_FOUND)
add_custom_target(format-src add_custom_target(format-src

View File

@ -1,11 +1,11 @@
# use default (or custom) Python executable, if version is sufficient # use default (or custom) Python executable.
if(Python_VERSION VERSION_GREATER_EQUAL 3.6) # Python version check is in main CMakeLists.txt file
if(Python_EXECUTABLE)
set(Python3_EXECUTABLE ${Python_EXECUTABLE}) set(Python3_EXECUTABLE ${Python_EXECUTABLE})
endif() endif()
find_package(Python3 COMPONENTS Interpreter) find_package(Python3 COMPONENTS Interpreter)
if(Python3_EXECUTABLE) if(Python3_EXECUTABLE)
if(Python3_VERSION VERSION_GREATER_EQUAL 3.6)
add_custom_target( add_custom_target(
check-whitespace check-whitespace
${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py . ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py .
@ -36,5 +36,4 @@ if(Python3_EXECUTABLE)
${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py -f . ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py -f .
WORKING_DIRECTORY ${LAMMPS_DIR} WORKING_DIRECTORY ${LAMMPS_DIR}
COMMENT "Fix permission errors") COMMENT "Fix permission errors")
endif()
endif() endif()

View File

@ -13,7 +13,7 @@ if(BUILD_DOC)
endif() endif()
find_package(Python3 REQUIRED COMPONENTS Interpreter) find_package(Python3 REQUIRED COMPONENTS Interpreter)
if(Python3_VERSION VERSION_LESS 3.8) if(Python3_VERSION VERSION_LESS 3.8)
message(FATAL_ERROR "Python 3.8 and up is required to build the HTML documentation") message(FATAL_ERROR "Python 3.8 and up is required to build the LAMMPS HTML documentation")
endif() endif()
set(VIRTUALENV ${Python3_EXECUTABLE} -m venv) set(VIRTUALENV ${Python3_EXECUTABLE} -m venv)
@ -65,8 +65,8 @@ if(BUILD_DOC)
find_package(Sphinx) find_package(Sphinx)
endif() endif()
set(MATHJAX_URL "https://github.com/mathjax/MathJax/archive/3.1.3.tar.gz" CACHE STRING "URL for MathJax tarball") set(MATHJAX_URL "https://github.com/mathjax/MathJax/archive/3.2.2.tar.gz" CACHE STRING "URL for MathJax tarball")
set(MATHJAX_MD5 "b81661c6e6ba06278e6ae37b30b0c492" CACHE STRING "MD5 checksum of MathJax tarball") set(MATHJAX_MD5 "08dd6ef33ca08870220d9aade2a62845" CACHE STRING "MD5 checksum of MathJax tarball")
mark_as_advanced(MATHJAX_URL) mark_as_advanced(MATHJAX_URL)
GetFallbackURL(MATHJAX_URL MATHJAX_FALLBACK) GetFallbackURL(MATHJAX_URL MATHJAX_FALLBACK)

View File

@ -34,8 +34,26 @@ if(MSVC)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS) add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif() endif()
# C++11 is required 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_STANDARD_REQUIRED ON)
# Need -restrict with Intel compilers # Need -restrict with Intel compilers

View File

@ -24,9 +24,7 @@ if(MLIAP_ENABLE_PYTHON)
if(NOT PKG_PYTHON) if(NOT PKG_PYTHON)
message(FATAL_ERROR "Must enable PYTHON package for including Python support in ML-IAP") message(FATAL_ERROR "Must enable PYTHON package for including Python support in ML-IAP")
endif() endif()
if(Python_VERSION VERSION_LESS 3.6) # Python version check is in main CMakeLists.txt file
message(FATAL_ERROR "Python support in ML-IAP requires Python 3.6 or later")
endif()
set(MLIAP_BINARY_DIR ${CMAKE_BINARY_DIR}/cython) set(MLIAP_BINARY_DIR ${CMAKE_BINARY_DIR}/cython)
file(GLOB MLIAP_CYTHON_SRC CONFIGURE_DEPENDS ${LAMMPS_SOURCE_DIR}/ML-IAP/*.pyx) file(GLOB MLIAP_CYTHON_SRC CONFIGURE_DEPENDS ${LAMMPS_SOURCE_DIR}/ML-IAP/*.pyx)

View File

@ -37,7 +37,7 @@ if(DOWNLOAD_QUIP)
endforeach() endforeach()
# Fix cmake crashing when MATH_LINKOPTS not set, required for e.g. recent Cray Programming Environment # Fix cmake crashing when MATH_LINKOPTS not set, required for e.g. recent Cray Programming Environment
set(temp "${temp} -L/_DUMMY_PATH_\n") set(temp "${temp} -L/_DUMMY_PATH_\n")
set(temp "${temp}PYTHON=python\nPIP=pip\nEXTRA_LINKOPTS=\n") set(temp "${temp}PYTHON=${Python_EXECUTABLE}\nPIP=pip\nEXTRA_LINKOPTS=\n")
set(temp "${temp}HAVE_CP2K=0\nHAVE_VASP=0\nHAVE_TB=0\nHAVE_PRECON=1\nHAVE_LOTF=0\nHAVE_ONIOM=0\n") set(temp "${temp}HAVE_CP2K=0\nHAVE_VASP=0\nHAVE_TB=0\nHAVE_PRECON=1\nHAVE_LOTF=0\nHAVE_ONIOM=0\n")
set(temp "${temp}HAVE_LOCAL_E_MIX=0\nHAVE_QC=0\nHAVE_GAP=1\nHAVE_DESCRIPTORS_NONCOMMERCIAL=1\n") set(temp "${temp}HAVE_LOCAL_E_MIX=0\nHAVE_QC=0\nHAVE_GAP=1\nHAVE_DESCRIPTORS_NONCOMMERCIAL=1\n")
set(temp "${temp}HAVE_TURBOGAP=0\nHAVE_QR=1\nHAVE_THIRDPARTY=0\nHAVE_FX=0\nHAVE_SCME=0\nHAVE_MTP=0\n") set(temp "${temp}HAVE_TURBOGAP=0\nHAVE_QR=1\nHAVE_THIRDPARTY=0\nHAVE_FX=0\nHAVE_SCME=0\nHAVE_MTP=0\n")

View File

@ -40,6 +40,13 @@ mark_as_advanced(PLUMED_URL)
mark_as_advanced(PLUMED_MD5) mark_as_advanced(PLUMED_MD5)
GetFallbackURL(PLUMED_URL PLUMED_FALLBACK) GetFallbackURL(PLUMED_URL PLUMED_FALLBACK)
# adjust C++ standard support for self-compiled Plumed2
if(CMAKE_CXX_STANDARD GREATER 11)
set(PLUMED_CXX_STANDARD 14)
else()
set(PLUMED_CXX_STANDARD 11)
endif()
if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND (CMAKE_CROSSCOMPILING)) if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND (CMAKE_CROSSCOMPILING))
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set(CROSS_CONFIGURE mingw64-configure) set(CROSS_CONFIGURE mingw64-configure)
@ -55,7 +62,7 @@ if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND (CMAKE_CROSSCOMPILING))
URL_MD5 ${PLUMED_MD5} URL_MD5 ${PLUMED_MD5}
BUILD_IN_SOURCE 1 BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ${CROSS_CONFIGURE} --disable-shared --disable-bsymbolic CONFIGURE_COMMAND ${CROSS_CONFIGURE} --disable-shared --disable-bsymbolic
--disable-python --enable-cxx=11 --disable-python --enable-cxx=${PLUMED_CXX_STANDARD}
--enable-modules=-adjmat:+crystallization:-dimred:+drr:+eds:-fisst:+funnel:+logmfd:+manyrestraints:+maze:+opes:+multicolvar:-pamm:-piv:+s2cm:-sasa:-ves --enable-modules=-adjmat:+crystallization:-dimred:+drr:+eds:-fisst:+funnel:+logmfd:+manyrestraints:+maze:+opes:+multicolvar:-pamm:-piv:+s2cm:-sasa:-ves
${PLUMED_CONFIG_OMP} ${PLUMED_CONFIG_OMP}
${PLUMED_CONFIG_MPI} ${PLUMED_CONFIG_MPI}
@ -142,7 +149,7 @@ else()
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
${CONFIGURE_REQUEST_PIC} ${CONFIGURE_REQUEST_PIC}
--enable-modules=all --enable-modules=all
--enable-cxx=11 --enable-cxx=${PLUMED_CXX_STANDARD}
--disable-python --disable-python
${PLUMED_CONFIG_MPI} ${PLUMED_CONFIG_MPI}
${PLUMED_CONFIG_OMP} ${PLUMED_CONFIG_OMP}

View File

@ -1,6 +1,6 @@
if(NOT Python_INTERPRETER) if(NOT Python_INTERPRETER)
# backward compatibility with CMake before 3.12 and older LAMMPS documentation # backward compatibility with older LAMMPS documentation
if(PYTHON_EXECUTABLE) if(PYTHON_EXECUTABLE)
set(Python_EXECUTABLE ${PYTHON_EXECUTABLE}) set(Python_EXECUTABLE ${PYTHON_EXECUTABLE})
endif() endif()

View File

@ -22,12 +22,12 @@ doxygen-warn.log logfile with warnings from running doxygen
and: and:
github-development-workflow.md notes on the LAMMPS development workflow github-development-workflow.md notes on the LAMMPS development workflow
include-file-conventions.md notes on LAMMPS' include file conventions
documentation_conventions.md notes on writing documentation for LAMMPS documentation_conventions.md notes on writing documentation for LAMMPS
If you downloaded a LAMMPS tarball from www.lammps.org, then the html If you downloaded a LAMMPS tarball from www.lammps.org, then the html
folder and the PDF manual should be included. If you downloaded LAMMPS folder and the PDF manual should be included. If you downloaded LAMMPS
from GitHub then you either need to build them. using GitHub then you either need to build them yourself or read the
online version at https://docs.lammps.org/
You can build the HTML and PDF files yourself, by typing "make html" You can build the HTML and PDF files yourself, by typing "make html"
or by "make pdf", respectively. This requires various tools and files. or by "make pdf", respectively. This requires various tools and files.
@ -39,10 +39,10 @@ environment and local folders.
Installing prerequisites for the documentation build Installing prerequisites for the documentation build
To run the HTML documention build toolchain, python 3.x, doxygen, git, To run the HTML documention build toolchain, python 3.8 or later,
and the venv python module have to be installed if not already available. doxygen 1.8.10 or later, git, and the venv python module have to be
Also internet access is initially required to download external files installed if not already available. Also internet access is initially
and tools. required to download external files and tools.
Building the PDF format manual requires in addition a compatible LaTeX Building the PDF format manual requires in addition a compatible LaTeX
installation with support for PDFLaTeX and several add-on LaTeX packages installation with support for PDFLaTeX and several add-on LaTeX packages
@ -52,16 +52,24 @@ installed. This includes:
- babel - babel
- capt-of - capt-of
- cmap - cmap
- dvipng
- ellipse
- fncychap - fncychap
- fontawesom
- framed - framed
- geometry - geometry
- gyre
- hyperref - hyperref
- hypcap - hypcap
- needspace - needspace
- pict2e
- times - times
- tabulary - tabulary
- titlesec
- upquote - upquote
- wrapfig - wrapfig
- xindy
Also the latexmk script is required to run PDFLaTeX and related tools. Also the latexmk script is required to run PDFLaTeX and related tools.
the required number of times to have self-consistent output and include the required number of times to have self-consistent output and include
updated bibliography and indices. updated bibliography and indices.

View File

@ -14,6 +14,29 @@ As an alternative, you can download a package with pre-built executables
or automated build trees, as described in the :doc:`Install <Install>` or automated build trees, as described in the :doc:`Install <Install>`
section of the manual. section of the manual.
Prerequisites
-------------
Which software you need to compile and use LAMMPS strongly depends on
which :doc:`features and settings <Build_settings>` and which
:doc:`optional packages <Packages_list>` you are trying to include.
Common to all is that you need a C++ and C compiler, where the C++
compiler has to support at least the C++11 standard (note that some
compilers require command-line flag to activate C++11 support).
Furthermore, if you are building with CMake, you need at least CMake
version 3.20 and a compatible build tool (make or ninja-build); if you
are building the the legacy GNU make based build system you need GNU
make (other make variants are not going to work since the build system
uses features unique to GNU make) and a Unix-like build environment with
a Bourne shell, and shell tools like "sed", "grep", "touch", "test",
"tr", "cp", "mv", "rm", "ln", "diff" and so on. Parts of LAMMPS
interface with or use Python version 3.6 or later.
The LAMMPS developers aim to keep LAMMPS very portable and usable -
at least in parts - on most operating systems commonly used for
running MD simulations. Please see the :doc:`section on portablility
<Intro_portability>` for more details.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1

View File

@ -52,9 +52,9 @@ software or for people that want to modify or extend LAMMPS.
compilers can be configured and built concurrently from the same compilers can be configured and built concurrently from the same
source tree. source tree.
- Simplified packaging of LAMMPS for Linux distributions, environment - Simplified packaging of LAMMPS for Linux distributions, environment
modules, or automated build tools like `Homebrew <https://brew.sh/>`_. modules, or automated build tools like `Spack <https://spack.io>`_
- Integration of automated unit and regression testing (the LAMMPS side or `Homebrew <https://brew.sh/>`_.
of this is still under active development). - Integration of automated unit and regression testing.
.. _cmake_build: .. _cmake_build:

View File

@ -1139,11 +1139,10 @@ POEMS package
PYTHON package PYTHON package
--------------------------- ---------------------------
Building with the PYTHON package requires you have a the Python development Building with the PYTHON package requires you have a the Python
headers and library available on your system, which needs to be a Python 2.7 development headers and library available on your system, which
version or a Python 3.x version. Since support for Python 2.x has ended, needs to be Python version 3.6 or later. See ``lib/python/README``
using Python 3.x is strongly recommended. See ``lib/python/README`` for for additional details.
additional details.
.. tabs:: .. tabs::
@ -1159,7 +1158,7 @@ additional details.
set the Python_EXECUTABLE variable to specify which Python set the Python_EXECUTABLE variable to specify which Python
interpreter should be used. Note note that you will also need to interpreter should be used. Note note that you will also need to
have the development headers installed for this version, have the development headers installed for this version,
e.g. python2-devel. e.g. python3-devel.
.. tab:: Traditional make .. tab:: Traditional make

View File

@ -30,9 +30,9 @@ additional tools to be available and functioning.
* A Bourne shell compatible "Unix" shell program (frequently this is ``bash``) * A Bourne shell compatible "Unix" shell program (frequently this is ``bash``)
* A few shell utilities: ``ls``, ``mv``, ``ln``, ``rm``, ``grep``, ``sed``, ``tr``, ``cat``, ``touch``, ``diff``, ``dirname`` * A few shell utilities: ``ls``, ``mv``, ``ln``, ``rm``, ``grep``, ``sed``, ``tr``, ``cat``, ``touch``, ``diff``, ``dirname``
* Python (optional, required for ``make lib-<pkg>`` in the ``src`` * Python (optional, required for ``make lib-<pkg>`` in the ``src``
folder). Python scripts are currently tested with python 2.7 and folder). Python scripts are currently tested with 3.6 to 3.11.
3.6 to 3.11. The procedure for :doc:`building the documentation The procedure for :doc:`building the documentation <Build_manual>`
<Build_manual>` *requires* Python 3.5 or later. *requires* Python 3.8 or later.
Getting started Getting started
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^

View File

@ -116,9 +116,9 @@ environment variable.
Prerequisites for HTML Prerequisites for HTML
---------------------- ----------------------
To run the HTML documentation build toolchain, python 3, git, doxygen, To run the HTML documentation build toolchain, Python 3.8 or later, git,
and virtualenv have to be installed locally. Here are instructions for doxygen, and virtualenv have to be installed locally. Here are
common setups: instructions for common setups:
.. tabs:: .. tabs::
@ -128,13 +128,7 @@ common setups:
sudo apt-get install git doxygen sudo apt-get install git doxygen
.. tab:: RHEL or CentOS (Version 7.x) .. tab:: Fedora or RHEL/AlmaLinux/RockyLinux (8.x or later)
.. code-block:: bash
sudo yum install git doxygen
.. tab:: Fedora or RHEL/CentOS (8.x or later)
.. code-block:: bash .. code-block:: bash
@ -154,7 +148,36 @@ Prerequisites for PDF
In addition to the tools needed for building the HTML format manual, In addition to the tools needed for building the HTML format manual,
a working LaTeX installation with support for PDFLaTeX and a selection a working LaTeX installation with support for PDFLaTeX and a selection
of LaTeX styles/packages are required. To run the PDFLaTeX translation of LaTeX styles/packages are required. Apart from LaTeX packages that
are usually installed by default, the following packages are required:
.. table_from_list::
:columns: 11
- amsmath
- anysize
- babel
- capt-of
- cmap
- dvipng
- ellipse
- fncychap
- fontawesome
- framed
- geometry
- gyre
- hyperref
- hypcap
- needspace
- pict2e
- times
- tabulary
- titlesec
- upquote
- wrapfig
- xindy
To run the PDFLaTeX translation
the ``latexmk`` script needs to be installed as well. the ``latexmk`` script needs to be installed as well.
Prerequisites for ePUB and MOBI Prerequisites for ePUB and MOBI

View File

@ -8,7 +8,7 @@ Optional build settings
LAMMPS can be built with several optional settings. Each subsection LAMMPS can be built with several optional settings. Each subsection
explains how to do this for building both with CMake and make. explains how to do this for building both with CMake and make.
* `C++11 standard compliance`_ when building all of LAMMPS * `C++11 and C++17 standard compliance`_ when building all of LAMMPS
* `FFT library`_ for use with the :doc:`kspace_style pppm <kspace_style>` command * `FFT library`_ for use with the :doc:`kspace_style pppm <kspace_style>` command
* `Size of LAMMPS integer types and size limits`_ * `Size of LAMMPS integer types and size limits`_
* `Read or write compressed files`_ * `Read or write compressed files`_
@ -23,14 +23,15 @@ explains how to do this for building both with CMake and make.
.. _cxx11: .. _cxx11:
C++11 standard compliance C++11 and C++17 standard compliance
------------------------- -----------------------------------
A C++11 standard compatible compiler is a requirement for compiling LAMMPS. A C++11 standard compatible compiler is currently the minimum
LAMMPS version 3 March 2020 is the last version compatible with the previous requirement for compiling LAMMPS. LAMMPS version 3 March 2020 is the
C++98 standard for the core code and most packages. Most currently used last version compatible with the previous C++98 standard for the core
C++ compilers are compatible with C++11, but some older ones may need extra code and most packages. Most currently used C++ compilers are compatible
flags to enable C++11 compliance. Example for GNU c++ 4.8.x: with C++11, but some older ones may need extra flags to enable C++11
compliance. Example for GNU c++ 4.8.x:
.. code-block:: make .. code-block:: make
@ -40,6 +41,17 @@ Individual packages may require compliance with a later C++ standard
like C++14 or C++17. These requirements will be documented with the like C++14 or C++17. These requirements will be documented with the
:doc:`individual packages <Packages_details>`. :doc:`individual packages <Packages_details>`.
.. versionchanged:: 4Feb2025
Starting with LAMMPS version 4 February 2025 we are starting a
transition to require the C++17 standard. Most current compilers are
compatible and if the C++17 standard is available by default, LAMMPS
will enable C++17 and will compile normally. If the chosen compiler is
not compatible with C++17, but only supports C++11, then the define
-DLAMMPS_CXX11 is required to fall back to compiling with a C++11
compiler. After the next stable release of LAMMPS in summer 2025, the
LAMMPS development branch and future releases will require C++17.
---------- ----------
.. _fft: .. _fft:

View File

@ -140,6 +140,7 @@ additional letter in parenthesis: k = KOKKOS.
* :doc:`plugin <plugin>` * :doc:`plugin <plugin>`
* :doc:`prd <prd>` * :doc:`prd <prd>`
* :doc:`python <python>` * :doc:`python <python>`
* :doc:`region2vmd <region2vmd>`
* :doc:`tad <tad>` * :doc:`tad <tad>`
* :doc:`temper <temper>` * :doc:`temper <temper>`
* :doc:`temper/grem <temper_grem>` * :doc:`temper/grem <temper_grem>`

View File

@ -13,10 +13,14 @@ Programming language standards
Most of the C++ code currently requires a compiler compatible with the Most of the C++ code currently requires a compiler compatible with the
C++11 standard, the KOKKOS package currently requires C++17. Most of C++11 standard, the KOKKOS package currently requires C++17. Most of
the Python code is written to be compatible with Python 3.5 or later or the Python code is written to be compatible with Python 3.6 or later.
Python 2.7. Some Python scripts *require* Python 3 and a few others
still need to be ported from Python 2 to Python 3.
.. deprecated:: TBD
Python 2.x is no longer supported and trying to use it, e.g. for the
LAMMPS Python module should result in an error. If you come across
some part of the LAMMPS distribution that is not (yet) compatible with
Python 3, please notify the LAMMPS developers.
Build systems Build systems
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@ -24,8 +28,8 @@ Build systems
LAMMPS can be compiled from source code using a (traditional) build LAMMPS can be compiled from source code using a (traditional) build
system based on shell scripts, a few shell utilities (grep, sed, cat, system based on shell scripts, a few shell utilities (grep, sed, cat,
tr) and the GNU make program. This requires running within a Bourne tr) and the GNU make program. This requires running within a Bourne
shell (``/bin/sh``). Alternatively, a build system with different back ends shell (``/bin/sh``). Alternatively, a build system with different back
can be created using CMake. CMake must be at least version 3.16. ends can be created using CMake. CMake must be at least version 3.16.
Operating systems Operating systems
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^

View File

@ -189,10 +189,8 @@ of the contribution. As of January 2023, all previously included
Fortran code for the LAMMPS executable has been replaced by equivalent Fortran code for the LAMMPS executable has been replaced by equivalent
C++ code. C++ code.
Python code must be compatible with Python 3.5 and later. Large parts Python code currently must be compatible with Python 3.6. If a later
of LAMMPS (including the :ref:`PYTHON package <PKG-PYTHON>`) are also version or Python is required, it needs to be documented.
compatible with Python 2.7. Compatibility with Python 2.7 is desirable,
but compatibility with Python 3.5 is **required**.
Compatibility with older programming language standards is very Compatibility with older programming language standards is very
important to maintain portability and availability of LAMMPS on many important to maintain portability and availability of LAMMPS on many

View File

@ -2428,7 +2428,7 @@ ways to use LAMMPS and Python together.
Building with the PYTHON package assumes you have a Python development Building with the PYTHON package assumes you have a Python development
environment (headers and libraries) available on your system, which needs environment (headers and libraries) available on your system, which needs
to be either Python version 2.7 or Python 3.5 and later. to be Python version 3.6 or later.
**Install:** **Install:**

View File

@ -7,6 +7,10 @@ LAMMPS shared library through the Python `ctypes <ctypes_>`_
module. Because of the dynamic loading, it is required that LAMMPS is module. Because of the dynamic loading, it is required that LAMMPS is
compiled in :ref:`"shared" mode <exe>`. compiled in :ref:`"shared" mode <exe>`.
.. versionchanged:: TBD
LAMMPS currently only supports Python version 3.6 or later.
Two components are necessary for Python to be able to invoke LAMMPS code: Two components are necessary for Python to be able to invoke LAMMPS code:
* The LAMMPS Python Package (``lammps``) from the ``python`` folder * The LAMMPS Python Package (``lammps``) from the ``python`` folder
@ -136,11 +140,6 @@ folder that the dynamic loader searches or inside of the installed
# create virtual environment in folder $HOME/myenv # create virtual environment in folder $HOME/myenv
python3 -m venv $HOME/myenv python3 -m venv $HOME/myenv
For Python versions prior 3.3 you can use `virtualenv
<https://packaging.python.org/en/latest/key_projects/#virtualenv>`_
command instead of "python3 -m venv". This step has to be done
only once.
To activate the virtual environment type: To activate the virtual environment type:
.. code-block:: bash .. code-block:: bash
@ -245,14 +244,14 @@ make MPI calls directly from Python in your script, if you desire.
We have tested this with `MPI for Python <https://mpi4py.readthedocs.io/>`_ We have tested this with `MPI for Python <https://mpi4py.readthedocs.io/>`_
(aka mpi4py) and you will find installation instruction for it below. (aka mpi4py) and you will find installation instruction for it below.
Installation of mpi4py (version 3.0.3 as of Sep 2020) can be done as Installation of mpi4py (version 4.0.1 as of Feb 2025) can be done as
follows: follows:
- Via ``pip`` into a local user folder with: - Via ``pip`` into a local user folder with:
.. code-block:: bash .. code-block:: bash
pip install --user mpi4py python3 -m pip install --user mpi4py
- Via ``dnf`` into a system folder for RedHat/Fedora systems: - Via ``dnf`` into a system folder for RedHat/Fedora systems:
@ -261,20 +260,20 @@ follows:
# for use with OpenMPI # for use with OpenMPI
sudo dnf install python3-mpi4py-openmpi sudo dnf install python3-mpi4py-openmpi
# for use with MPICH # for use with MPICH
sudo dnf install python3-mpi4py-openmpi sudo dnf install python3-mpi4py-mpich
- Via ``pip`` into a virtual environment (see above): - Via ``pip`` into a virtual environment (see above):
.. code-block:: console .. code-block:: console
$ source $HOME/myenv/activate $ source $HOME/myenv/activate
(myenv)$ pip install mpi4py (myenv)$ python -m pip install mpi4py
- Via ``pip`` into a system folder (not recommended): - Via ``pip`` into a system folder (not recommended):
.. code-block:: bash .. code-block:: bash
sudo pip install mpi4py sudo python3 -m pip install mpi4py
For more detailed installation instructions and additional options, For more detailed installation instructions and additional options,
please see the `mpi4py installation <https://mpi4py.readthedocs.io/en/stable/install.html>`_ page. please see the `mpi4py installation <https://mpi4py.readthedocs.io/en/stable/install.html>`_ page.

View File

@ -44,15 +44,11 @@ Below is an example output for Python version 3.8.5.
.. warning:: .. warning::
The options described in this section of the manual for using Python The options described in this section of the manual for using Python
with LAMMPS currently support either Python 2 or 3. Specifically with LAMMPS support only Python 3.6 or later. For use with Python
version 2.7 or later and 3.6 or later. Since the Python community no 2.x you will need to use an older LAMMPS version like 29 Aug 2024
longer maintains Python 2 (see `this notice or older. If you notice Python code in the LAMMPS distribution that
<https://www.python.org/doc/sunset-python-2/>`_), we recommend use of is not compatible with Python 3, please contact the LAMMPS developers
Python 3 with LAMMPS. While Python 2 code should continue to work, or submit `and issue on GitHub <https://github.com/lammps/lammps/issues>`_
that is not something we can guarantee long-term. If you notice
Python code in the LAMMPS distribution that is not compatible with
Python 3, please contact the LAMMPS developers or submit `and issue
on GitHub <https://github.com/lammps/lammps/issues>`_
--------- ---------

View File

@ -82,6 +82,7 @@ Commands
read_dump read_dump
read_restart read_restart
region region
region2vmd
replicate replicate
rerun rerun
reset_atoms reset_atoms

179
doc/src/region2vmd.rst Normal file
View File

@ -0,0 +1,179 @@
.. index:: region2vmd
region2vmd command
==================
Syntax
""""""
.. code-block:: LAMMPS
region2vmd file keyword arg ...
* filename = name of file to write VMD script commands to
* zero or more keyword/arg pairs may be appended
* keyword = *region* or *color* or *material* or *command*
.. parsed-literal::
*region* region-ID = name of region to translate to VMD graphics
*color* color-name = set color for following visualized objects
*material* material-name = set material for following visualized objects
*command* string = string with custom VMD script command (in quotes)
Examples
""""""""
.. code-block:: LAMMPS
region2vmd regions.vmd material Opaque color red region c1 color green region c2
region2vmd vizbox.vmd command "mol new system.lammpstrj waitfor all" region box
region2vmd regdefs.vmd region upper region lower region hole
Description
"""""""""""
.. versionadded:: TBD
Write a `VMD <https:://ks.uiuc.edu/Research/vmd/>`_ Tcl script file with
commands that aim to create a visualization of :doc:`regions <region>`.
There may be multiple region visualizations stored in a single file.
The visualization is implemented by creating a new (and empty) "VMD
molecule" and then assigning a sequence of VMD graphics primitives to
represent the region in VMD. Each region will be stored in a separate
"VMD molecule" with the name "LAMMPS region <region ID>".
The *region2vmd* command is following by the filename for the resulting
VMD script and an arbitrary number of keyword argument pairs to either
write out a new *region* visualization, change the *color* or *material*
setting, or to insert arbitrary VMD script *command*\ s. The keywords
and arguments are processed in sequence.
The *region* keyword must be followed by a previously defined LAMMPS
:doc:`region <region>`. Only a limited set region styles and region
settings are currently supported. See **Restrictions** below.
Unsupported region styles or regions with unsupported settings will be
skipped and a corresponding message is printed.
The *color* keyword must be followed by a color name that is defined in
VMD. This color will be used by all following region visualizations.
The default setting is 'silver'. VMD has the following colors
pre-defined:
.. table_from_list::
:columns: 11
* blue
* red
* gray
* orange
* yellow
* tan
* silver
* green
* white
* pink
* cyan
* purple
* lime
* mauve
* ochre
* iceblue
* black
* yellow2
* yellow3
* green2
* green3
* cyan2
* cyan3
* blue2
* blue3
* violet
* violet2
* magenta
* magenta2
* red2
* red3
* orange2
* orange3
The *material* keyword must be followed by a material name that is defined in
VMD. This material will be used by all following visualizations. The
default setting is 'Transparent'. VMD has the following materials
pre-defined:
.. table_from_list::
:columns: 8
* Opaque
* Transparent
* BrushedMetal
* Diffuse
* Ghost
* Glass1
* Glass2
* Glass3
* Glossy
* HardPlastic
* MetallicPastel
* Steel
* Translucent
* Edgy
* EdgyShiny
* EdgyGlass
* Goodsell
* AOShiny
* AOChalky
* AOEdgy
* BlownGlass
* GlassBubble
* RTChrome
The *command* keyword must be followed by a VMD script command as a
single string in quotes. This VMD command will be directly inserted
into the created VMD script.
The created file can be loaded into VMD either from the command line
with the '-e' flag, or from the command prompt with 'play <script
file>', or from the File menu via "Load VMD visualization state".
.. admonition:: Setting the "top" molecule in VMD
:class: note
It is usually desirable to have the "molecule" with the LAMMPS
trajectory set at "top" molecule in VMD and not one of the "region
molecules". The VMD script generated by this region2vmd assumes that
this molecule is already loaded and set as the current "top"
molecule. Thus at the beginning of the script the index of the top
molecule is stored in the VMD variable 'oldtop' and at the end of the
script, that "top" molecule is restored. If no molecule is loaded,
this can be inserted into the script with a custom command. The
molecule index to this new molecules should be assigned to the oldtop
variable. This can be done with e.g. ``set oldtop [mol new
{regions.vmd} waitfor all]``
----------
Restrictions
""""""""""""
This command is part of the EXTRA-COMMAND package. It is only enabled
if LAMMPS was built with that package. See the :doc:`Build package
<Build_package>` page for more info.
Only the following region styles are currently supported: *block*,
*cone*, *cylinder*, *ellipsoid*, *prism*, and *sphere*. Regions formed
from unions or intersections of other regions are not supported.
Rotating regions are currently not supported.
Related commands
""""""""""""""""
:doc:`region <region>`
Defaults
""""""""
*color* = silver, *material* = Transparent

View File

@ -99,6 +99,7 @@ AMD
amino amino
Amirjalayer Amirjalayer
Amit Amit
amsmath
amu amu
Amzallag Amzallag
analytical analytical
@ -128,6 +129,7 @@ Antisymmetrized
antisymmetry antisymmetry
anton anton
Antonelli Antonelli
anysize
api api
apolar apolar
Apoorva Apoorva
@ -613,6 +615,7 @@ Courant
covalent covalent
covalently covalently
covariance covariance
cp
cpp cpp
cpu cpu
cradius cradius
@ -905,6 +908,7 @@ dUs
Duval Duval
dV dV
dvector dvector
dvipng
dVx dVx
dW dW
dx dx
@ -1215,12 +1219,14 @@ fmz
fN fN
Fn Fn
fname fname
fncychap
fno fno
Fnudge Fnudge
foces foces
Fock Fock
Fogarty Fogarty
Foiles Foiles
fontawesome
fopenmp fopenmp
forceclear forceclear
forestgreen forestgreen
@ -1353,6 +1359,7 @@ Goga
Goldfarb Goldfarb
Gompper Gompper
Gonzalez-Melchor Gonzalez-Melchor
Goodsell
googlemail googlemail
googletest googletest
Gordan Gordan
@ -1406,6 +1413,7 @@ Gunsteren
Gunzenmuller Gunzenmuller
Guo Guo
gw gw
gyre
gyromagnetic gyromagnetic
gz gz
gzip gzip
@ -1531,10 +1539,12 @@ hydrostatically
hydroxyl hydroxyl
Hynninen Hynninen
Hyoungki Hyoungki
hypcap
hyperdynamics hyperdynamics
hyperparameters hyperparameters
hyperplane hyperplane
hyperradius hyperradius
hyperref
hyperspherical hyperspherical
hysteretic hysteretic
hz hz
@ -1544,6 +1554,7 @@ Ibanez
ibar ibar
ibm ibm
icc icc
iceblue
ico ico
icosahedral icosahedral
idealgas idealgas
@ -2512,6 +2523,7 @@ Ndof
Ndouble Ndouble
ndx ndx
neb neb
needspace
neel neel
Neel Neel
Neelov Neelov
@ -2724,6 +2736,7 @@ nylo
nz nz
Nz Nz
nzlo nzlo
ochre
ocl ocl
octahedral octahedral
octants octants
@ -2738,6 +2751,7 @@ Okazaki
O'Keefe O'Keefe
OKeefe OKeefe
oldlace oldlace
oldtop
olecular olecular
Oleinik Oleinik
Olfason Olfason
@ -2914,6 +2928,7 @@ picogram
picograms picograms
picosecond picosecond
picoseconds picoseconds
pict
pid pid
piecewise piecewise
Pieniazek Pieniazek
@ -3685,6 +3700,7 @@ Sz
Tabbernor Tabbernor
tabinner tabinner
tabstyle tabstyle
tabulary
Tadmor Tadmor
Tafipolsky Tafipolsky
tagID tagID
@ -3782,6 +3798,7 @@ timestamps
timestep timestep
timestepping timestepping
timesteps timesteps
titlesec
TiN TiN
TiO TiO
Tirado Tirado
@ -3958,6 +3975,7 @@ untilted
Unwin Unwin
uparrow uparrow
upenn upenn
upquote
upto upto
Urbakh Urbakh
Urbana Urbana
@ -4144,6 +4162,7 @@ Workum
Worley Worley
wormlike wormlike
wpbe wpbe
wrapfig
Wriggers Wriggers
writedata writedata
Wuppertal Wuppertal
@ -4174,6 +4193,7 @@ Xia
Xiaohu Xiaohu
Xiaowang Xiaowang
Xie Xie
xindy
xk xk
xlat xlat
xlattice xlattice

View File

@ -1,7 +0,0 @@
# Settings that the LAMMPS build will import when this package library is used
# See the README file for more explanation
python_SYSINC = $(shell which python2-config > /dev/null 2>&1 && python2-config --includes || (which python-config > /dev/null 2>&1 && python-config --includes || :))
python_SYSLIB = $(shell which python2-config > /dev/null 2>&1 && python2-config --ldflags || (which python-config > /dev/null 2>&1 && python-config --ldflags || :))
python_SYSPATH =
PYTHON=$(shell which python2 > /dev/null 2>&1 && echo python2 || echo python)

View File

@ -9,30 +9,29 @@ installation. If needed, you can copy one of the other provided
Makefile.lammps.* files to to Makefile.lammps before building Makefile.lammps.* files to to Makefile.lammps before building
LAMMPS itself. LAMMPS itself.
The files Makefile.lammps.python2 and Makefile.lammps.python3 are The file Makefile.lammps.python3 is similar to the default file, but
similar to the default file, but meant for the case that both, meant for the case that both, python 2 and python 3, are installed
python 2 and python 3, are installed simultaneously and you want simultaneously. LAMMPS only supports python 3. If neither of these
to prefer one over the other. If neither of these files work, you files work, you may have to create a custom Makefile.lammps file
may have to create a custom Makefile.lammps file suitable for suitable for the version of Python on your system. To illustrate, these
the version of Python on your system. To illustrate, these are are example settings from the Makefile.lammps.python3.13 file:
example settings from the Makefile.lammps.python2.7 file:
python_SYSINC = -I/usr/local/include/python2.7 python_SYSINC = -I/usr/local/include/python3.13
python_SYSLIB = -lpython2.7 -lnsl -ldl -lreadline -ltermcap -lpthread -lutil -lm python_SYSLIB = -lpython3.13 -ldl -lm
python_SYSPATH = python_SYSPATH = -L/usr/lib64
PYTHON=python2.7 PYTHON=python3.13
python_SYSINC refers to the directory where Python's Python.h file is python_SYSINC refers to the directory where Python's Python.h file is
found. LAMMPS includes this file. found. LAMMPS includes this file.
python_SYSLIB refers to the libraries needed to link to from an python_SYSLIB refers to the libraries needed to link to from an
application (LAMMPS in this case) to "embed" Python in the application (LAMMPS in this case) to "embed" Python in the
application. The Python library itself is listed (-lpython2.7) are application. The Python library itself is listed (-lpython3.13) are
are several system libraries needed by Python. are several system libraries needed by Python.
python_SYSPATH refers to the path (e.g. -L/usr/local/lib) where the python_SYSPATH refers to the path (e.g. -L/usr/local/lib) where the
Python library can be found. You may not need this setting if the Python library can be found. You may not need this setting if the
path is already included in your LD_LIBRARY_PATH environment variable. path is already included in your LIBRARY_PATH environment variable.
PYTHON is the name of the python interpreter. It is used for PYTHON is the name of the python interpreter. It is used for
installing the LAMMPS python module with "make install-python" installing the LAMMPS python module with "make install-python"
@ -45,7 +44,7 @@ run in embedded mode on your machine.
Here is what this Python doc page says about it: Here is what this Python doc page says about it:
https://docs.python.org/2/extending/embedding.html#compiling-and-linking-under-unix-like-systems https://docs.python.org/3/extending/embedding.html#compiling-and-linking-under-unix-like-systems
"It is not necessarily trivial to find the right flags to pass to your "It is not necessarily trivial to find the right flags to pass to your
compiler (and linker) in order to embed the Python interpreter into compiler (and linker) in order to embed the Python interpreter into

View File

@ -1,20 +1,27 @@
This directory contains Python code which wraps LAMMPS as a library This directory contains the LAMMPS Python module that allows the LAMMPS
and allows the LAMMPS library interface to be invoked from Python, C library interface to be invoked from Python, either from a Python
either from a Python script or using Python interactively. script or using Python interactively.
Details on the Python interface to LAMMPS and how to build LAMMPS as a Details on the Python interface to LAMMPS and how to build LAMMPS as a
shared library, for use with Python, are given in shared library, for use with Python, are given in
doc/Section_python.html and in doc/Section_start.html#start_5. https://docs.lammps.org/Build_basics.html#exe
and
https://docs.lammps.org/Python_install.html
Basically you need to follow these steps in the src directory: Basically you need to use the flag -D BUILD_SHARED_LIBS=ON when
configuring LAMMPS with CMake and then in the build folder use the
command % cmake --build . --target install-python
or for the legacy GNU build system execute these steps in the src folder:
% make g++ mode=shlib # build for whatever machine target you wish % make g++ mode=shlib # build for whatever machine target you wish
% make install-python # install into site-packages folder % make install-python # install into site-packages folder
You can replace the last step by a one-time setting of environment You can replace the last step by a one-time setting of environment
variables in your shell script. Or you can run the python/install.py variables in your shell environment. Or you can run the
script directly to give you more control over where the two relevant python/install.py script directly to give you more control over where
files are installed. See doc/Python_install.html for details. the two relevant files are installed. See
https://docs.lammps.org/Python_install.html for details.
You should then be able to launch Python and instantiate an instance You should then be able to launch Python and instantiate an instance
of LAMMPS: of LAMMPS:
@ -24,13 +31,14 @@ of LAMMPS:
>>> lmp = lammps() >>> lmp = lammps()
If that gives no errors, you have successfully wrapped LAMMPS with If that gives no errors, you have successfully wrapped LAMMPS with
Python. See doc/Section_python.html#py_7 for tests you can then use Python. See https://docs.lammps.org/Python_launch.html for examples how
to run LAMMPS both in serial or parallel thru Python. to run LAMMPS both in serial or parallel from Python.
Note that you can also invoke Python code from within a LAMMPS input Note that you can also invoke Python code from within a LAMMPS input
script, using the "python" command. See the doc/python.html doc page script, using the "python" command. See the
for details. The Python code you invoke can also call back to LAMMPS https://docs.lammps.org/python.html doc page for details. The Python
using the same interface described here for wrapping LAMMPS. code you invoke can also call back to LAMMPS using the same interface
described here for wrapping LAMMPS.
------------------------------------------------------------------- -------------------------------------------------------------------
@ -45,18 +53,19 @@ mc.py Monte Carlo energy relaxation wrapper on LAMMPS
gui.py GUI go/stop/temperature-slider to control LAMMPS gui.py GUI go/stop/temperature-slider to control LAMMPS
plot.py real-time temperature plot with GnuPlot via Pizza.py plot.py real-time temperature plot with GnuPlot via Pizza.py
matplotlib_plot.py real-time temperature plot with Matplotlib via Pizza.py matplotlib_plot.py real-time temperature plot with Matplotlib via Pizza.py
viz_tool.py real-time viz via some viz package viz_<tool>.py real-time viz via some viz package
vizplotgui_tool.py combination of viz.py and plot.py and gui.py vizplotgui_<tool>.py combination of viz.py and plot.py and gui.py
For the viz_tool.py and vizplotgui_tool.py commands, replace "tool" For the viz_<tool>.py and vizplotgui_<tool>.py commands, replace
with "gl" or "atomeye" or "pymol", depending on what visualization "<tool>" with "gl" or "atomeye" or "pymol", depending on what
package you have installed. We hope to add a VMD option soon. visualization package you have installed. We hope to add a VMD option
soon.
Note that for GL, you need to be able to run the Pizza.py GL tool, Note that for GL, you need to be able to run the Pizza.py GL tool,
which is included in the pizza sub-directory. See the Pizza.py doc which is included in the pizza sub-directory. See the Pizza.py doc
pages for more info: pages for more info:
http://www.sandia.gov/~sjplimp/pizza.html https://lammps.github.io/pizza/
Note that for AtomEye, you need version 3, and their is a line in the Note that for AtomEye, you need version 3, and their is a line in the
scripts that specifies the path and name of the executable. See scripts that specifies the path and name of the executable. See
@ -115,17 +124,14 @@ one-processor run, where both Python and LAMMPS will run on single
processors. Each running job will read the same input file, and write processors. Each running job will read the same input file, and write
to same log.lammps file, which isn't too useful. to same log.lammps file, which isn't too useful.
However, if you have the mpi4py Python package installed and uncomment mpi4py However, if you have the mpi4py Python package installed and uncomment
code in simple.py, then the above commands will invoke 1 instance of a mpi4py code in simple.py, then the above commands will invoke 1 instance
P-processor run. Both Python and LAMMPS will run on P processors. The job will of a P-processor run. Both Python and LAMMPS will run on P processors.
read the input file and write a single log.lammps file. The job will read the input file and write a single log.lammps file.
The split.py script can also be run in parallel. It uses mpi4py
version 2.0.0 (or later), which makes it possible to pass a
communicator when creating the LAMMPS object and thus run multiple
instances of LAMMPS at the same time, each on a different subset of
MPI ranks. Or run LAMMPS on one subset and some other program on the
rest of the MPI ranks, concurrently. See comments in the split.py
script for more details.
The split.py script can also be run in parallel. It uses mpi4py version
2.0.0 (or later), which makes it possible to pass a communicator when
creating the LAMMPS object and thus run multiple instances of LAMMPS at
the same time, each on a different subset of MPI ranks. Or run LAMMPS
on one subset and some other program on the rest of the MPI ranks,
concurrently. See comments in the split.py script for more details.

View File

@ -23,6 +23,9 @@ def get_version_number():
if __file__.find(join('python', 'lammps', '__init__.py')) > 0: if __file__.find(join('python', 'lammps', '__init__.py')) > 0:
return 0 return 0
if version_info.major < 3 or (version_info.major == 3 and version_info.minor < 6):
raise SystemError('LAMMPS only supports Python version 3.6 or later')
vstring = None vstring = None
if version_info.major == 3 and version_info.minor >= 8: if version_info.major == 3 and version_info.minor >= 8:
from importlib.metadata import version, PackageNotFoundError from importlib.metadata import version, PackageNotFoundError

View File

@ -83,8 +83,6 @@ class command_wrapper(object):
def _wrap_args(self, x): def _wrap_args(self, x):
if callable(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 hashlib
import __main__ import __main__
sha = hashlib.sha256() sha = hashlib.sha256()
@ -105,11 +103,6 @@ class command_wrapper(object):
all the arguments, concatinates them to a single string, and executes it using all the arguments, concatinates them to a single string, and executes it using
:py:meth:`lammps.command`. :py:meth:`lammps.command`.
Starting with Python 3.6 it also supports keyword arguments. key=value is
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) LAMMPS commands that accept callback functions (such as fix python/invoke)
can be passed functions and lambdas directly. The first argument of such can be passed functions and lambdas directly. The first argument of such
callbacks will be an lammps object constructed from the passed LAMMPS callbacks will be an lammps object constructed from the passed LAMMPS
@ -121,9 +114,6 @@ class command_wrapper(object):
def handler(*args, **kwargs): def handler(*args, **kwargs):
cmd_args = [name] + [str(self._wrap_args(x)) for x in args] 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 # Python 3.6+ maintains ordering of kwarg keys
for k in kwargs.keys(): for k in kwargs.keys():
cmd_args.append(k) cmd_args.append(k)
@ -530,16 +520,10 @@ class lammps(object):
else: else:
# magic to convert ptr to ctypes ptr # magic to convert ptr to ctypes ptr
if sys.version_info >= (3, 0):
# Python 3 (uses PyCapsule API) # Python 3 (uses PyCapsule API)
pythonapi.PyCapsule_GetPointer.restype = c_void_p pythonapi.PyCapsule_GetPointer.restype = c_void_p
pythonapi.PyCapsule_GetPointer.argtypes = [py_object, c_char_p] pythonapi.PyCapsule_GetPointer.argtypes = [py_object, c_char_p]
self.lmp = c_void_p(pythonapi.PyCapsule_GetPointer(ptr, None)) self.lmp = c_void_p(pythonapi.PyCapsule_GetPointer(ptr, None))
else:
# Python 2 (uses PyCObject API)
pythonapi.PyCObject_AsVoidPtr.restype = c_void_p
pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object]
self.lmp = c_void_p(pythonapi.PyCObject_AsVoidPtr(ptr))
# check if library initilialization failed # check if library initilialization failed
if not self.lmp: if not self.lmp:

2
src/.gitignore vendored
View File

@ -1549,6 +1549,8 @@
/reaxff_inline.h /reaxff_inline.h
/reaxff_omp.h /reaxff_omp.h
/reaxff_types.h /reaxff_types.h
/region2vmd.cpp
/region2vmd.h
/remap.cpp /remap.cpp
/remap.h /remap.h
/remap_wrap.cpp /remap_wrap.cpp

View File

@ -0,0 +1,893 @@
/* -*- 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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Axel Kohlmeyer (Temple U)
------------------------------------------------------------------------- */
#include "region2vmd.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "math_const.h"
#include "math_extra.h"
#include "region.h"
#include "safe_pointers.h"
#include "region_block.h"
#include "region_cone.h"
#include "region_cylinder.h"
#include "region_ellipsoid.h"
#include "region_plane.h"
#include "region_prism.h"
#include "region_sphere.h"
#include <cmath>
#include <cstring>
#include <unordered_set>
using namespace LAMMPS_NS;
using MathConst::MY_2PI;
static constexpr double SMALL = 1.0e-10;
static constexpr double DELTA = 1.0e-5;
static constexpr int RESOLUTION = 20;
static constexpr double RADINC = MY_2PI / RESOLUTION;
static const std::unordered_set<std::string> vmdcolors{
"blue", "red", "gray", "orange", "yellow", "tan", "silver", "green", "white",
"pink", "cyan", "purple", "lime", "mauve", "ochre", "iceblue", "black", "yellow2",
"yellow3", "green2", "green3", "cyan2", "cyan3", "blue2", "blue3", "violet", "violet2",
"magenta", "magenta2", "red2", "red3", "orange2", "orange3"};
static const std::unordered_set<std::string> vmdmaterials{
"Opaque", "Transparent", "BrushedMetal", "Diffuse", "Ghost", "Glass1",
"Glass2", "Glass3", "Glossy", "HardPlastic", "MetallicPastel", "Steel",
"Translucent", "Edgy", "EdgyShiny", "EdgyGlass", "Goodsell", "AOShiny",
"AOChalky", "AOEdgy", "BlownGlass", "GlassBubble", "RTChrome"};
static constexpr char draw_ellipsoid_function[] =
"\n# VMD script code to emulate ellipsoids with trinorm graphics objects\n"
"proc vmd_draw_ellipsoid {mol level {center {0.0 0.0 0.0}} {radius {1.0 1.0 1.0}}} {\n"
" set orient {1.0 0.0 0.0 0.0}\n"
" set gid {}\n\n"
" # vertices of an octahedron inscribed\n"
" # in a sphere with radius 1.0.\n"
" set vec1 {-1.0 0.0 0.0}\n"
" set vec2 { 1.0 0.0 0.0}\n"
" set vec3 { 0.0 -1.0 0.0}\n"
" set vec4 { 0.0 1.0 0.0}\n"
" set vec5 { 0.0 0.0 -1.0}\n"
" set vec6 { 0.0 0.0 1.0}\n\n"
" # build list of triangles representing\n"
" # the octahedron. the points of the \n"
" # triangles have to be given clockwise from\n"
" # looking at the surface from the outside.\n"
" set trilist [list \\\n"
" [list $vec1 $vec4 $vec5] \\\n"
" [list $vec5 $vec4 $vec2] \\\n"
" [list $vec2 $vec4 $vec6] \\\n"
" [list $vec6 $vec4 $vec1] \\\n"
" [list $vec5 $vec3 $vec1] \\\n"
" [list $vec2 $vec3 $vec5] \\\n"
" [list $vec6 $vec3 $vec2] \\\n"
" [list $vec1 $vec3 $vec6] ]\n\n"
" # refinement iterations to approximate a sphere:\n"
" # each triangle is split into 4 subtriangles\n"
" # p2\n"
" # /\\\n"
" # / \\\n"
" # pb/____\\pc\n"
" # /\\ /\\\n"
" # / \\ / \\\n"
" # /____\\/____\\\n"
" # p1 pa p3\n\n"
" # we construct vectors to the three midpoints and rescale\n"
" # them to unit length. then build new triangles enumerating\n"
" # the points in clockwise order again.\n"
" for {set i 0} {$i < $level} {incr i} {\n"
" set newlist {}\n"
" foreach tri $trilist {\n"
" foreach {p1 p2 p3} $tri {}\n"
" set pa [vecnorm [vecadd $p1 $p3]]\n"
" set pb [vecnorm [vecadd $p1 $p2]]\n"
" set pc [vecnorm [vecadd $p2 $p3]]\n"
" lappend newlist [list $p1 $pb $pa]\n"
" lappend newlist [list $pb $p2 $pc]\n"
" lappend newlist [list $pa $pb $pc]\n"
" lappend newlist [list $pa $pc $p3]\n"
" }\n"
" set trilist $newlist\n"
" }\n\n"
" # compute vertex scaling factor to deform a sphere to an ellipsoid\n"
" proc radscale {radius vector} {\n"
" foreach {a b c} $radius {}\n"
" foreach {x y z} $vector {}\n"
" return [expr {sqrt(1.0/($x/$a*$x/$a+$y/$b*$y/$b+$z/$c*$z/$c))}]\n"
" }\n\n"
" # convert quaternion to rotation matrix\n"
" proc quattorot {quat} {\n"
" foreach {w x y z} $quat {}\n"
" set norm [expr {$w*$w + $x*$x + $y*$y +$z*$z}]\n"
" set sc 0.0\n"
" if {$norm > 0.0} { set s [expr {2.0/$norm}] }\n"
" set X [expr {$x*$s}]\n"
" set Y [expr {$y*$s}]\n"
" set Z [expr {$z*$s}]\n"
" return [list \\\n"
" [list [expr {1.0-($y*$y*$s + $z*$z*$s)}] \\\n"
" [expr {$x*$y*$s - $w*$z*$s}] \\\n"
" [expr {$x*$z*$s + $w*$y*$s}] ] \\\n"
" [list [expr {$x*$y*$s + $w*$z*$s}] \\\n"
" [expr {1.0-($x*$x*$s + $z*$z*$s)}] \\\n"
" [expr {$y*$z*$s - $w*$x*$s}] ] \\\n"
" [list [expr {$x*$z*$s - $w*$y*$s}] \\\n"
" [expr {$y*$z*$s + $w*$x*$s}] \\\n"
" [expr {1.0-($x*$x*$s + $y*$y*$s)}] ] ]\n"
" }\n\n"
" # apply rotation matrix to vector\n"
" proc rotvec {mat vec} {\n"
" set new {}\n"
" foreach c $mat {\n"
" lappend new [vecdot $c $vec]\n"
" }\n"
" return $new\n"
" }\n\n"
" foreach tri $trilist {\n"
" foreach {vec1 vec2 vec3} $tri {}\n"
" # rescale to desired radius\n"
" set rad1 [radscale $radius $vec1]\n"
" set rad2 [radscale $radius $vec2]\n"
" set rad3 [radscale $radius $vec3]\n"
" # get and apply rotation matrix\n"
" set mat [quattorot $orient]\n"
" set vec1 [rotvec $mat $vec1]\n"
" set vec2 [rotvec $mat $vec2]\n"
" set vec3 [rotvec $mat $vec3]\n"
" # deform sphereoid and translate\n"
" set pos1 [vecadd [vecscale $rad1 $vec1] $center]\n"
" set pos2 [vecadd [vecscale $rad2 $vec2] $center]\n"
" set pos3 [vecadd [vecscale $rad3 $vec3] $center]\n"
" # since the original vectors to the vertices are those of\n"
" # a unit sphere, we can use them directly as surface normals.\n"
" lappend gid [graphics $mol trinorm $pos1 $pos2 $pos3 $vec1 $vec2 $vec3]\n"
" }\n"
" return $gid\n"
"}\n\n";
/* ---------------------------------------------------------------------- */
void Region2VMD::command(int narg, char **arg)
{
if (narg < 3) utils::missing_cmd_args(FLERR, "region2vmd", error);
// automatically close file when it goes out of scope
SafeFilePtr fp;
if (comm->me == 0) {
fp = fopen(arg[0], "w");
if (fp == nullptr) {
error->one(FLERR, Error::ARGZERO, "Cannot open file {} for writing: {}", arg[0],
utils::getsyserror());
} else {
utils::logmesg(lmp, "Writing region visualizations to VMD Tcl script file {}:\n", arg[0]);
fputs("# save old top molecule index\nset oldtop [molinfo top]\n", fp);
}
}
// defaults
std::string color = "silver";
std::string material = "Transparent";
bool def_ellipsoid_func = false;
int iarg = 1;
std::string thisarg = arg[iarg];
while (iarg < narg) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "region2vmd", error);
thisarg = arg[iarg];
++iarg;
if (thisarg == "color") {
color = arg[iarg];
if (const auto &search = vmdcolors.find(color); search == vmdcolors.end())
error->all(FLERR, iarg, "Color {} is not a known VMD color", color);
} else if (thisarg == "material") {
material = arg[iarg];
if (const auto &search = vmdmaterials.find(material); search == vmdmaterials.end())
error->all(FLERR, iarg, "Material {} is not a known VMD material", material);
} else if (thisarg == "command") {
if (fp) {
fputs("\n# custom command\n", fp);
fputs(arg[iarg], fp);
fputs("\n", fp);
}
} else if (thisarg == "region") {
auto *region = domain->get_region_by_id(arg[iarg]);
if (!region) {
error->all(FLERR, iarg, "Region {} does not exist", arg[iarg]);
} else {
if (fp) {
// add VMD / Tcl function to draw ellipsoids only once
if (!def_ellipsoid_func && (strcmp(region->style, "ellipsoid") == 0)) {
fputs(draw_ellipsoid_function, fp);
def_ellipsoid_func = true;
}
utils::logmesg(lmp, " writing region {} ...", region->id);
utils::print(fp, "\n# region {} of style {}\n", region->id, region->style);
fputs("# create new empty VMD molecule to store the graphics primitives\n"
"set gfxmol [mol new]\nmol top $gfxmol\n",
fp);
utils::print(fp, "mol rename $gfxmol {{LAMMPS region {}}}\n", region->id);
fputs("# set color and material\n", fp);
utils::print(fp, "graphics $gfxmol color {}\n", color);
utils::print(fp, "graphics $gfxmol material {}\n", material);
write_region(fp, region);
}
}
} else {
error->all(FLERR, iarg - 1, "Unknown region2vmd keyword {}", thisarg);
}
++iarg;
}
// done. file will be close automatically
if (fp) {
// reset views and restore previous top molecule
fputs("after idle {if {$oldtop >= 0} {mol top $oldtop}; display resetview}\n", fp);
}
}
/* ----------------------------------------------------------------------
write out one region using VMD graphics primitives
fp is non-NULL only on MPI rank 0
---------------------------------------------------------------------- */
void Region2VMD::write_region(FILE *fp, Region *region)
{
if (!fp || !region) return;
if (region->rotateflag) {
utils::logmesg(lmp, "Cannot (yet) handle rotating region {}. Skipping... ", region->id);
return;
}
// update internal variables
region->prematch();
// compute position offset for moving regions
double dx = 0.0;
double dy = 0.0;
double dz = 0.0;
if (region->moveflag) {
dx = region->dx;
dy = region->dy;
dz = region->dz;
}
// translate compatible regions to VMD graphics primitives, skip others.
const std::string regstyle = region->style;
if (regstyle == "block") {
const auto block = dynamic_cast<RegBlock *>(region);
if (!block) {
error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'block'", region->id);
} else {
// a block is represented by 12 triangles
// comment out VMD command when side is open
utils::print(fp,
"{6}draw triangle {{{0} {2} {4}}} {{{0} {2} {5}}} {{{0} {3} {4}}}\n"
"{6}draw triangle {{{0} {3} {4}}} {{{0} {3} {5}}} {{{0} {2} {5}}}\n"
"{8}draw triangle {{{0} {2} {4}}} {{{0} {2} {5}}} {{{1} {2} {4}}}\n"
"{8}draw triangle {{{1} {2} {4}}} {{{1} {2} {5}}} {{{0} {2} {5}}}\n"
"{7}draw triangle {{{1} {2} {4}}} {{{1} {2} {5}}} {{{1} {3} {4}}}\n"
"{7}draw triangle {{{1} {3} {4}}} {{{1} {3} {5}}} {{{1} {2} {5}}}\n"
"{10}draw triangle {{{0} {2} {4}}} {{{1} {2} {4}}} {{{1} {3} {4}}}\n"
"{10}draw triangle {{{0} {2} {4}}} {{{0} {3} {4}}} {{{1} {3} {4}}}\n"
"{11}draw triangle {{{0} {2} {5}}} {{{1} {2} {5}}} {{{1} {3} {5}}}\n"
"{11}draw triangle {{{0} {2} {5}}} {{{0} {3} {5}}} {{{1} {3} {5}}}\n"
"{9}draw triangle {{{0} {3} {4}}} {{{0} {3} {5}}} {{{1} {3} {5}}}\n"
"{9}draw triangle {{{0} {3} {4}}} {{{1} {3} {4}}} {{{1} {3} {5}}}\n",
block->xlo + dx, block->xhi + dx, block->ylo + dy, block->yhi + dy,
block->zlo + dz, block->zhi + dz, block->open_faces[0] ? "# " : "",
block->open_faces[1] ? "# " : "", block->open_faces[2] ? "# " : "",
block->open_faces[3] ? "# " : "", block->open_faces[4] ? "# " : "",
block->open_faces[5] ? "# " : "");
}
} else if (regstyle == "cone") {
const auto cone = dynamic_cast<RegCone *>(region);
if (!cone) {
error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'cone'", region->id);
} else {
// draw cone
if (!cone->open_faces[2]) {
// both radii too small
if ((cone->radiuslo < SMALL) && (cone->radiushi < SMALL)) {
; // nothing to draw
// lo end has a tip
} else if (cone->radiuslo < SMALL) {
double v1[3], v2[3], v3[3], v4[3], v5[3];
if (cone->axis == 'x') {
// set tip coordinate
v1[0] = cone->lo + dx;
v1[1] = cone->c1 + dy;
v1[2] = cone->c2 + dz;
// loop around radius
for (int i = 0; i < RESOLUTION; ++i) {
v2[0] = cone->hi + dx;
v2[1] = cone->c1 + cone->radiushi * sin(RADINC * i) + dy;
v2[2] = cone->c2 + cone->radiushi * cos(RADINC * i) + dz;
v3[0] = cone->hi + dx;
v3[1] = cone->c1 + cone->radiushi * sin(RADINC * (i + 1.0)) + dy;
v3[2] = cone->c2 + cone->radiushi * cos(RADINC * (i + 1.0)) + dz;
v4[0] = 0.0;
v4[1] = sin(RADINC * i);
v4[2] = cos(RADINC * i);
v5[0] = 0.0;
v5[1] = sin(RADINC * (i + 1.0));
v5[2] = cos(RADINC * (i + 1.0));
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 1.0, 0.0,
0.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]);
}
} else if (cone->axis == 'y') {
// set tip coordinate
v1[0] = cone->c1 + dx;
v1[1] = cone->lo + dy;
v1[2] = cone->c2 + dz;
// loop around radius
for (int i = 0; i < RESOLUTION; ++i) {
v2[0] = cone->c1 + cone->radiushi * sin(RADINC * i) + dx;
v2[1] = cone->hi + dy;
v2[2] = cone->c2 + cone->radiushi * cos(RADINC * i) + dz;
v3[0] = cone->c1 + cone->radiushi * sin(RADINC * (i + 1.0)) + dx;
v3[1] = cone->hi + dy;
v3[2] = cone->c2 + cone->radiushi * cos(RADINC * (i + 1.0)) + dz;
v4[0] = sin(RADINC * i);
v4[1] = 0.0;
v4[2] = cos(RADINC * i);
v5[0] = sin(RADINC * (i + 1.0));
v5[1] = 0.0;
v5[2] = cos(RADINC * (i + 1.0));
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 0.0, 1.0,
0.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]);
}
} else if (cone->axis == 'z') {
// set tip coordinate
v1[0] = cone->c1 + dx;
v1[1] = cone->c2 + dy;
v1[2] = cone->lo + dz;
// loop around radius
for (int i = 0; i < RESOLUTION; ++i) {
v2[0] = cone->c1 + cone->radiushi * sin(RADINC * i) + dx;
v2[1] = cone->c2 + cone->radiushi * cos(RADINC * i) + dy;
v2[2] = cone->hi + dz;
v3[0] = cone->c1 + cone->radiushi * sin(RADINC * (i + 1.0)) + dx;
v3[1] = cone->c2 + cone->radiushi * cos(RADINC * (i + 1.0)) + dy;
v3[2] = cone->hi + dz;
v4[0] = sin(RADINC * i);
v4[1] = cos(RADINC * i);
v4[2] = 0.0;
v5[0] = sin(RADINC * (i + 1.0));
v5[1] = cos(RADINC * (i + 1.0));
v5[2] = 0.0;
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 0.0, 0.0,
1.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]);
}
}
// hi end has a tip
} else if (cone->radiushi < SMALL) {
double v1[3], v2[3], v3[3], v4[3], v5[3];
if (cone->axis == 'x') {
// set tip coordinate
v1[0] = cone->hi + dx;
v1[1] = cone->c1 + dy;
v1[2] = cone->c2 + dz;
// loop around radius
for (int i = 0; i < RESOLUTION; ++i) {
v2[0] = cone->lo + dx;
v2[1] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dy;
v2[2] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dz;
v3[0] = cone->lo + dx;
v3[1] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dy;
v3[2] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dz;
v4[0] = 0.0;
v4[1] = sin(RADINC * i);
v4[2] = cos(RADINC * i);
v5[0] = 0.0;
v5[1] = sin(RADINC * (i + 1.0));
v5[2] = cos(RADINC * (i + 1.0));
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 1.0, 0.0,
0.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]);
}
} else if (cone->axis == 'y') {
// set tip coordinate
v1[0] = cone->c1 + dx;
v1[1] = cone->hi + dy;
v1[2] = cone->c2 + dz;
// loop around radius
for (int i = 0; i < RESOLUTION; ++i) {
v2[0] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dx;
v2[1] = cone->lo + dy;
v2[2] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dz;
v3[0] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dx;
v3[1] = cone->lo + dy;
v3[2] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dz;
v4[0] = sin(RADINC * i);
v4[1] = 0.0;
v4[2] = cos(RADINC * i);
v5[0] = sin(RADINC * (i + 1.0));
v5[1] = 0.0;
v5[2] = cos(RADINC * (i + 1.0));
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 0.0, 1.0,
0.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]);
}
} else if (cone->axis == 'z') {
// set tip coordinate
v1[0] = cone->c1 + dx;
v1[1] = cone->c2 + dy;
v1[2] = cone->hi + dz;
// loop around radius
for (int i = 0; i < RESOLUTION; ++i) {
v2[0] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dx;
v2[1] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dy;
v2[2] = cone->lo + dz;
v3[0] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dx;
v3[1] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dy;
v3[2] = cone->lo + dz;
v4[0] = sin(RADINC * i);
v4[1] = cos(RADINC * i);
v4[2] = 0.0;
v5[0] = sin(RADINC * (i + 1.0));
v5[1] = cos(RADINC * (i + 1.0));
v5[2] = 0.0;
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 0.0, 0.0,
1.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]);
}
}
// truncated cone
} else if (!cone->open_faces[2]) {
double v1[3], v2[3], v3[3], v4[3], v5[3], v6[3], v7[3], v8[3];
if (cone->axis == 'x') {
// loop around radii
for (int i = 0; i < RESOLUTION; ++i) {
v1[0] = cone->hi + dx;
v1[1] = cone->c1 + cone->radiushi * sin(RADINC * (i - 0.5)) + dy;
v1[2] = cone->c2 + cone->radiushi * cos(RADINC * (i - 0.5)) + dz;
v2[0] = cone->lo + dx;
v2[1] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dy;
v2[2] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dz;
v3[0] = cone->hi + dx;
v3[1] = cone->c1 + cone->radiushi * sin(RADINC * (i + 0.5)) + dy;
v3[2] = cone->c2 + cone->radiushi * cos(RADINC * (i + 0.5)) + dz;
v4[0] = cone->lo + dx;
v4[1] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dy;
v4[2] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dz;
v5[0] = 0.0;
v5[1] = sin(RADINC * (i - 0.5));
v5[2] = cos(RADINC * (i - 0.5));
v6[0] = 0.0;
v6[1] = sin(RADINC * i);
v6[2] = cos(RADINC * i);
v7[0] = 0.0;
v7[1] = sin(RADINC * (i + 0.5));
v7[2] = cos(RADINC * (i + 0.5));
v8[0] = 0.0;
v8[1] = sin(RADINC * (i + 1.0));
v8[2] = cos(RADINC * (i + 1.0));
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], v5[0],
v5[1], v5[2], v6[0], v6[1], v6[2], v7[0], v7[1], v7[2]);
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v2[0], v2[1], v2[2], v4[0], v4[1], v4[2], v3[0], v3[1], v3[2], v6[0],
v6[1], v6[2], v8[0], v8[1], v8[2], v7[0], v7[1], v7[2]);
}
} else if (cone->axis == 'y') {
// loop around radii
for (int i = 0; i < RESOLUTION; ++i) {
v1[0] = cone->c1 + cone->radiushi * sin(RADINC * (i - 0.5)) + dx;
v1[1] = cone->hi + dy;
v1[2] = cone->c2 + cone->radiushi * cos(RADINC * (i - 0.5)) + dz;
v2[0] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dx;
v2[1] = cone->lo + dy;
v2[2] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dz;
v3[0] = cone->c1 + cone->radiushi * sin(RADINC * (i + 0.5)) + dx;
v3[1] = cone->hi + dy;
v3[2] = cone->c2 + cone->radiushi * cos(RADINC * (i + 0.5)) + dz;
v4[0] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dx;
v4[1] = cone->lo + dy;
v4[2] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dz;
v5[0] = sin(RADINC * (i - 0.5));
v5[1] = 0.0;
v5[2] = cos(RADINC * (i - 0.5));
v6[0] = sin(RADINC * i);
v6[1] = 0.0;
v6[2] = cos(RADINC * i);
v7[0] = sin(RADINC * (i + 0.5));
v7[1] = 0.0;
v7[2] = cos(RADINC * (i + 0.5));
v8[0] = sin(RADINC * (i + 1.0));
v8[1] = 0.0;
v8[2] = cos(RADINC * (i + 1.0));
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], v5[0],
v5[1], v5[2], v6[0], v6[1], v6[2], v7[0], v7[1], v7[2]);
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v2[0], v2[1], v2[2], v4[0], v4[1], v4[2], v3[0], v3[1], v3[2], v6[0],
v6[1], v6[2], v8[0], v8[1], v8[2], v7[0], v7[1], v7[2]);
}
} else if (cone->axis == 'z') {
// loop around radii
for (int i = 0; i < RESOLUTION; ++i) {
v1[0] = cone->c1 + cone->radiushi * sin(RADINC * (i - 0.5)) + dx;
v1[1] = cone->c2 + cone->radiushi * cos(RADINC * (i - 0.5)) + dy;
v1[2] = cone->hi + dz;
v2[0] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dx;
v2[1] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dy;
v2[2] = cone->lo + dz;
v3[0] = cone->c1 + cone->radiushi * sin(RADINC * (i + 0.5)) + dx;
v3[1] = cone->c2 + cone->radiushi * cos(RADINC * (i + 0.5)) + dy;
v3[2] = cone->hi + dz;
v4[0] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dx;
v4[1] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dy;
v4[2] = cone->lo + dz;
v5[0] = sin(RADINC * (i - 0.5));
v5[1] = cos(RADINC * (i - 0.5));
v5[2] = 0.0;
v6[0] = sin(RADINC * i);
v6[1] = cos(RADINC * i);
v6[2] = 0.0;
v7[0] = sin(RADINC * (i + 0.5));
v7[1] = cos(RADINC * (i + 0.5));
v7[2] = 0.0;
v8[0] = sin(RADINC * (i + 1.0));
v8[1] = cos(RADINC * (i + 1.0));
v8[2] = 0.0;
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], v5[0],
v5[1], v5[2], v6[0], v6[1], v6[2], v7[0], v7[1], v7[2]);
utils::print(fp,
"draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} "
"{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n",
v2[0], v2[1], v2[2], v4[0], v4[1], v4[2], v3[0], v3[1], v3[2], v6[0],
v6[1], v6[2], v8[0], v8[1], v8[2], v7[0], v7[1], v7[2]);
}
}
}
}
// draw lids
if ((cone->radiuslo > SMALL) && !cone->open_faces[0]) {
double lid = cone->lo;
if (cone->axis == 'x') {
lid += dx;
utils::print(fp,
"draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cone->c1 + dy, cone->c2 + dz, cone->radiuslo, RESOLUTION);
} else if (cone->axis == 'y') {
lid += dy;
utils::print(fp,
"draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cone->c1 + dx, cone->c2 + dz, cone->radiuslo, RESOLUTION);
} else if (cone->axis == 'z') {
lid += dz;
utils::print(fp,
"draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cone->c1 + dx, cone->c2 + dy, cone->radiuslo, RESOLUTION);
}
}
if ((cone->radiushi > SMALL) && !cone->open_faces[1]) {
double lid = cone->hi;
if (cone->axis == 'x') {
lid += dx;
utils::print(fp,
"draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cone->c1 + dy, cone->c2 + dz, cone->radiushi, RESOLUTION);
} else if (cone->axis == 'y') {
lid += dy;
utils::print(fp,
"draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cone->c1 + dx, cone->c2 + dz, cone->radiushi, RESOLUTION);
} else if (cone->axis == 'z') {
lid += dz;
utils::print(fp,
"draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cone->c1 + dx, cone->c2 + dy, cone->radiushi, RESOLUTION);
}
}
}
} else if (regstyle == "cylinder") {
const auto cyl = dynamic_cast<RegCylinder *>(region);
if (!cyl) {
error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'cylinder'", region->id);
} else {
// first draw the cylinder. filled only when *all* faces are closed.
// with any open face we draw each part separately
std::string filled = "filled no";
if (!cyl->open_faces[0] && !cyl->open_faces[1] && !cyl->open_faces[2]) {
filled = "filled yes";
}
// the cylinder uses a single cylinder primitive
if (!cyl->open_faces[2]) {
if (cyl->axis == 'x') {
utils::print(
fp, "draw cylinder {{{0} {2} {3}}} {{{1} {2} {3}}} radius {4} resolution {5} {6}\n",
cyl->lo + dx, cyl->hi + dx, cyl->c1 + dy, cyl->c2 + dz, cyl->radius, RESOLUTION,
filled);
} else if (cyl->axis == 'y') {
utils::print(
fp, "draw cylinder {{{2} {0} {3}}} {{{2} {1} {3}}} radius {4} resolution {5} {6}\n",
cyl->lo + dy, cyl->hi + dy, cyl->c1 + dx, cyl->c2 + dz, cyl->radius, RESOLUTION,
filled);
} else if (cyl->axis == 'z') {
utils::print(
fp, "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1}}} radius {4} resolution {5} {6}\n",
cyl->lo + dz, cyl->hi + dz, cyl->c1 + dx, cyl->c2 + dy, cyl->radius, RESOLUTION,
filled);
}
}
// draw lids
if ((filled == "filled no") && !cyl->open_faces[0]) {
double lid = cyl->lo;
if (cyl->axis == 'x') {
lid += dx;
utils::print(fp,
"draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cyl->c1 + dy, cyl->c2 + dz, cyl->radius, RESOLUTION);
} else if (cyl->axis == 'y') {
lid += dy;
utils::print(fp,
"draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dz, cyl->radius, RESOLUTION);
} else if (cyl->axis == 'z') {
lid += dz;
utils::print(fp,
"draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dy, cyl->radius, RESOLUTION);
}
}
if ((filled == "filled no") && !cyl->open_faces[1]) {
double lid = cyl->hi;
if (cyl->axis == 'x') {
lid += dx;
utils::print(fp,
"draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cyl->c1 + dy, cyl->c2 + dz, cyl->radius, RESOLUTION);
} else if (cyl->axis == 'y') {
lid += dy;
utils::print(fp,
"draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dz, cyl->radius, RESOLUTION);
} else if (cyl->axis == 'z') {
lid += dz;
utils::print(fp,
"draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} "
"resolution {5} filled yes\n",
lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dy, cyl->radius, RESOLUTION);
}
}
}
} else if (regstyle == "ellipsoid") {
const auto ellipsoid = dynamic_cast<RegEllipsoid *>(region);
if (!ellipsoid) {
error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'ellipsoid'", region->id);
} else {
// for ellipsoid we use a custom VMD function that emulates it using trinorm primitives
utils::print(fp, "draw ellipsoid 3 {{{} {} {}}} {{{} {} {}}}\n", ellipsoid->xc + dx,
ellipsoid->yc + dy, ellipsoid->zc + dz, ellipsoid->a, ellipsoid->b,
ellipsoid->c);
}
} else if (regstyle == "plane") {
const auto plane = dynamic_cast<RegPlane *>(region);
if (!plane) {
error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'plane'", region->id);
} else {
double v1[3], v2[3], v3[3], v4[3], v5[3], v6[3];
MathExtra::copy3(plane->normal, v1);
MathExtra::norm3(v1);
v2[0] = plane->xp + dx;
v2[1] = plane->yp + dy;
v2[2] = plane->zp + dz;
// determine the largest component of the plane normal and use that to determine the triangle edges
int dim1, dim2, dim3;
if (fabs(v1[0]) > fabs(v1[1])) { // x > y
if (fabs(v1[0]) > fabs(v1[2])) { // x > z => x is largest
dim3 = 0;
dim1 = 1;
dim2 = 2;
} else { // z is largest
dim3 = 2;
dim1 = 0;
dim2 = 1;
}
} else { // x < y
if (fabs(v1[1]) > fabs(v1[2])) { // y > z => y is largest
dim3 = 1;
dim1 = 0;
dim2 = 2;
} else { // z is largest
dim3 = 2;
dim1 = 0;
dim2 = 1;
}
}
MathExtra::scale3(2.0, domain->boxlo, v3);
v3[dim3] = 0.0;
MathExtra::cross3(v1, v3, v4);
MathExtra::add3(v4, v2, v5);
v3[dim1] = domain->boxhi[dim1];
v3[dim2] = domain->boxlo[dim2];
v3[dim3] = 0.0;
MathExtra::scale3(2.0, v3);
MathExtra::cross3(v1, v3, v4);
MathExtra::add3(v4, v2, v6);
utils::print(fp, "draw triangle {{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", v2[dim1], v2[dim2],
v2[dim3], v5[dim1], v5[dim2], v5[dim3], v6[dim1], v6[dim2], v6[dim3]);
v3[dim1] = domain->boxlo[dim1];
v3[dim2] = domain->boxhi[dim2];
v3[dim3] = 0.0;
MathExtra::scale3(2.0, v3);
MathExtra::cross3(v1, v3, v4);
MathExtra::add3(v4, v2, v6);
utils::print(fp, "draw triangle {{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", v2[dim1], v2[dim2],
v2[dim3], v5[dim1], v5[dim2], v5[dim3], v6[dim1], v6[dim2], v6[dim3]);
v3[dim1] = domain->boxhi[dim1];
v3[dim2] = domain->boxhi[dim2];
v3[dim3] = 0.0;
MathExtra::scale3(2.0, v3);
MathExtra::cross3(v1, v3, v4);
MathExtra::add3(v4, v2, v5);
v3[dim1] = domain->boxhi[dim1];
v3[dim2] = domain->boxlo[dim2];
v3[dim3] = 0.0;
MathExtra::scale3(2.0, v3);
MathExtra::cross3(v1, v3, v4);
MathExtra::add3(v4, v2, v6);
utils::print(fp, "draw triangle {{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", v2[dim1], v2[dim2],
v2[dim3], v5[dim1], v5[dim2], v5[dim3], v6[dim1], v6[dim2], v6[dim3]);
v3[dim1] = domain->boxlo[dim1];
v3[dim2] = domain->boxhi[dim2];
v3[dim3] = 0.0;
MathExtra::scale3(2.0, v3);
MathExtra::cross3(v1, v3, v4);
MathExtra::add3(v4, v2, v6);
utils::print(fp, "draw triangle {{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", v2[dim1], v2[dim2],
v2[dim3], v5[dim1], v5[dim2], v5[dim3], v6[dim1], v6[dim2], v6[dim3]);
}
} else if (regstyle == "prism") {
const auto prism = dynamic_cast<RegPrism *>(region);
if (!prism) {
error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'prism'", region->id);
} else {
// a prism is represented by 12 triangles
// comment out VMD command when side is open
utils::print(fp,
"{14}draw triangle {{{0} {2} {4}}} {{{1} {2} {4}}} {{{7} {3} {4}}}\n"
"{14}draw triangle {{{0} {2} {4}}} {{{6} {3} {4}}} {{{7} {3} {4}}}\n"
"{16}draw triangle {{{0} {2} {4}}} {{{1} {2} {4}}} {{{8} {9} {5}}}\n"
"{16}draw triangle {{{0} {2} {4}}} {{{10} {9} {5}}} {{{8} {9} {5}}}\n"
"{19}draw triangle {{{1} {2} {4}}} {{{8} {9} {5}}} {{{7} {3} {4}}}\n"
"{19}draw triangle {{{11} {12} {5}}} {{{8} {9} {5}}} {{{7} {3} {4}}}\n"
"{18}draw triangle {{{0} {2} {4}}} {{{6} {3} {4}}} {{{13} {12} {5}}}\n"
"{18}draw triangle {{{0} {2} {4}}} {{{10} {9} {5}}} {{{13} {12} {5}}}\n"
"{15}draw triangle {{{10} {9} {5}}} {{{8} {9} {5}}} {{{11} {12} {5}}}\n"
"{15}draw triangle {{{10} {9} {5}}} {{{13} {12} {5}}} {{{11} {12} {5}}}\n"
"{17}draw triangle {{{6} {3} {4}}} {{{7} {3} {4}}} {{{11} {12} {5}}}\n"
"{17}draw triangle {{{6} {3} {4}}} {{{13} {12} {5}}} {{{11} {12} {5}}}\n",
prism->xlo, prism->xhi, prism->ylo, prism->yhi, prism->zlo, prism->zhi,
prism->xlo + prism->xy, prism->xhi + prism->xy, prism->xhi + prism->xz,
prism->ylo + prism->yz, prism->xlo + prism->xz,
prism->xhi + prism->xy + prism->xz, prism->yhi + prism->yz,
prism->xlo + prism->xy + prism->xz, prism->open_faces[0] ? "# " : "",
prism->open_faces[1] ? "# " : "", prism->open_faces[2] ? "# " : "",
prism->open_faces[3] ? "# " : "", prism->open_faces[4] ? "# " : "",
prism->open_faces[5] ? "# " : "");
}
} else if (regstyle == "sphere") {
const auto sphere = dynamic_cast<RegSphere *>(region);
if (!sphere) {
error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'sphere'", region->id);
} else {
// a sphere uses a single sphere primitive
utils::print(fp, "draw sphere {{{} {} {}}} radius {} resolution {}\n", sphere->xc, sphere->yc,
sphere->zc, sphere->radius, RESOLUTION);
}
} else {
utils::logmesg(lmp,
"Cannot (yet) translate region {} of style {} to VMD graphics. Skipping... ",
region->id, region->style);
}
utils::logmesg(lmp, " done\n");
}

View File

@ -0,0 +1,41 @@
/* -*- 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 COMMAND_CLASS
// clang-format off
CommandStyle(region2vmd,Region2VMD);
// clang-format on
#else
#ifndef LMP_REGION2VMD_H
#define LMP_REGION2VMD_H
#include "command.h"
namespace LAMMPS_NS {
class Region;
class Region2VMD : public Command {
public:
Region2VMD(class LAMMPS *lmp) : Command(lmp) {};
void command(int, char **) override;
protected:
void write_region(FILE *, Region *);
};
} // namespace LAMMPS_NS
#endif
#endif

View File

@ -793,7 +793,10 @@ void CommKokkos::exchange()
} }
atomKK->sync(Host,ALL_MASK); atomKK->sync(Host,ALL_MASK);
int prev_auto_sync = lmp->kokkos->auto_sync;
lmp->kokkos->auto_sync = 1;
CommBrick::exchange(); CommBrick::exchange();
lmp->kokkos->auto_sync = prev_auto_sync;
atomKK->modified(Host,ALL_MASK); atomKK->modified(Host,ALL_MASK);
} }

View File

@ -68,12 +68,12 @@ MLIAPModelPythonKokkos<DeviceType>::MLIAPModelPythonKokkos(LAMMPS *lmp, char *co
// Recipe from lammps/src/pair_python.cpp : // Recipe from lammps/src/pair_python.cpp :
// add current directory to PYTHONPATH // add current directory to PYTHONPATH
PyObject *py_path = PySys_GetObject((char *) "path"); PyObject *py_path = PySys_GetObject((char *) "path");
PyList_Append(py_path, PY_STRING_FROM_STRING(".")); PyList_Append(py_path, PyUnicode_FromString("."));
// if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well // if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well
const char *potentials_path = getenv("LAMMPS_POTENTIALS"); const char *potentials_path = getenv("LAMMPS_POTENTIALS");
if (potentials_path != nullptr) { if (potentials_path != nullptr) {
PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); PyList_Append(py_path, PyUnicode_FromString(potentials_path));
} }
PyGILState_Release(gstate); PyGILState_Release(gstate);
if (coefffilename) read_coeffs(coefffilename); if (coefffilename) read_coeffs(coefffilename);

View File

@ -62,12 +62,12 @@ MLIAPModelPython::MLIAPModelPython(LAMMPS *lmp, char *coefffilename, bool is_chi
// Recipe from lammps/src/pair_python.cpp : // Recipe from lammps/src/pair_python.cpp :
// add current directory to PYTHONPATH // add current directory to PYTHONPATH
PyObject *py_path = PySys_GetObject((char *) "path"); PyObject *py_path = PySys_GetObject((char *) "path");
PyList_Append(py_path, PY_STRING_FROM_STRING(".")); PyList_Append(py_path, PyUnicode_FromString("."));
// if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well // if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well
const char *potentials_path = getenv("LAMMPS_POTENTIALS"); const char *potentials_path = getenv("LAMMPS_POTENTIALS");
if (potentials_path != nullptr) { if (potentials_path != nullptr) {
PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); PyList_Append(py_path, PyUnicode_FromString(potentials_path));
} }
PyGILState_Release(gstate); PyGILState_Release(gstate);
if (coefffilename) read_coeffs(coefffilename); if (coefffilename) read_coeffs(coefffilename);

View File

@ -36,6 +36,8 @@ DISTRIBUTION A. Approved for public release; distribution unlimited. OPSEC#4918
using namespace LAMMPS_NS::RANN; using namespace LAMMPS_NS::RANN;
static constexpr double SMALL = 1.0e-12;
Fingerprint_bond::Fingerprint_bond(PairRANN *_pair) : Fingerprint(_pair) Fingerprint_bond::Fingerprint_bond(PairRANN *_pair) : Fingerprint(_pair)
{ {
n_body_type = 3; n_body_type = 3;
@ -317,7 +319,8 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
i = ilist[ii]; i = ilist[ii];
itype = pair->map[type[i]]; itype = pair->map[type[i]];
int f = pair->net[itype].dimensions[0]; int f = pair->net[itype].dimensions[0];
double expr[jnum][kmax+12]; std::vector<double> row(kmax+12, 0.0);
std::vector<std::vector<double>> expr(jnum, row);
int p = kmax; int p = kmax;
int countmb=((mlength)*(mlength+1))>>1; int countmb=((mlength)*(mlength+1))>>1;
// calculate interpolation expr, rinvs and dfc, for each neighbor // calculate interpolation expr, rinvs and dfc, for each neighbor
@ -354,13 +357,13 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
expr[jj][p+1]=dely*rinvs; expr[jj][p+1]=dely*rinvs;
expr[jj][p+2]=delz*rinvs; expr[jj][p+2]=delz*rinvs;
//Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy. //Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy.
if (expr[jj][p]*expr[jj][p]<0.000000000001) { if (expr[jj][p]*expr[jj][p] < SMALL) {
expr[jj][p] = 0.000001; expr[jj][p] = 0.000001;
} }
if (expr[jj][p+1]*expr[jj][p+1]<0.000000000001) { if (expr[jj][p+1]*expr[jj][p+1] < SMALL) {
expr[jj][p+1] = 0.000001; expr[jj][p+1] = 0.000001;
} }
if (expr[jj][p+2]*expr[jj][p+2]<0.000000000001) { if (expr[jj][p+2]*expr[jj][p+2] < SMALL) {
expr[jj][p+2] = 0.000001; expr[jj][p+2] = 0.000001;
} }
expr[jj][p+3] = -dfc*expr[jj][p]; expr[jj][p+3] = -dfc*expr[jj][p];
@ -377,7 +380,7 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
int kb = kmax; int kb = kmax;
int mb = mlength; int mb = mlength;
count = startingneuron; count = startingneuron;
double Bb[mb]; std::vector<double> Bb(mb, 0.0);
double dBbx; double dBbx;
double dBby; double dBby;
double dBbz; double dBbz;
@ -397,7 +400,7 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
} }
for (n=0;n<kb;n++) { for (n=0;n<kb;n++) {
for (a1=0;a1<mb;a1++) { for (a1=0;a1<mb;a1++) {
Bb[a1]=0; Bb[a1]=0.0;
} }
ai = n; ai = n;
double y1 = alpha_k[ai]/re; double y1 = alpha_k[ai]/re;
@ -409,7 +412,7 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
continue; continue;
} }
double yprod = expr[jj][ai]; double yprod = expr[jj][ai];
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
yprod *= y4[M[a2+1]]; yprod *= y4[M[a2+1]];
} }
@ -419,10 +422,7 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
} }
} }
if (atomtypes[1]!=atomtypes[2]) {//Bb!=Bg if (atomtypes[1]!=atomtypes[2]) {//Bb!=Bg
double Bg[mb]; std::vector<double> Bg(mb, 0.0);
for (a1=0;a1<mb;a1++) {
Bg[a1]=0;
}
ai = n; ai = n;
double y1 = alpha_k[ai]/re; double y1 = alpha_k[ai]/re;
//loop over ktype to get Bg //loop over ktype to get Bg
@ -433,7 +433,7 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
continue; continue;
} }
double yprod = expr[jj][ai]; double yprod = expr[jj][ai];
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
yprod *= y4[M[a2+1]]; yprod *= y4[M[a2+1]];
} }
@ -450,8 +450,8 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
if (atomtypes[2] != nelements && atomtypes[2] != jtype) { if (atomtypes[2] != nelements && atomtypes[2] != jtype) {
continue; continue;
} }
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -477,8 +477,8 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
if (atomtypes[1] != nelements && atomtypes[1] != jtype) { if (atomtypes[1] != nelements && atomtypes[1] != jtype) {
continue; continue;
} }
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -512,8 +512,8 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do
if (atomtypes[1] != nelements && atomtypes[1] != jtype) { if (atomtypes[1] != nelements && atomtypes[1] != jtype) {
continue; continue;
} }
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -572,16 +572,18 @@ void Fingerprint_bond::do3bodyfeatureset_doubleneighborloop(double * features,do
i = ilist[ii]; i = ilist[ii];
itype = pair->map[type[i]]; itype = pair->map[type[i]];
int f = pair->net[itype].dimensions[0]; int f = pair->net[itype].dimensions[0];
double expr[jnum][kmax]; std::vector<double> row(kmax, 0.0);
double y[jnum][3]; std::vector<std::vector<double>> expr(jnum, row);
double ri[jnum]; std::vector<double> yrow(3, 0.0);
double dfc[jnum]; std::vector<std::vector<double>> y(jnum, yrow);
std::vector<double> ri(jnum, 0.0);
std::vector<double> dfc(jnum, 0.0);
int kb = kmax; int kb = kmax;
int mb = mlength; int mb = mlength;
double c41[kmax]; std::vector<double> c41(kmax, 0.0);
double c51[kmax]; std::vector<double> c51(kmax, 0.0);
double c61[kmax]; std::vector<double> c61(kmax, 0.0);
double ct[kmax]; std::vector<double> ct(kmax, 0.0);
for (jj = 0; jj < jnum; jj++) { for (jj = 0; jj < jnum; jj++) {
jtype = tn[jj]; jtype = tn[jj];
if (jtypes != nelements && jtypes != jtype && ktypes != nelements && ktypes != jtype) { if (jtypes != nelements && jtypes != jtype && ktypes != nelements && ktypes != jtype) {

View File

@ -36,6 +36,8 @@ DISTRIBUTION A. Approved for public release; distribution unlimited. OPSEC#4918
using namespace LAMMPS_NS::RANN; using namespace LAMMPS_NS::RANN;
static constexpr double SMALL = 1.0e-12;
Fingerprint_bondscreened::Fingerprint_bondscreened(PairRANN *_pair) : Fingerprint(_pair) Fingerprint_bondscreened::Fingerprint_bondscreened(PairRANN *_pair) : Fingerprint(_pair)
{ {
n_body_type = 3; n_body_type = 3;
@ -319,7 +321,8 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
i = ilist[ii]; i = ilist[ii];
itype = pair->map[type[i]]; itype = pair->map[type[i]];
int f = pair->net[itype].dimensions[0]; int f = pair->net[itype].dimensions[0];
double expr[jnum][kmax+12]; std::vector<double> row(kmax+12, 0.0);
std::vector<std::vector<double>> expr(jnum, row);
int p = kmax; int p = kmax;
int countmb=((mlength)*(mlength+1))>>1; int countmb=((mlength)*(mlength+1))>>1;
// calculate interpolation expr, rinvs and dfc, for each neighbor // calculate interpolation expr, rinvs and dfc, for each neighbor
@ -358,13 +361,13 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
expr[jj][p+1]=dely*rinvs; expr[jj][p+1]=dely*rinvs;
expr[jj][p+2]=delz*rinvs; expr[jj][p+2]=delz*rinvs;
//Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy. //Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy.
if (expr[jj][p]*expr[jj][p]<0.000000000001) { if (expr[jj][p]*expr[jj][p] < SMALL) {
expr[jj][p] = 0.000001; expr[jj][p] = 0.000001;
} }
if (expr[jj][p+1]*expr[jj][p+1]<0.000000000001) { if (expr[jj][p+1]*expr[jj][p+1] < SMALL) {
expr[jj][p+1] = 0.000001; expr[jj][p+1] = 0.000001;
} }
if (expr[jj][p+2]*expr[jj][p+2]<0.000000000001) { if (expr[jj][p+2]*expr[jj][p+2] < SMALL) {
expr[jj][p+2] = 0.000001; expr[jj][p+2] = 0.000001;
} }
expr[jj][p+3] = -dfc*expr[jj][p]-dSikx[jj]; expr[jj][p+3] = -dfc*expr[jj][p]-dSikx[jj];
@ -381,13 +384,13 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
int kb = kmax; int kb = kmax;
int mb = mlength; int mb = mlength;
count = startingneuron; count = startingneuron;
double Bb[mb]; std::vector<double> Bb(mb, 0.0);
double dBbx; double dBbx;
double dBby; double dBby;
double dBbz; double dBbz;
double dBbx1[mb]; std::vector<double> dBbx1(mb, 0.0);
double dBby1[mb]; std::vector<double> dBby1(mb, 0.0);
double dBbz1[mb]; std::vector<double> dBbz1(mb, 0.0);
double yprod; double yprod;
for (mcount=0;mcount<countmb;mcount++) { for (mcount=0;mcount<countmb;mcount++) {
int *M = Mf[mcount]; int *M = Mf[mcount];
@ -420,7 +423,7 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
continue; continue;
} }
double yprod = expr[jj][ai]; double yprod = expr[jj][ai];
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
yprod *= y4[M[a2+1]]; yprod *= y4[M[a2+1]];
} }
@ -430,10 +433,7 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
} }
} }
if (atomtypes[1]!=atomtypes[2]) {//Bb!=Bg if (atomtypes[1]!=atomtypes[2]) {//Bb!=Bg
double Bg[mb]; std::vector<double> Bg(mb, 0.0);
for (a1=0;a1<mb;a1++) {
Bg[a1]=0;
}
ai = n; ai = n;
double y1 = alpha_k[ai]/re; double y1 = alpha_k[ai]/re;
//loop over ktype to get Bg //loop over ktype to get Bg
@ -445,7 +445,7 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
continue; continue;
} }
double yprod = expr[jj][ai]; double yprod = expr[jj][ai];
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
yprod *= y4[M[a2+1]]; yprod *= y4[M[a2+1]];
} }
@ -463,8 +463,8 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
if (atomtypes[2] != nelements && atomtypes[2] != jtype) { if (atomtypes[2] != nelements && atomtypes[2] != jtype) {
continue; continue;
} }
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -500,8 +500,8 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
if (atomtypes[1] != nelements && atomtypes[1] != jtype) { if (atomtypes[1] != nelements && atomtypes[1] != jtype) {
continue; continue;
} }
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -545,8 +545,8 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea
if (atomtypes[1] != nelements && atomtypes[1] != jtype) { if (atomtypes[1] != nelements && atomtypes[1] != jtype) {
continue; continue;
} }
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -615,17 +615,20 @@ void Fingerprint_bondscreened::do3bodyfeatureset_doubleneighborloop(double * fea
i = ilist[ii]; i = ilist[ii];
itype = pair->map[type[i]]; itype = pair->map[type[i]];
int f = pair->net[itype].dimensions[0]; int f = pair->net[itype].dimensions[0];
double expr[jnum][kmax]; std::vector<double> row(kmax, 0.0);
double y[jnum][3]; std::vector<std::vector<double>> expr(jnum, row);
double ri[jnum]; std::vector<double> yrow(3, 0.0);
double dfc[jnum]; std::vector<std::vector<double>> y(jnum, yrow);
std::vector<double> ri(jnum, 0.0);
std::vector<double> dfc(jnum, 0.0);
int kb = kmax; int kb = kmax;
int mb = mlength; int mb = mlength;
double Bijk[kb][mb]; std::vector<double> brow(mb, 0.0);
double c41[kmax]; std::vector<std::vector<double>> Bijk(kb, brow);
double c51[kmax]; std::vector<double> c41(kmax, 0.0);
double c61[kmax]; std::vector<double> c51(kmax, 0.0);
double ct[kmax]; std::vector<double> c61(kmax, 0.0);
std::vector<double> ct(kmax, 0.0);
for (jj = 0; jj < jnum; jj++) { for (jj = 0; jj < jnum; jj++) {
if (Bij[jj]==false) {continue;} if (Bij[jj]==false) {continue;}
jtype = tn[jj]; jtype = tn[jj];

View File

@ -35,6 +35,8 @@ DISTRIBUTION A. Approved for public release; distribution unlimited. OPSEC#4918
using namespace LAMMPS_NS::RANN; using namespace LAMMPS_NS::RANN;
static constexpr double SMALL = 1.0e-12;
Fingerprint_bondscreenedspin::Fingerprint_bondscreenedspin(PairRANN *_pair) : Fingerprint(_pair) Fingerprint_bondscreenedspin::Fingerprint_bondscreenedspin(PairRANN *_pair) : Fingerprint(_pair)
{ {
n_body_type = 3; n_body_type = 3;
@ -320,7 +322,8 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
i = ilist[ii]; i = ilist[ii];
itype = pair->map[type[i]]; itype = pair->map[type[i]];
int f = pair->net[itype].dimensions[0]; int f = pair->net[itype].dimensions[0];
double expr[jnum][kmax+12]; std::vector<double> row(kmax+12, 0.0);
std::vector<std::vector<double>> expr(jnum, row);
int p = kmax; int p = kmax;
int countmb=((mlength)*(mlength+1))>>1; int countmb=((mlength)*(mlength+1))>>1;
double *si = sim->s[i]; double *si = sim->s[i];
@ -360,13 +363,13 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
expr[jj][p+1]=dely*rinvs; expr[jj][p+1]=dely*rinvs;
expr[jj][p+2]=delz*rinvs; expr[jj][p+2]=delz*rinvs;
//Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy. //Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy.
if (expr[jj][p]*expr[jj][p]<0.000000000001) { if (expr[jj][p]*expr[jj][p] < SMALL) {
expr[jj][p] = 0.000001; expr[jj][p] = 0.000001;
} }
if (expr[jj][p+1]*expr[jj][p+1]<0.000000000001) { if (expr[jj][p+1]*expr[jj][p+1] < SMALL) {
expr[jj][p+1] = 0.000001; expr[jj][p+1] = 0.000001;
} }
if (expr[jj][p+2]*expr[jj][p+2]<0.000000000001) { if (expr[jj][p+2]*expr[jj][p+2] < SMALL) {
expr[jj][p+2] = 0.000001; expr[jj][p+2] = 0.000001;
} }
expr[jj][p+3] = -dfc*expr[jj][p]-dSikx[jj]; expr[jj][p+3] = -dfc*expr[jj][p]-dSikx[jj];
@ -383,8 +386,8 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
int kb = kmax; int kb = kmax;
int mb = mlength; int mb = mlength;
count = startingneuron; count = startingneuron;
double Bb[mb]; std::vector<double> Bb(mb, 0.0);
double Bbs[mb]; std::vector<double> Bbs(mb, 0.0);
double dBbx; double dBbx;
double dBby; double dBby;
double dBbz; double dBbz;
@ -421,7 +424,7 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double yprod = expr[jj][ai]; double yprod = expr[jj][ai];
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
yprod *= y4[M[a2+1]]; yprod *= y4[M[a2+1]];
} }
@ -432,12 +435,8 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
} }
} }
if (atomtypes[1]!=atomtypes[2]) {//Bb!=Bg if (atomtypes[1]!=atomtypes[2]) {//Bb!=Bg
double Bg[mb]; std::vector<double> Bg(mb, 0.0);
double Bgs[mb]; std::vector<double> Bgs(mb, 0.0);
for (a1=0;a1<mb;a1++) {
Bg[a1]=0;
Bgs[a1]=0;
}
ai = n; ai = n;
double y1 = alpha_k[ai]/re; double y1 = alpha_k[ai]/re;
//loop over ktype to get Bg //loop over ktype to get Bg
@ -452,7 +451,7 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double yprod = expr[jj][ai]; double yprod = expr[jj][ai];
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
yprod *= y4[M[a2+1]]; yprod *= y4[M[a2+1]];
} }
@ -474,8 +473,8 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
j = jl[jj]; j = jl[jj];
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -517,8 +516,8 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
j = jl[jj]; j = jl[jj];
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -568,8 +567,8 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double *
j = jl[jj]; j = jl[jj];
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -641,18 +640,21 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_doubleneighborloop(double *
i = ilist[ii]; i = ilist[ii];
itype = pair->map[type[i]]; itype = pair->map[type[i]];
int f = pair->net[itype].dimensions[0]; int f = pair->net[itype].dimensions[0];
double expr[jnum][kmax]; std::vector<double> row(kmax, 0.0);
double y[jnum][3]; std::vector<std::vector<double>> expr(jnum, row);
double ri[jnum]; std::vector<double> yrow(3, 0.0);
double dfc[jnum]; std::vector<std::vector<double>> y(jnum, yrow);
std::vector<double> ri(jnum, 0.0);
std::vector<double> dfc(jnum, 0.0);
int kb = kmax; int kb = kmax;
int mb = mlength; int mb = mlength;
double Bijk[kb][mb];
double c41[kmax];
double c51[kmax];
double c61[kmax];
double ct[kmax];
double *si = sim->s[i]; double *si = sim->s[i];
std::vector<double> brow(mb, 0.0);
std::vector<std::vector<double>> Bijk(kb, brow);
std::vector<double> c41(kmax, 0.0);
std::vector<double> c51(kmax, 0.0);
std::vector<double> c61(kmax, 0.0);
std::vector<double> ct(kmax, 0.0);
for (jj = 0; jj < jnum; jj++) { for (jj = 0; jj < jnum; jj++) {
if (Bij[jj]==false) {continue;} if (Bij[jj]==false) {continue;}
jtype = tn[jj]; jtype = tn[jj];

View File

@ -35,6 +35,8 @@ DISTRIBUTION A. Approved for public release; distribution unlimited. OPSEC#4918
using namespace LAMMPS_NS::RANN; using namespace LAMMPS_NS::RANN;
static constexpr double SMALL = 1.0e-12;
Fingerprint_bondspin::Fingerprint_bondspin(PairRANN *_pair) : Fingerprint(_pair) Fingerprint_bondspin::Fingerprint_bondspin(PairRANN *_pair) : Fingerprint(_pair)
{ {
n_body_type = 3; n_body_type = 3;
@ -317,7 +319,8 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
i = ilist[ii]; i = ilist[ii];
itype = pair->map[type[i]]; itype = pair->map[type[i]];
int f = pair->net[itype].dimensions[0]; int f = pair->net[itype].dimensions[0];
double expr[jnum][kmax+12]; std::vector<double> row(kmax+12, 0.0);
std::vector<std::vector<double>> expr(jnum, row);
int p = kmax; int p = kmax;
int countmb=((mlength)*(mlength+1))>>1; int countmb=((mlength)*(mlength+1))>>1;
double *si = sim->s[i]; double *si = sim->s[i];
@ -355,13 +358,13 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
expr[jj][p+1]=dely*rinvs; expr[jj][p+1]=dely*rinvs;
expr[jj][p+2]=delz*rinvs; expr[jj][p+2]=delz*rinvs;
//Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy. //Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy.
if (expr[jj][p]*expr[jj][p]<0.000000000001) { if (expr[jj][p]*expr[jj][p] < SMALL) {
expr[jj][p] = 0.000001; expr[jj][p] = 0.000001;
} }
if (expr[jj][p+1]*expr[jj][p+1]<0.000000000001) { if (expr[jj][p+1]*expr[jj][p+1] < SMALL) {
expr[jj][p+1] = 0.000001; expr[jj][p+1] = 0.000001;
} }
if (expr[jj][p+2]*expr[jj][p+2]<0.000000000001) { if (expr[jj][p+2]*expr[jj][p+2] < SMALL) {
expr[jj][p+2] = 0.000001; expr[jj][p+2] = 0.000001;
} }
expr[jj][p+3] = -dfc*expr[jj][p]; expr[jj][p+3] = -dfc*expr[jj][p];
@ -378,8 +381,8 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
int kb = kmax; int kb = kmax;
int mb = mlength; int mb = mlength;
count = startingneuron; count = startingneuron;
double Bb[mb]; std::vector<double> Bb(mb, 0.0);
double Bbs[mb]; std::vector<double> Bbs(mb, 0.0);
double dBbx; double dBbx;
double dBby; double dBby;
double dBbz; double dBbz;
@ -415,7 +418,7 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double yprod = expr[jj][ai]; double yprod = expr[jj][ai];
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
yprod *= y4[M[a2+1]]; yprod *= y4[M[a2+1]];
} }
@ -426,12 +429,8 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
} }
} }
if (atomtypes[1]!=atomtypes[2]) {//Bb!=Bg if (atomtypes[1]!=atomtypes[2]) {//Bb!=Bg
double Bg[mb]; std::vector<double> Bg(mb, 0.0);
double Bgs[mb]; std::vector<double> Bgs(mb, 0.0);
for (a1=0;a1<mb;a1++) {
Bg[a1]=0;
Bgs[a1]=0;
}
ai = n; ai = n;
double y1 = alpha_k[ai]/re; double y1 = alpha_k[ai]/re;
//loop over ktype to get Bg //loop over ktype to get Bg
@ -445,7 +444,7 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double yprod = expr[jj][ai]; double yprod = expr[jj][ai];
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
yprod *= y4[M[a2+1]]; yprod *= y4[M[a2+1]];
} }
@ -466,8 +465,8 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
j = jl[jj]; j = jl[jj];
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -502,8 +501,8 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
j = jl[jj]; j = jl[jj];
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -546,8 +545,8 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature
j = jl[jj]; j = jl[jj];
double *sj = sim->s[j]; double *sj = sim->s[j];
double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2];
double *y3 = &expr[jj][p+3]; double *y3 = expr[jj].data() + p + 3;
double *y4 = &expr[jj][p]; double *y4 = expr[jj].data() + p;
ai = n; ai = n;
yprod = expr[jj][ai]; yprod = expr[jj][ai];
for (a2=0;a2<a;a2++) { for (a2=0;a2<a;a2++) {
@ -612,16 +611,18 @@ void Fingerprint_bondspin::do3bodyfeatureset_doubleneighborloop(double * feature
i = ilist[ii]; i = ilist[ii];
itype = pair->map[type[i]]; itype = pair->map[type[i]];
int f = pair->net[itype].dimensions[0]; int f = pair->net[itype].dimensions[0];
double expr[jnum][kmax]; std::vector<double> row(kmax, 0.0);
double y[jnum][3]; std::vector<std::vector<double>> expr(jnum, row);
double ri[jnum]; std::vector<double> yrow(3, 0.0);
double dfc[jnum]; std::vector<std::vector<double>> y(jnum, yrow);
std::vector<double> ri(jnum, 0.0);
std::vector<double> dfc(jnum, 0.0);
int kb = kmax; int kb = kmax;
int mb = mlength; int mb = mlength;
double c41[kmax]; std::vector<double> c41(kmax, 0.0);
double c51[kmax]; std::vector<double> c51(kmax, 0.0);
double c61[kmax]; std::vector<double> c61(kmax, 0.0);
double ct[kmax]; std::vector<double> ct(kmax, 0.0);
double *si = sim->s[i]; double *si = sim->s[i];
for (jj = 0; jj < jnum; jj++) { for (jj = 0; jj < jnum; jj++) {
jtype = tn[jj]; jtype = tn[jj];

View File

@ -2,6 +2,12 @@
SHELL = /bin/bash SHELL = /bin/bash
PYTHON = python PYTHON = python
PYTHON_VERSION=$(word 2,$(shell $(PYTHON) -V 2>&1 | tr '.' ' '))
ifeq ($(PYTHON_VERSION),2)
PYTHON_CHECK=@echo LAMMPS requires Python 3. Try: 'make PYTHON=python3 ...' ; exit 1
else
PYTHON_CHECK=@echo
endif
DYN_LIB = -ldl DYN_LIB = -ldl
#.IGNORE: #.IGNORE:
@ -276,7 +282,7 @@ LIBDIR = $(@:lib-%=%)
# List of all targets # List of all targets
help: help:
@echo '' $(PYTHON_CHECK)
@echo 'make clean-all delete all object files' @echo 'make clean-all delete all object files'
@echo 'make clean-machine delete object files for one machine' @echo 'make clean-machine delete object files for one machine'
@echo 'make mpi-stubs build dummy MPI library in STUBS' @echo 'make mpi-stubs build dummy MPI library in STUBS'
@ -378,6 +384,7 @@ gitversion:
# shared = shared compile in Obj_shared_machine # shared = shared compile in Obj_shared_machine
.DEFAULT: .DEFAULT:
$(PYTHON_CHECK)
@if [ $@ = "serial" ]; \ @if [ $@ = "serial" ]; \
then cd STUBS; $(MAKE); cd ..; fi then cd STUBS; $(MAKE); cd ..; fi
@test -f MAKE/Makefile.$@ -o -f MAKE/OPTIONS/Makefile.$@ -o \ @test -f MAKE/Makefile.$@ -o -f MAKE/OPTIONS/Makefile.$@ -o \
@ -465,6 +472,7 @@ mpi-stubs:
sinclude ../lib/python/Makefile.lammps sinclude ../lib/python/Makefile.lammps
install-python: install-python:
$(PYTHON_CHECK)
@rm -rf ../python/build @rm -rf ../python/build
@$(PYTHON) ../python/install.py -p ../python/lammps -l ../src/liblammps.so -w $(PWD) -v $(PWD)/version.h @$(PYTHON) ../python/install.py -p ../python/lammps -l ../src/liblammps.so -w $(PWD) -v $(PWD)/version.h
@ -483,49 +491,59 @@ tar:
check: check-whitespace check-permissions check-homepage check-errordocs check-fmtlib check-docs check-version check: check-whitespace check-permissions check-homepage check-errordocs check-fmtlib check-docs check-version
check-whitespace: check-whitespace:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/whitespace.py .. $(PYTHON) ../tools/coding_standard/whitespace.py ..
fix-whitespace: fix-whitespace:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/whitespace.py .. -f $(PYTHON) ../tools/coding_standard/whitespace.py .. -f
check-permissions: check-permissions:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/permissions.py .. $(PYTHON) ../tools/coding_standard/permissions.py ..
fix-permissions: fix-permissions:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/permissions.py .. -f $(PYTHON) ../tools/coding_standard/permissions.py .. -f
check-homepage: check-homepage:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/homepage.py .. $(PYTHON) ../tools/coding_standard/homepage.py ..
fix-homepage: fix-homepage:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/homepage.py .. -f $(PYTHON) ../tools/coding_standard/homepage.py .. -f
check-errordocs: check-errordocs:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/errordocs.py .. $(PYTHON) ../tools/coding_standard/errordocs.py ..
fix-errordocs: fix-errordocs:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/errordocs.py .. -f $(PYTHON) ../tools/coding_standard/errordocs.py .. -f
check-fmtlib: check-fmtlib:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/fmtlib.py .. $(PYTHON) ../tools/coding_standard/fmtlib.py ..
fix-fmtlib: fix-fmtlib:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/fmtlib.py .. -f $(PYTHON) ../tools/coding_standard/fmtlib.py .. -f
check-docs: check-docs:
$(PYTHON_CHECK)
$(MAKE) $(MFLAGS) -C ../doc anchor_check style_check package_check role_check $(MAKE) $(MFLAGS) -C ../doc anchor_check style_check package_check role_check
check-version: check-version:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/versiontags.py .. || echo $(PYTHON) ../tools/coding_standard/versiontags.py .. || echo
format-src: format-src:
clang-format -i --verbose --style=file *.cpp *.h */*.cpp */*.h clang-format -i --verbose --style=file *.cpp *.h */*.cpp */*.h
format-tests: format-tests:
clang-format -i --verbose --style=file ../unittest/*/*.cpp ../unittest/*/*.h clang-format -i --verbose --style=file ../unittest/*/*.cpp ../unittest/*/*.h
# Package management # Package management
package: package:

View File

@ -70,7 +70,7 @@ FixPythonInvoke::FixPythonInvoke(LAMMPS *lmp, int narg, char **arg) :
error->all(FLERR,"Could not find Python function"); error->all(FLERR,"Could not find Python function");
} }
lmpPtr = PY_VOID_POINTER(lmp); lmpPtr = PyCapsule_New((void *)lmp, nullptr, nullptr);
// nvalid = next step on which end_of_step or post_force does something // nvalid = next step on which end_of_step or post_force does something
// add nextvalid() to all computes that store invocation times // add nextvalid() to all computes that store invocation times

View File

@ -44,7 +44,7 @@ FixPythonMove::FixPythonMove(LAMMPS *lmp, int narg, char **arg) :
// add current directory to PYTHONPATH // add current directory to PYTHONPATH
PyObject *py_path = PySys_GetObject((char *)"path"); PyObject *py_path = PySys_GetObject((char *)"path");
PyList_Append(py_path, PY_STRING_FROM_STRING(".")); PyList_Append(py_path, PyUnicode_FromString("."));
// create integrator instance // create integrator instance
@ -73,7 +73,7 @@ FixPythonMove::FixPythonMove(LAMMPS *lmp, int narg, char **arg) :
error->all(FLERR,"Could not find integrator class {} in module {}", cls_name, module_name); error->all(FLERR,"Could not find integrator class {} in module {}", cls_name, module_name);
} }
PyObject *ptr = PY_VOID_POINTER(lmp); PyObject *ptr = PyCapsule_New((void *)lmp, nullptr, nullptr);
PyObject *py_move_obj = PyObject_CallFunction(py_move_type, (char *)"O", ptr); PyObject *py_move_obj = PyObject_CallFunction(py_move_type, (char *)"O", ptr);
Py_CLEAR(ptr); Py_CLEAR(ptr);

View File

@ -54,14 +54,14 @@ PairPython::PairPython(LAMMPS *lmp) : Pair(lmp) {
PyUtils::GIL lock; PyUtils::GIL lock;
PyObject *py_path = PySys_GetObject((char *)"path"); PyObject *py_path = PySys_GetObject((char *)"path");
PyList_Append(py_path, PY_STRING_FROM_STRING(".")); PyList_Append(py_path, PyUnicode_FromString("."));
// if LAMMPS_POTENTIALS environment variable is set, // if LAMMPS_POTENTIALS environment variable is set,
// add it to PYTHONPATH as well // add it to PYTHONPATH as well
const char *potentials_path = getenv("LAMMPS_POTENTIALS"); const char *potentials_path = getenv("LAMMPS_POTENTIALS");
if (potentials_path != nullptr) { if (potentials_path != nullptr) {
PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); PyList_Append(py_path, PyUnicode_FromString(potentials_path));
} }
} }

View File

@ -16,22 +16,11 @@
#include <Python.h> #include <Python.h>
// Wrap API changes between Python 2 and 3 using macros #if PY_VERSION_HEX < 0x030600f0
#if PY_MAJOR_VERSION == 2 #error Python version 3.6 or later is required by LAMMPS
#if defined(_MSC_VER) || defined(__MINGW32__)
#define PY_INT_FROM_LONG(X) PyLong_FromLongLong(X)
#define PY_INT_AS_LONG(X) PyLong_AsLongLong(X)
#define PY_LONG_FROM_STRING(X) std::stoll(X)
#else
#define PY_INT_FROM_LONG(X) PyInt_FromLong(X)
#define PY_INT_AS_LONG(X) PyInt_AsLong(X)
#define PY_LONG_FROM_STRING(X) std::stol(X)
#endif #endif
#define PY_STRING_FROM_STRING(X) PyString_FromString(X)
#define PY_VOID_POINTER(X) PyCObject_FromVoidPtr((void *) X, nullptr)
#define PY_STRING_AS_STRING(X) PyString_AsString(X)
#elif PY_MAJOR_VERSION == 3 // Wrap API differences between platforms using macros
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define PY_INT_FROM_LONG(X) PyLong_FromLongLong(X) #define PY_INT_FROM_LONG(X) PyLong_FromLongLong(X)
#define PY_INT_AS_LONG(X) PyLong_AsLongLong(X) #define PY_INT_AS_LONG(X) PyLong_AsLongLong(X)
@ -41,9 +30,5 @@
#define PY_INT_AS_LONG(X) PyLong_AsLong(X) #define PY_INT_AS_LONG(X) PyLong_AsLong(X)
#define PY_LONG_FROM_STRING(X) std::stol(X) #define PY_LONG_FROM_STRING(X) std::stol(X)
#endif #endif
#define PY_STRING_FROM_STRING(X) PyUnicode_FromString(X)
#define PY_VOID_POINTER(X) PyCapsule_New((void *) X, nullptr, nullptr)
#define PY_STRING_AS_STRING(X) PyUnicode_AsUTF8(X)
#endif
#endif #endif

View File

@ -361,12 +361,12 @@ void PythonImpl::invoke_function(int ifunc, char *result)
if (!str) if (!str)
error->all(FLERR, "Could not evaluate Python function {} input variable: {}", error->all(FLERR, "Could not evaluate Python function {} input variable: {}",
pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]); pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]);
pValue = PY_STRING_FROM_STRING(str); pValue = PyUnicode_FromString(str);
} else { } else {
pValue = PY_STRING_FROM_STRING(pfuncs[ifunc].svalue[i]); pValue = PyUnicode_FromString(pfuncs[ifunc].svalue[i]);
} }
} else if (itype == PTR) { } else if (itype == PTR) {
pValue = PY_VOID_POINTER(lmp); pValue = PyCapsule_New((void *)lmp, nullptr, nullptr);
} else { } else {
error->all(FLERR, "Unsupported variable type: {}", itype); error->all(FLERR, "Unsupported variable type: {}", itype);
} }
@ -397,7 +397,7 @@ void PythonImpl::invoke_function(int ifunc, char *result)
auto value = fmt::format("{:.15g}", PyFloat_AsDouble(pValue)); auto value = fmt::format("{:.15g}", PyFloat_AsDouble(pValue));
strncpy(result, value.c_str(), Variable::VALUELENGTH - 1); strncpy(result, value.c_str(), Variable::VALUELENGTH - 1);
} else if (otype == STRING) { } else if (otype == STRING) {
const char *pystr = PY_STRING_AS_STRING(pValue); const char *pystr = PyUnicode_AsUTF8(pValue);
if (pfuncs[ifunc].longstr) if (pfuncs[ifunc].longstr)
strncpy(pfuncs[ifunc].longstr, pystr, pfuncs[ifunc].length_longstr); strncpy(pfuncs[ifunc].longstr, pystr, pfuncs[ifunc].length_longstr);
else else

View File

@ -965,6 +965,7 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec)
int *mask = atom->mask; int *mask = atom->mask;
double *mass = atom->mass; double *mass = atom->mass;
double *rmass = atom->rmass; double *rmass = atom->rmass;
int *type = atom->type;
double localmass, totalmass; double localmass, totalmass;
std::string species_str; std::string species_str;
@ -1013,12 +1014,12 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec)
if (!(mask[i] & groupbit)) continue; if (!(mask[i] & groupbit)) continue;
cid = nint(clusterID[i]); cid = nint(clusterID[i]);
if (cid == m) { if (cid == m) {
itype = ele2uele[atom->type[i] - 1]; itype = ele2uele[type[i] - 1];
Name[itype]++; Name[itype]++;
count++; count++;
marklist[nmarklist++] = i; marklist[nmarklist++] = i;
if (rmass) localmass += rmass[i]; if (rmass) localmass += rmass[i];
else localmass += atom->mass[atom->type[i]]; else localmass += mass[type[i]];
} }
} }

View File

@ -26,6 +26,7 @@
#include "force.h" #include "force.h"
#include "input.h" #include "input.h"
#include "math_const.h" #include "math_const.h"
#include "safe_pointers.h"
#include "update.h" #include "update.h"
#include <cmath> #include <cmath>
@ -79,13 +80,12 @@ void AngleWrite::command(int narg, char **arg)
// otherwise make certain that units are consistent // otherwise make certain that units are consistent
// print header in format used by angle_style table // print header in format used by angle_style table
FILE *fp = nullptr; SafeFilePtr fp;
std::string coeffs_file = table_file + ".tmp.coeffs"; std::string coeffs_file = table_file + ".tmp.coeffs";
if (comm->me == 0) { if (comm->me == 0) {
fp = fopen(coeffs_file.c_str(), "w"); SafeFilePtr coeffs = fopen(coeffs_file.c_str(), "w");
force->angle->write_data(fp); force->angle->write_data(coeffs);
fclose(fp);
// units sanity check: // units sanity check:
// - if this is the first time we write to this potential file, // - if this is the first time we write to this potential file,
@ -145,16 +145,14 @@ void AngleWrite::command(int narg, char **arg)
writer->input->one("pair_coeff * *"); writer->input->one("pair_coeff * *");
writer->input->one("mass * 1.0"); writer->input->one("mass * 1.0");
writer->input->one(fmt::format("angle_style {}", force->angle_style)); writer->input->one(fmt::format("angle_style {}", force->angle_style));
FILE *coeffs;
char line[MAXLINE] = {'\0'}; char line[MAXLINE] = {'\0'};
coeffs = fopen(coeffs_file.c_str(), "r"); SafeFilePtr coeffs = fopen(coeffs_file.c_str(), "r");
if (!coeffs) if (!coeffs)
error->one(FLERR, "Unable to open temporary file {}: {}", coeffs_file, utils::getsyserror()); error->one(FLERR, "Unable to open temporary file {}: {}", coeffs_file, utils::getsyserror());
for (int i = 0; i < atom->nangletypes; ++i) { for (int i = 0; i < atom->nangletypes; ++i) {
utils::sfgets(FLERR, line, MAXLINE, coeffs, coeffs_file.c_str(), error); utils::sfgets(FLERR, line, MAXLINE, coeffs, coeffs_file.c_str(), error);
writer->input->one(fmt::format("angle_coeff {}", line)); writer->input->one(fmt::format("angle_coeff {}", line));
} }
fclose(coeffs);
platform::unlink(coeffs_file); platform::unlink(coeffs_file);
// initialize system // initialize system
@ -221,7 +219,6 @@ void AngleWrite::command(int narg, char **arg)
// clean up // clean up
delete writer; delete writer;
fclose(fp);
} }
MPI_Comm_free(&singlecomm); MPI_Comm_free(&singlecomm);
} }

View File

@ -20,6 +20,7 @@
#include "force.h" #include "force.h"
#include "memory.h" #include "memory.h"
#include "neighbor.h" #include "neighbor.h"
#include "safe_pointers.h"
#include "suffix.h" #include "suffix.h"
#include "update.h" #include "update.h"
@ -365,7 +366,7 @@ void Bond::write_file(int narg, char **arg)
// add line with DATE: and UNITS: tag when creating new file // add line with DATE: and UNITS: tag when creating new file
// print header in format used by bond_style table // print header in format used by bond_style table
FILE *fp = nullptr; SafeFilePtr fp;
if (comm->me == 0) { if (comm->me == 0) {
std::string table_file = arg[4]; std::string table_file = arg[4];
@ -419,7 +420,6 @@ void Bond::write_file(int narg, char **arg)
e = single(btype, r * r, itype, jtype, f); e = single(btype, r * r, itype, jtype, f);
fprintf(fp, "%8d %- 22.15g %- 22.15g %- 22.15g\n", i + 1, r, e, f * r); fprintf(fp, "%8d %- 22.15g %- 22.15g %- 22.15g\n", i + 1, r, e, f * r);
} }
fclose(fp);
} }
} }

View File

@ -34,6 +34,7 @@
#include "random_mars.h" #include "random_mars.h"
#include "random_park.h" #include "random_park.h"
#include "region.h" #include "region.h"
#include "safe_pointers.h"
#include "special.h" #include "special.h"
#include "text_file_reader.h" #include "text_file_reader.h"
#include "variable.h" #include "variable.h"
@ -1082,8 +1083,9 @@ void CreateAtoms::add_mesh(const char *filename)
molid = maxmol + 1; molid = maxmol + 1;
} }
FILE *fp = fopen(filename, "rb"); SafeFilePtr fp = fopen(filename, "rb");
if (fp == nullptr) error->one(FLERR, "Cannot open file {}: {}", filename, utils::getsyserror()); if (fp == nullptr)
error->one(FLERR, "Cannot open STL mesh file {}: {}", filename, utils::getsyserror());
// first try reading the file in ASCII format // first try reading the file in ASCII format
@ -1184,7 +1186,7 @@ void CreateAtoms::add_mesh(const char *filename)
} }
} }
} else { } else {
error->all(FLERR, "Error reading triangles from file {}: {}", filename, e.what()); error->all(FLERR, "Error reading triangles from STL mesh file {}: {}", filename, e.what());
} }
} }
@ -1195,7 +1197,6 @@ void CreateAtoms::add_mesh(const char *filename)
utils::logmesg(lmp, " read {} triangles with {:.2f} atoms per triangle added in {} mode\n", utils::logmesg(lmp, " read {} triangles with {:.2f} atoms per triangle added in {} mode\n",
ntriangle, ratio, mesh_name[mesh_style]); ntriangle, ratio, mesh_name[mesh_style]);
} }
if (fp) fclose(fp);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------

View File

@ -54,7 +54,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) :
{ {
if (narg < 5) utils::missing_cmd_args(FLERR,"fix adapt", error); if (narg < 5) utils::missing_cmd_args(FLERR,"fix adapt", error);
nevery = utils::inumeric(FLERR,arg[3],false,lmp); nevery = utils::inumeric(FLERR,arg[3],false,lmp);
if (nevery < 0) error->all(FLERR,"Illegal fix adapt every value {}", nevery); if (nevery < 0) error->all(FLERR, 3, "Illegal fix adapt every value {}", nevery);
dynamic_group_allow = 1; dynamic_group_allow = 1;
create_attribute = 1; create_attribute = 1;
@ -92,7 +92,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) :
} else break; } else break;
} }
if (nadapt == 0) error->all(FLERR,"Nothing to adapt in fix adapt command"); if (nadapt == 0) error->all(FLERR, 3, "Nothing to adapt in fix adapt command");
adapt = new Adapt[nadapt]; adapt = new Adapt[nadapt];
// parse keywords // parse keywords
@ -125,7 +125,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) :
if (utils::strmatch(arg[iarg+5],"^v_")) { if (utils::strmatch(arg[iarg+5],"^v_")) {
adapt[nadapt].var = utils::strdup(arg[iarg+5]+2); adapt[nadapt].var = utils::strdup(arg[iarg+5]+2);
} else error->all(FLERR,"Argument #{} must be variable not {}", iarg+6, arg[iarg+5]); } else error->all(FLERR, iarg+5, "Argument must be variable not {}", arg[iarg+5]);
nadapt++; nadapt++;
iarg += 6; iarg += 6;
@ -138,7 +138,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) :
adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::BOND); adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::BOND);
if (utils::strmatch(arg[iarg+4],"^v_")) { if (utils::strmatch(arg[iarg+4],"^v_")) {
adapt[nadapt].var = utils::strdup(arg[iarg+4]+2); adapt[nadapt].var = utils::strdup(arg[iarg+4]+2);
} else error->all(FLERR,"Argument #{} must be variable not {}", iarg+5, arg[iarg+4]); } else error->all(FLERR, iarg+4, "Argument must be variable not {}", arg[iarg+4]);
nadapt++; nadapt++;
iarg += 5; iarg += 5;
@ -151,7 +151,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) :
adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::ANGLE); adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::ANGLE);
if (utils::strmatch(arg[iarg+4],"^v_")) { if (utils::strmatch(arg[iarg+4],"^v_")) {
adapt[nadapt].var = utils::strdup(arg[iarg+4]+2); adapt[nadapt].var = utils::strdup(arg[iarg+4]+2);
} else error->all(FLERR,"Argument #{} must be variable not {}", iarg+5, arg[iarg+4]); } else error->all(FLERR,iarg+4, "Argument must be variable not {}", arg[iarg+4]);
nadapt++; nadapt++;
iarg += 5; iarg += 5;
@ -172,7 +172,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) :
adapt[nadapt].which = KSPACE; adapt[nadapt].which = KSPACE;
if (utils::strmatch(arg[iarg+1],"^v_")) { if (utils::strmatch(arg[iarg+1],"^v_")) {
adapt[nadapt].var = utils::strdup(arg[iarg+1]+2); adapt[nadapt].var = utils::strdup(arg[iarg+1]+2);
} else error->all(FLERR,"Argument #{} must be variable not {}", iarg+2, arg[iarg+1]); } else error->all(FLERR, iarg+1, "Argument must be variable not {}", arg[iarg+1]);
nadapt++; nadapt++;
iarg += 2; iarg += 2;
@ -187,10 +187,11 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) :
} else if (strcmp(arg[iarg+1],"charge") == 0) { } else if (strcmp(arg[iarg+1],"charge") == 0) {
adapt[nadapt].atomparam = CHARGE; adapt[nadapt].atomparam = CHARGE;
chgflag = 1; chgflag = 1;
} else error->all(FLERR,"Unsupported per-atom property {} for fix adapt", arg[iarg+1]); } else error->all(FLERR, iarg+1, "Unsupported per-atom property {} for fix adapt",
arg[iarg+1]);
if (utils::strmatch(arg[iarg+2],"^v_")) { if (utils::strmatch(arg[iarg+2],"^v_")) {
adapt[nadapt].var = utils::strdup(arg[iarg+2]+2); adapt[nadapt].var = utils::strdup(arg[iarg+2]+2);
} else error->all(FLERR,"Argument #{} must be variable not {}", iarg+3, arg[iarg+2]); } else error->all(FLERR, iarg+2, "Argument must be variable not {}", arg[iarg+2]);
nadapt++; nadapt++;
iarg += 3; iarg += 3;
} else break; } else break;
@ -359,7 +360,8 @@ void FixAdapt::init()
if (group->dynamic[igroup]) if (group->dynamic[igroup])
for (i = 0; i < nadapt; i++) for (i = 0; i < nadapt; i++)
if (adapt[i].which == ATOM) if (adapt[i].which == ATOM)
error->all(FLERR,"Cannot use dynamic group {} with fix adapt atom", group->names[igroup]); error->all(FLERR, Error::NOLASTLINE,
"Cannot use dynamic group {} with fix adapt atom", group->names[igroup]);
// setup and error checks // setup and error checks
@ -373,9 +375,11 @@ void FixAdapt::init()
ad->ivar = input->variable->find(ad->var); ad->ivar = input->variable->find(ad->var);
if (ad->ivar < 0) if (ad->ivar < 0)
error->all(FLERR,"Variable name {} for fix adapt does not exist", ad->var); error->all(FLERR, Error::NOLASTLINE,
"Variable name {} for fix adapt does not exist", ad->var);
if (!input->variable->equalstyle(ad->ivar)) if (!input->variable->equalstyle(ad->ivar))
error->all(FLERR,"Variable {} for fix adapt is invalid style", ad->var); error->all(FLERR, Error::NOLASTLINE,
"Variable {} for fix adapt is invalid style", ad->var);
if (ad->which == PAIR) { if (ad->which == PAIR) {
anypair = 1; anypair = 1;
@ -400,17 +404,20 @@ void FixAdapt::init()
ad->pair = force->pair_match(fmt::format("{}/{}",pstyle,lmp->suffix2),1,nsub); ad->pair = force->pair_match(fmt::format("{}/{}",pstyle,lmp->suffix2),1,nsub);
} }
if (ad->pair == nullptr) ad->pair = force->pair_match(pstyle,1,nsub); if (ad->pair == nullptr) ad->pair = force->pair_match(pstyle,1,nsub);
if (ad->pair == nullptr) error->all(FLERR,"Fix adapt pair style {} not found", pstyle); if (ad->pair == nullptr)
error->all(FLERR, Error::NOLASTLINE, "Fix adapt pair style {} not found", pstyle);
void *ptr = ad->pair->extract(ad->pparam,ad->pdim); void *ptr = ad->pair->extract(ad->pparam,ad->pdim);
if (ptr == nullptr) if (ptr == nullptr)
error->all(FLERR,"Fix adapt pair style {} param {} not supported", ad->pstyle, ad->pparam); error->all(FLERR, Error::NOLASTLINE,
"Fix adapt pair style {} param {} not supported", ad->pstyle, ad->pparam);
// for pair styles only parameters that are 2-d arrays in atom types or // for pair styles only parameters that are 2-d arrays in atom types or
// scalars are supported // scalars are supported
if (ad->pdim != 2 && ad->pdim != 0) if (ad->pdim != 2 && ad->pdim != 0)
error->all(FLERR,"Pair style parameter {} is not compatible with fix adapt", ad->pparam); error->all(FLERR, Error::NOLASTLINE,
"Pair style parameter {} is not compatible with fix adapt", ad->pparam);
if (ad->pdim == 2) ad->array = (double **) ptr; if (ad->pdim == 2) ad->array = (double **) ptr;
if (ad->pdim == 0) ad->scalar = (double *) ptr; if (ad->pdim == 0) ad->scalar = (double *) ptr;
@ -423,7 +430,7 @@ void FixAdapt::init()
for (i = ad->ilo; i <= ad->ihi; i++) { for (i = ad->ilo; i <= ad->ihi; i++) {
for (j = MAX(ad->jlo,i); j <= ad->jhi; j++) { for (j = MAX(ad->jlo,i); j <= ad->jhi; j++) {
if (!pair->check_ijtype(i,j,pstyle)) if (!pair->check_ijtype(i,j,pstyle))
error->all(FLERR,"Fix adapt type pair range is not valid " error->all(FLERR, Error::NOLASTLINE, "Fix adapt type pair range is not valid "
"for pair hybrid sub-style {}", pstyle); "for pair hybrid sub-style {}", pstyle);
} }
} }
@ -442,12 +449,13 @@ void FixAdapt::init()
if (ad->bond == nullptr) ad->bond = force->bond_match(bstyle); if (ad->bond == nullptr) ad->bond = force->bond_match(bstyle);
if (ad->bond == nullptr ) if (ad->bond == nullptr )
error->all(FLERR,"Fix adapt bond style {} does not exist", bstyle); error->all(FLERR, Error::NOLASTLINE,"Fix adapt bond style {} does not exist", bstyle);
void *ptr = ad->bond->extract(ad->bparam,ad->bdim); void *ptr = ad->bond->extract(ad->bparam,ad->bdim);
if (ptr == nullptr) if (ptr == nullptr)
error->all(FLERR,"Fix adapt bond style parameter {} not supported", ad->bparam); error->all(FLERR, Error::NOLASTLINE,
"Fix adapt bond style parameter {} not supported", ad->bparam);
// for bond styles, use a vector // for bond styles, use a vector
@ -458,8 +466,8 @@ void FixAdapt::init()
if (bond) { if (bond) {
for (i = ad->ilo; i <= ad->ihi; i++) { for (i = ad->ilo; i <= ad->ihi; i++) {
if (!bond->check_itype(i,bstyle)) if (!bond->check_itype(i,bstyle))
error->all(FLERR,"Fix adapt type bond range is not valid " error->all(FLERR, Error::NOLASTLINE, "Fix adapt type bond range is not valid "
"for pair hybrid sub-style {}", bstyle); "for bond hybrid sub-style {}", bstyle);
} }
} }
} }
@ -476,12 +484,13 @@ void FixAdapt::init()
if (ad->angle == nullptr) ad->angle = force->angle_match(astyle); if (ad->angle == nullptr) ad->angle = force->angle_match(astyle);
if (ad->angle == nullptr ) if (ad->angle == nullptr )
error->all(FLERR,"Fix adapt angle style {} does not exist", astyle); error->all(FLERR, Error::NOLASTLINE, "Fix adapt angle style {} does not exist", astyle);
void *ptr = ad->angle->extract(ad->aparam,ad->adim); void *ptr = ad->angle->extract(ad->aparam,ad->adim);
if (ptr == nullptr) if (ptr == nullptr)
error->all(FLERR,"Fix adapt angle style parameter {} not supported", ad->aparam); error->all(FLERR, Error::NOLASTLINE,
"Fix adapt angle style parameter {} not supported", ad->aparam);
// for angle styles, use a vector // for angle styles, use a vector
@ -492,8 +501,8 @@ void FixAdapt::init()
if (angle) { if (angle) {
for (i = ad->ilo; i <= ad->ihi; i++) { for (i = ad->ilo; i <= ad->ihi; i++) {
if (!angle->check_itype(i,astyle)) if (!angle->check_itype(i,astyle))
error->all(FLERR,"Fix adapt type angle range is not valid " error->all(FLERR, Error::NOLASTLINE, "Fix adapt type angle range is not valid "
"for pair hybrid sub-style {}", astyle); "for angle hybrid sub-style {}", astyle);
} }
} }
} }
@ -536,22 +545,23 @@ void FixAdapt::init()
} else if (ad->which == KSPACE) { } else if (ad->which == KSPACE) {
if (force->kspace == nullptr) if (force->kspace == nullptr)
error->all(FLERR,"Fix adapt expected a kspace style but none was defined"); error->all(FLERR, Error::NOLASTLINE,
"Fix adapt expected a kspace style but none was defined");
kspace_scale = (double *) force->kspace->extract("scale"); kspace_scale = (double *) force->kspace->extract("scale");
} else if (ad->which == ATOM) { } else if (ad->which == ATOM) {
if (ad->atomparam == DIAMETER) { if (ad->atomparam == DIAMETER) {
if (!atom->radius_flag) if (!atom->radius_flag)
error->all(FLERR,"Fix adapt requires atom attribute diameter"); error->all(FLERR, Error::NOLASTLINE, "Fix adapt requires atom attribute diameter");
if (!atom->rmass_flag) if (!atom->rmass_flag)
error->all(FLERR,"Fix adapt requires atom attribute mass"); error->all(FLERR, Error::NOLASTLINE, "Fix adapt requires atom attribute mass");
if (discflag && domain->dimension != 2) if (discflag && domain->dimension != 2)
error->all(FLERR,"Fix adapt requires 2d simulation"); error->all(FLERR, Error::NOLASTLINE, "Fix adapt requires 2d simulation");
if (!restart_reset) previous_diam_scale = 1.0; if (!restart_reset) previous_diam_scale = 1.0;
} }
if (ad->atomparam == CHARGE) { if (ad->atomparam == CHARGE) {
if (!atom->q_flag) if (!atom->q_flag)
error->all(FLERR,"Fix adapt requires atom attribute charge"); error->all(FLERR, Error::NOLASTLINE, "Fix adapt requires atom attribute charge");
if (!restart_reset) previous_chg_scale = 1.0; if (!restart_reset) previous_chg_scale = 1.0;
} }
} }
@ -589,11 +599,15 @@ void FixAdapt::init()
if (id_fix_diam) { if (id_fix_diam) {
fix_diam = dynamic_cast<FixStoreAtom *>(modify->get_fix_by_id(id_fix_diam)); fix_diam = dynamic_cast<FixStoreAtom *>(modify->get_fix_by_id(id_fix_diam));
if (!fix_diam) error->all(FLERR,"Could not find fix adapt storage fix ID {}", id_fix_diam); if (!fix_diam)
error->all(FLERR, Error::NOLASTLINE,
"Could not find fix adapt storage fix ID {}", id_fix_diam);
} }
if (id_fix_chg) { if (id_fix_chg) {
fix_chg = dynamic_cast<FixStoreAtom *>(modify->get_fix_by_id(id_fix_chg)); fix_chg = dynamic_cast<FixStoreAtom *>(modify->get_fix_by_id(id_fix_chg));
if (!fix_chg) error->all(FLERR,"Could not find fix adapt storage fix ID {}", id_fix_chg); if (!fix_chg)
error->all(FLERR, Error::NOLASTLINE,
"Could not find fix adapt storage fix ID {}", id_fix_chg);
} }
if (utils::strmatch(update->integrate_style,"^respa")) if (utils::strmatch(update->integrate_style,"^respa"))

View File

@ -65,27 +65,39 @@ void Region::init()
{ {
if (xstr) { if (xstr) {
xvar = input->variable->find(xstr); xvar = input->variable->find(xstr);
if (xvar < 0) error->all(FLERR, "Variable {} for region does not exist", xstr); if (xvar < 0)
error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} does not exist", xstr,
style, id);
if (!input->variable->equalstyle(xvar)) if (!input->variable->equalstyle(xvar))
error->all(FLERR, "Variable {} for region is invalid style", xstr); error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} is invalid style", xstr,
style, id);
} }
if (ystr) { if (ystr) {
yvar = input->variable->find(ystr); yvar = input->variable->find(ystr);
if (yvar < 0) error->all(FLERR, "Variable {} for region does not exist", ystr); if (yvar < 0)
error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} does not exist", ystr,
style, id);
if (!input->variable->equalstyle(yvar)) if (!input->variable->equalstyle(yvar))
error->all(FLERR, "Variable {} for region is not equal style", ystr); error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} is not equal style", ystr,
style, id);
} }
if (zstr) { if (zstr) {
zvar = input->variable->find(zstr); zvar = input->variable->find(zstr);
if (zvar < 0) error->all(FLERR, "Variable {} for region does not exist", zstr); if (zvar < 0)
error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} does not exist", zstr,
style, id);
if (!input->variable->equalstyle(zvar)) if (!input->variable->equalstyle(zvar))
error->all(FLERR, "Variable {} for region is not equal style", zstr); error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} is not equal style", zstr,
style, id);
} }
if (tstr) { if (tstr) {
tvar = input->variable->find(tstr); tvar = input->variable->find(tstr);
if (tvar < 0) error->all(FLERR, "Variable {} for region does not exist", tstr); if (tvar < 0)
error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} does not exist", tstr,
style, id);
if (!input->variable->equalstyle(tvar)) if (!input->variable->equalstyle(tvar))
error->all(FLERR, "Variable {} for region is not equal style", tstr); error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} is not equal style", tstr,
style, id);
} }
vel_timestep = -1; vel_timestep = -1;
} }
@ -303,6 +315,16 @@ void Region::options(int narg, char **arg)
{ {
if (narg < 0) utils::missing_cmd_args(FLERR, "region", error); if (narg < 0) utils::missing_cmd_args(FLERR, "region", error);
int offset = -20;
if (input && input->arg && arg) {
for (int i = 0; i < input->narg; ++i) {
if (arg[0] == input->arg[i]) {
offset = i;
break;
}
}
}
// option defaults // option defaults
interior = 1; interior = 1;
@ -321,7 +343,7 @@ void Region::options(int narg, char **arg)
else if (strcmp(arg[iarg + 1], "lattice") == 0) else if (strcmp(arg[iarg + 1], "lattice") == 0)
scaleflag = 1; scaleflag = 1;
else else
error->all(FLERR, "Illegal region units: {}", arg[iarg + 1]); error->all(FLERR, iarg + 1 + offset, "Unknown region units: {}", arg[iarg + 1]);
iarg += 2; iarg += 2;
} else if (strcmp(arg[iarg], "side") == 0) { } else if (strcmp(arg[iarg], "side") == 0) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "region side", error); if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "region side", error);
@ -330,24 +352,27 @@ void Region::options(int narg, char **arg)
else if (strcmp(arg[iarg + 1], "out") == 0) else if (strcmp(arg[iarg + 1], "out") == 0)
interior = 0; interior = 0;
else else
error->all(FLERR, "Illegal region side: {}", arg[iarg + 1]); error->all(FLERR, iarg + 1 + offset, "Unknown region side setting: {}", arg[iarg + 1]);
iarg += 2; iarg += 2;
} else if (strcmp(arg[iarg], "move") == 0) { } else if (strcmp(arg[iarg], "move") == 0) {
if (iarg + 4 > narg) utils::missing_cmd_args(FLERR, "region move", error); if (iarg + 4 > narg) utils::missing_cmd_args(FLERR, "region move", error);
if (strcmp(arg[iarg + 1], "NULL") != 0) { if (strcmp(arg[iarg + 1], "NULL") != 0) {
if (strstr(arg[iarg + 1], "v_") != arg[iarg + 1]) if (strstr(arg[iarg + 1], "v_") != arg[iarg + 1])
error->all(FLERR, "Illegal region move x displacement variable: {}", arg[iarg + 1]); error->all(FLERR, iarg + 1 + offset, "Illegal region move x displacement variable: {}",
arg[iarg + 1]);
xstr = utils::strdup(&arg[iarg + 1][2]); xstr = utils::strdup(&arg[iarg + 1][2]);
} }
if (strcmp(arg[iarg + 2], "NULL") != 0) { if (strcmp(arg[iarg + 2], "NULL") != 0) {
if (strstr(arg[iarg + 2], "v_") != arg[iarg + 2]) if (strstr(arg[iarg + 2], "v_") != arg[iarg + 2])
error->all(FLERR, "Illegal region move y displacement variable: {}", arg[iarg + 2]); error->all(FLERR, iarg + 2 + offset, "Illegal region move y displacement variable: {}",
arg[iarg + 2]);
ystr = utils::strdup(&arg[iarg + 2][2]); ystr = utils::strdup(&arg[iarg + 2][2]);
} }
if (strcmp(arg[iarg + 3], "NULL") != 0) { if (strcmp(arg[iarg + 3], "NULL") != 0) {
if (strstr(arg[iarg + 3], "v_") != arg[iarg + 3]) if (strstr(arg[iarg + 3], "v_") != arg[iarg + 3])
error->all(FLERR, "Illegal region move z displacement variable: {}", arg[iarg + 3]); error->all(FLERR, iarg + 3 + offset, "Illegal region move z displacement variable: {}",
arg[iarg + 3]);
zstr = utils::strdup(&arg[iarg + 3][2]); zstr = utils::strdup(&arg[iarg + 3][2]);
} }
moveflag = 1; moveflag = 1;
@ -369,19 +394,20 @@ void Region::options(int narg, char **arg)
} else if (strcmp(arg[iarg], "open") == 0) { } else if (strcmp(arg[iarg], "open") == 0) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "region open", error); if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "region open", error);
int iface = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); int iface = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
if (iface < 1 || iface > 6) error->all(FLERR, "Illegal region open face index: {}", iface); if (iface < 1 || iface > 6)
error->all(FLERR, iarg + 1 + offset, "Illegal region open face index: {}", iface);
// additional checks on valid face index are done by region classes // additional checks on valid face index are done by region classes
open_faces[iface - 1] = 1; open_faces[iface - 1] = 1;
openflag = 1; openflag = 1;
iarg += 2; iarg += 2;
} else } else
error->all(FLERR, "Illegal region command argument: {}", arg[iarg]); error->all(FLERR, iarg + offset, "Unknown region command argument: {}", arg[iarg]);
} }
// error check // error check
if ((moveflag || rotateflag) && (strcmp(style, "union") == 0 || strcmp(style, "intersect") == 0)) if ((moveflag || rotateflag) && (strcmp(style, "union") == 0 || strcmp(style, "intersect") == 0))
error->all(FLERR, "Region union or intersect cannot be dynamic"); error->all(FLERR, 1, "Region union or intersect cannot be dynamic");
// setup scaling // setup scaling
@ -402,7 +428,7 @@ void Region::options(int narg, char **arg)
if (rotateflag) { if (rotateflag) {
double len = sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]); double len = sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
if (len == 0.0) error->all(FLERR, "Region cannot have 0 length rotation vector"); if (len == 0.0) error->all(FLERR, Error::NOPOINTER, "Region cannot have 0 length rotation vector");
runit[0] = axis[0] / len; runit[0] = axis[0] / len;
runit[1] = axis[1] / len; runit[1] = axis[1] / len;
runit[2] = axis[2] / len; runit[2] = axis[2] / len;

View File

@ -26,6 +26,7 @@ namespace LAMMPS_NS {
class RegBlock : public Region { class RegBlock : public Region {
friend class FixPour; friend class FixPour;
friend class Region2VMD;
public: public:
RegBlock(class LAMMPS *, int, char **); RegBlock(class LAMMPS *, int, char **);

View File

@ -41,10 +41,11 @@ RegCone::RegCone(LAMMPS *lmp, int narg, char **arg) :
if (openflag) if (openflag)
for (int i = 3; i < 6; i++) for (int i = 3; i < 6; i++)
if (open_faces[i]) error->all(FLERR, "Illegal region cone open face: {}", i + 1); if (open_faces[i])
error->all(FLERR, Error::NOPOINTER, "Illegal region cone open face: {}", i + 1);
if (strcmp(arg[2], "x") != 0 && strcmp(arg[2], "y") != 0 && strcmp(arg[2], "z") != 0) if (strcmp(arg[2], "x") != 0 && strcmp(arg[2], "y") != 0 && strcmp(arg[2], "z") != 0)
error->all(FLERR, "Illegal region cone axis: {}", arg[2]); error->all(FLERR, 2, "Illegal region cone axis: {}", arg[2]);
axis = arg[2][0]; axis = arg[2][0];
if (axis == 'x') { if (axis == 'x') {
@ -256,8 +257,8 @@ RegCone::RegCone(LAMMPS *lmp, int narg, char **arg) :
// error check // error check
if (radiuslo < 0.0) error->all(FLERR, "Illegal radius in region cone command"); if (radiuslo < 0.0) error->all(FLERR, 5, "Illegal lower radius in region cone command");
if (radiushi < 0.0) error->all(FLERR, "Illegal radius in region cone command"); if (radiushi < 0.0) error->all(FLERR, 6, "Illegal upper radius in region cone command");
if (radiuslo == 0.0 && radiushi == 0.0) if (radiuslo == 0.0 && radiushi == 0.0)
error->all(FLERR, "Illegal radius in region cone command"); error->all(FLERR, "Illegal radius in region cone command");
if (hi <= lo) error->all(FLERR, "Illegal cone length in region cone command"); if (hi <= lo) error->all(FLERR, "Illegal cone length in region cone command");

View File

@ -25,6 +25,8 @@ RegionStyle(cone,RegCone);
namespace LAMMPS_NS { namespace LAMMPS_NS {
class RegCone : public Region { class RegCone : public Region {
friend class Region2VMD;
public: public:
RegCone(class LAMMPS *, int, char **); RegCone(class LAMMPS *, int, char **);
~RegCone() override; ~RegCone() override;

View File

@ -26,6 +26,7 @@ namespace LAMMPS_NS {
class RegCylinder : public Region { class RegCylinder : public Region {
friend class FixPour; friend class FixPour;
friend class Region2VMD;
public: public:
RegCylinder(class LAMMPS *, int, char **); RegCylinder(class LAMMPS *, int, char **);

View File

@ -25,6 +25,8 @@ RegionStyle(ellipsoid,RegEllipsoid);
namespace LAMMPS_NS { namespace LAMMPS_NS {
class RegEllipsoid : public Region { class RegEllipsoid : public Region {
friend class Region2VMD;
public: public:
RegEllipsoid(class LAMMPS *, int, char **); RegEllipsoid(class LAMMPS *, int, char **);
~RegEllipsoid() override; ~RegEllipsoid() override;

View File

@ -25,6 +25,8 @@ RegionStyle(plane,RegPlane);
namespace LAMMPS_NS { namespace LAMMPS_NS {
class RegPlane : public Region { class RegPlane : public Region {
friend class Region2VMD;
public: public:
RegPlane(class LAMMPS *, int, char **); RegPlane(class LAMMPS *, int, char **);
~RegPlane() override; ~RegPlane() override;

View File

@ -26,6 +26,7 @@ namespace LAMMPS_NS {
class RegPrism : public Region { class RegPrism : public Region {
friend class CreateBox; friend class CreateBox;
friend class Region2VMD;
public: public:
RegPrism(class LAMMPS *, int, char **); RegPrism(class LAMMPS *, int, char **);

View File

@ -23,8 +23,9 @@ RegionStyle(sphere,RegSphere);
#include "region.h" #include "region.h"
namespace LAMMPS_NS { namespace LAMMPS_NS {
class RegSphere : public Region { class RegSphere : public Region {
friend class Region2VMD;
public: public:
RegSphere(class LAMMPS *, int, char **); RegSphere(class LAMMPS *, int, char **);
~RegSphere() override; ~RegSphere() override;

61
src/safe_pointers.h Normal file
View File

@ -0,0 +1,61 @@
/* -*- 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.
------------------------------------------------------------------------- */
#ifndef LMP_SAFE_POINTERS_H
#define LMP_SAFE_POINTERS_H
// collection of smart pointers for specific purposes
#include <cstdio>
#include <utility>
namespace LAMMPS_NS {
/** Class to automatically close a FILE pointer when a class instance goes out of scope.
\verbatim embed:rst
Drop in replacement for ``FILE *``. Use as ``SafeFilePtr fp;`` instead of
``FILE *fp = nullptr;`` and there is no more need to explicitly call
``fclose(fp)``.
\endverbatim
*/
class SafeFilePtr {
public:
SafeFilePtr() : fp(nullptr) {};
SafeFilePtr(FILE *_fp) : fp(_fp) {};
SafeFilePtr(const SafeFilePtr &) = delete;
SafeFilePtr(SafeFilePtr &&o) noexcept : fp(std::exchange(o.fp, nullptr)) {}
SafeFilePtr &operator=(const SafeFilePtr &) = delete;
~SafeFilePtr()
{
if (fp) fclose(fp);
}
SafeFilePtr &operator=(FILE *_fp)
{
if (fp && (fp != _fp)) fclose(fp);
fp = _fp;
return *this;
}
operator FILE *() const { return fp; }
private:
FILE *fp;
};
} // namespace LAMMPS_NS
#endif

View File

@ -26,6 +26,7 @@
namespace LAMMPS_NS { namespace LAMMPS_NS {
class TextFileReader { class TextFileReader {
private:
std::string filetype; std::string filetype;
bool closefp; bool closefp;
int bufsize; int bufsize;

View File

@ -1 +1,2 @@
#define LAMMPS_VERSION "4 Feb 2025" #define LAMMPS_VERSION "4 Feb 2025"
#define LAMMPS_UPDATE "Development"

View File

@ -279,7 +279,7 @@ if(APPLE)
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE_ICON_FILE lammps.icns MACOSX_BUNDLE_ICON_FILE lammps.icns
MACOSX_BUNDLE_COPYRIGHT "(c) 2003 - 2024, The LAMMPS Developers" MACOSX_BUNDLE_COPYRIGHT "(c) 2003 - 2025, The LAMMPS Developers"
MACOSX_BUNDLE TRUE MACOSX_BUNDLE TRUE
) )
# additional targets to populate the bundle tree and create the .dmg image file # additional targets to populate the bundle tree and create the .dmg image file

View File

@ -1,6 +1,6 @@
# Apptainer (aka Singularity) container definitions for compiling/testing LAMMPS # Apptainer (aka Singularity) container definitions for compiling/testing LAMMPS
The *.def files in this folder can be used to build container images The \*.def files in this folder can be used to build container images
for [Apptainer](https://apptainer.org) (previously called for [Apptainer](https://apptainer.org) (previously called
[Singularity](https://sylabs.io)), suitable for compiling and testing [Singularity](https://sylabs.io)), suitable for compiling and testing
LAMMPS on a variety of OS variants with support for most standard LAMMPS on a variety of OS variants with support for most standard

View File

@ -0,0 +1,109 @@
BootStrap: docker
From: fedora:41
%setup
curl -L -o musl-gcc-f37.tar.gz https://download.lammps.org/static/musl-gcc-f37.tar.gz
cp musl-gcc-f37.tar.gz ${APPTAINER_ROOTFS}
%post
dnf -y update
dnf -y install vim-enhanced git file make cmake patch which file \
ninja-build libomp-devel diffutils dos2unix findutils rsync \
ccache gcc-c++ gcc-gfortran gdb valgrind python3-pyyaml \
enchant enchant2 python3-enchant python3-virtualenv doxygen latexmk \
texlive-latex-fonts texlive-pslatex texlive-collection-latexrecommended \
texlive-latex texlive-latexconfig doxygen-latex texlive-collection-latex \
texlive-latex-bin texlive-lualatex-math texlive-fncychap texlive-tabulary \
texlive-framed texlive-wrapfig texlive-upquote texlive-capt-of texlive-pict2e \
texlive-needspace texlive-titlesec texlive-anysize texlive-dvipng texlive-xindy \
texlive-fontawesome texlive-ellipse texlive-tex-gyre \
mingw-filesystem-base mingw32-nsis mingw-binutils-generic \
mingw64-filesystem mingw64-pkg-config \
mingw64-crt mingw64-headers mingw64-binutils \
mingw64-cpp mingw64-gcc mingw64-gcc-gfortran mingw64-gcc-c++ \
mingw64-curl \
mingw64-libgomp \
mingw64-winpthreads \
mingw64-eigen3 \
mingw64-fftw \
mingw64-libjpeg-turbo \
mingw64-libpng \
mingw64-python3 \
mingw64-python3-numpy \
mingw64-python3-pyyaml \
mingw64-python3-setuptools \
mingw64-readline \
mingw64-termcap \
mingw64-tcl \
mingw64-tk \
mingw64-zlib \
mingw64-zstd \
mingw64-qt5-qtdeclarative \
mingw64-qt5-qmldevtools \
mingw64-qt5-qmldevtools-devel \
mingw64-qt5-qttools-tools \
mingw64-qt5-qtcharts \
mingw64-qt5-qttools \
mingw64-qt5-qmake \
mingw64-qt5-qtbase \
mingw64-qt5-qtbase-devel \
mingw64-qt5-qtbase-static \
dnf clean all
# install musl-libc Linux-2-Linux cross-compiler
tar -C /usr/ -xvf /musl-gcc-f37.tar.gz
rm -f /musl-gcc-f37.tar.gz
# install NSIS EnVar plugin
curl -L -o EnVar_plugin.zip https://nsis.sourceforge.io/mediawiki/images/7/7f/EnVar_plugin.zip
unzip -d /usr/share/nsis EnVar_plugin.zip
rm EnVar_plugin.zip
# create missing termcap pkgconfig file
cat > /usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/termcap.pc <<EOF
prefix=/usr/x86_64-w64-mingw32/sys-root/mingw
exec_prefix=/usr/x86_64-w64-mingw32/sys-root/mingw
libdir=/usr/x86_64-w64-mingw32/sys-root/mingw/lib
includedir=/usr/x86_64-w64-mingw32/sys-root/mingw/include
Name: Termcap
Description: GNU/MinGW terminal feature database
URL: ftp://ftp.gnu.org/gnu/termcap/
Version: 1.3
Libs: -L\${libdir} -ltermcap
Cflags:
EOF
# set custom prompt indicating the container name
CUSTOM_PROMPT_ENV=/.singularity.d/env/99-zz_custom_prompt.sh
cat >$CUSTOM_PROMPT_ENV <<EOF
#!/bin/bash
PS1="[fedora41/musl-mingw:\u@\h] \W> "
EOF
chmod 755 $CUSTOM_PROMPT_ENV
%environment
# we need to reset any module variables
# inherited from the host.
unset __LMOD_REF_COUNT__LMFILES_
unset __LMOD_REF_COUNT_PATH
unset __LMOD_REF_COUNT_LD_LIBRARY_PATH
unset __LMOD_REF_COUNT_MANPATH
unset __LMOD_REF_COUNT_MODULEPATH
unset __LMOD_REF_COUNT_LOADEDMODULES
unset _LMFILES_
unset MODULEPATH
unset MODULESHOME
unset MODULEPATH_ROOT
unset LOADEDMODULES
unset LMOD_SYSTEM_DEFAULT_MODULES
. /etc/profile
# tell OpenMPI to not try using Infiniband
OMPI_MCA_btl="^openib"
# do not warn about unused components as this messes up testing
OMPI_MCA_btl_base_warn_component_unused="0"
export OMPI_MCA_btl OMPI_MCA_btl_base_warn_component_unused
%labels
Author akohlmey